https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103569
Bug ID: 103569 Summary: Type alias from result of lambda call in unevaluated context, used in template, is inconsistent Product: gcc Version: 11.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: tim.pavlic at minelab dot com.au Target Milestone: --- Code: ------------------------- #include <type_traits> template <typename T> using probably_unsigned = decltype([] { return std::make_unsigned_t<T>{}; }()); template <typename T> auto definitely_unsigned_helper() { return std::make_unsigned_t<T>{}; } template <typename T> using definitely_unsigned = decltype(definitely_unsigned_helper<T>()); static_assert(std::is_same_v<probably_unsigned<char>, unsigned char>); static_assert(std::is_same_v<probably_unsigned<short>, unsigned short>); static_assert(std::is_same_v<definitely_unsigned<char>, unsigned char>); static_assert(std::is_same_v<definitely_unsigned<short>, unsigned short>); void no_template_no_problem() { probably_unsigned<char> p; static_assert(std::is_same_v<decltype(p), unsigned char>); } template <typename T> void definitely_no_problem() { definitely_unsigned<T> d; static_assert(std::is_unsigned_v<decltype(d)>); } template <typename T> void problem() { probably_unsigned<T> p; static_assert(std::is_unsigned_v<decltype(p)>); // Always resolved as int!!! static_assert(std::is_same_v<int, decltype(p)>); // !!!!!! } int main() { problem<char>(); problem<short>(); problem<long>(); definitely_no_problem<char>(); definitely_no_problem<short>(); definitely_no_problem<long>(); } ------------------------ https://godbolt.org/z/bnbdsj3ar ------------------------ Observed behaviour: ------------------- The type alias based on the result of calling decltype() on the lambda invocation works correctly outside of a function template, but not inside. The static asserts at namespace level pass. But the static assert inside the problem() function, where it asserts the type is int, also passes! So the alias yields two results, depending on where it is. Expected behaviour: ------------------- I would expect the alias to give the same type, every time. Command line: ------------- -std=c++20 gcc -v output: -------------- Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-linux-gnu/11.1.0/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-bugurl=https://bugs.archlinux.org/ --enable-languages=c,c++,ada,fortran,go,lto,objc,obj-c++,d --with-isl --with-linker-hash-style=gnu --with-system-zlib --enable-__cxa_atexit --enable-cet=auto --enable-checking=release --enable-clocale=gnu --enable-default-pie --enable-default-ssp --enable-gnu-indirect-function --enable-gnu-unique-object --enable-install-libiberty --enable-linker-build-id --enable-lto --enable-multilib --enable-plugin --enable-shared --enable-threads=posix --disable-libssp --disable-libstdcxx-pch --disable-libunwind-exceptions --disable-werror gdc_include_dir=/usr/include/dlang/gdc Thread model: posix Supported LTO compression algorithms: zlib zstd gcc version 11.1.0 (GCC)