[Bug c++/93807] New: -std=c++2a allows to omit out-of-class declaration in template class
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93807 Bug ID: 93807 Summary: -std=c++2a allows to omit out-of-class declaration in template class Product: gcc Version: 9.2.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: bobogu at atlas dot cz Target Milestone: --- gcc -v: Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-linux-gnu/9.2.1/lto-wrapper Target: x86_64-pc-linux-gnu Configured with: /build/gcc/src/gcc/configure --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-pkgversion='Arch Linux 9.2.1+20200130-2' --with-bugurl=https://bugs.archlinux.org/ --enable-languages=c,c++,ada,fortran,go,lto,objc,obj-c++,d --enable-shared --enable-threads=posix --with-system-zlib --with-isl --enable-__cxa_atexit --disable-libunwind-exceptions --enable-clocale=gnu --disable-libstdcxx-pch --disable-libssp --enable-gnu-unique-object --enable-linker-build-id --enable-lto --enable-plugin --enable-install-libiberty --with-linker-hash-style=gnu --enable-gnu-indirect-function --enable-multilib --disable-werror --enable-checking=release --enable-default-pie --enable-default-ssp --enable-cet=auto gdc_include_dir=/usr/include/dlang/gdc Thread model: posix gcc version 9.2.1 20200130 (Arch Linux 9.2.1+20200130-2) Command line: gcc -lstdc++ -std=c++2a main.cpp With -std=c++2a, gcc allows me to omit out-of-class declaration of a friend member function in a template class: // template // class Foo; // template // constexpr bool operator==(T lhs, const Foo& rhs); template class Foo { public: constexpr Foo(T k) : mK(k) {} constexpr friend bool operator==(T lhs, const Foo& rhs); private: T mK; }; template constexpr bool operator==(T lhs, const Foo& rhs) { return lhs == rhs.mK; } int main() { return 1 == Foo(1) ? 0 : 1; } This code compiles just fine and the binary returns 0, although I didn't find anything in the C++20 standard that would allow us to omit the out-of-class declaration. I would expect this code to work only if the first 4 lines were uncommented. The same behaviour was also reproduced on a gcc 9.1.0. For reference, clang doesn't accept this code.
[Bug c++/87016] std::optional::operator= in constexpr context
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87016 --- Comment #9 from bobogu at atlas dot cz --- (In reply to Jonathan Wakely from comment #8) > (In reply to bobogu from comment #7) > > All right, I'm sorry then... I just thought that as this is undocumented, it > > could lead to producing an unportable code. > > It could, except that you should get the same behaviour for every correct > implementation. Your example doesn't compile with libc++, but that's a bug: > https://bugs.llvm.org/show_bug.cgi?id=38638 Yes, that was just my misconception before you got me on the right track - I thought clang's behaviour was correct because of what I saw in the standard :-)
[Bug c++/87016] std::optional::operator= in constexpr context
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87016 --- Comment #7 from bobogu at atlas dot cz --- (In reply to Jonathan Wakely from comment #5) > (In reply to bobogu from comment #4) > All implementations define the assignment operator as defaulted, and so the > compiler makes it constexpr. > > In fact the p0602R3 proposal you linked to is relevant, because it would > *require* implementations to define the operator as defaulted (in order to > be trivial) and so the compiler is always going to make it constexpr for > std::optional. Ah, finally it makes sense to me! > Anyway, I don't consider "I can use more things in constant expressions than > the standard says" to be a bug. All right, I'm sorry then... I just thought that as this is undocumented, it could lead to producing an unportable code. Anyway, thank you for clearing it out. > I've raised this with the standards committee. Thanks!
[Bug c++/87016] std::optional::operator= in constexpr context
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87016 --- Comment #4 from bobogu at atlas dot cz --- (In reply to Jonathan Wakely from comment #3) > (In reply to bobogu from comment #2) > When you assign an int to optional it is equivalent to constructing a > temporary optional and then assigning that to the left-hand operand. I feel stupid, but I still don't understand how that can work in a constexpr context when the current c++17 standard doesn't specify any constexpr assignment operator. The second line of this snippet std::optional bar = 3; bar = std::optional(10); would call the 3rd assignment operator (https://en.cppreference.com/w/cpp/utility/optional/operator%3D), right? And the operator isn't constexpr, but works in a constexpr function.
[Bug c++/87016] std::optional::operator= in constexpr context
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87016 --- Comment #2 from bobogu at atlas dot cz --- Do I understand it correctly that this will get optimized into one statement saying bar = std::optional(10); If so, is there something that could prevent such optimizations in order to check if the code is portable? Also, just to clarify, this has nothing to do with this proposal http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0602r3.html to which someone has pointed me to?
[Bug c++/87016] New: std::optional::operator= in constexpr context
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87016 Bug ID: 87016 Summary: std::optional::operator= in constexpr context Product: gcc Version: 8.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: bobogu at atlas dot cz Target Milestone: --- Created attachment 44558 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=44558&action=edit preprocessed TU According to the standard, there is no assignment operator that should work in a constexpr context, however, I am able to successfully compile and use the following snippet: // gcc -lstdc++ -std=c++17 main.cpp @Linux laptop 4.17.11-arch1 x86_64 constexpr std::optional foo() { std::optional bar = 3; bar = 10; return bar; }