Skip to content

[clang][regression] lambda call in unevaluated context in generic lambda in template function fails from clang 15 onwards #114755

@wanghan02

Description

@wanghan02

Example code could be found below or on godbolt. clang 14, gcc and MSVC all compile fine. clang 15 onwards fail.

The problem is triggered only if tc_lazy is called in a template function and the lambda in tc_lazy is a generic lambda.

#include <type_traits>
#include <utility>

#define HYBRIDSTR(str) \
	[](auto t) constexpr noexcept -> decltype(auto) { \
		using ArgCharT = typename decltype(t)::type; \
		if constexpr(std::is_same<ArgCharT, char>::value) { \
			return str; \
		} else if constexpr(std::is_same<ArgCharT, wchar_t>::value) { \
			return L ## str; \
		} else if constexpr(std::is_same<ArgCharT, char16_t>::value) { \
			return u ## str; \
		} else { \
			static_assert(std::is_same<ArgCharT, char32_t>::value); \
			return U ## str; \
		} \
	}

namespace tc {
    template<typename T>
    constexpr std::conditional_t<
        std::is_rvalue_reference<T&&>::value,
        std::decay_t<T>,
        T
    > lvalue_or_decay(T&& t) {
        return std::forward<T>(t);
    }

	namespace make_lazy_adl {
		template<typename Func>
		struct make_lazy : Func {
			constexpr explicit make_lazy(Func func) noexcept : Func(std::move(func)) {}

			constexpr operator decltype(std::declval<Func const&>()())() const&& {
				return (*this)();
			}
		};
	}
	using make_lazy_adl::make_lazy;
	namespace lazy_detail {
		template<bool bReference, typename T>
		decltype(auto) lvalue_or_decay(T&& t) noexcept {
			if constexpr (bReference) {
				return tc::lvalue_or_decay(std::forward<T>(t));
			}
		}
	}
}

#define tc_lazy( ... ) tc::make_lazy([&](auto&&...) -> decltype(auto) { \
		if constexpr (std::is_reference<decltype((__VA_ARGS__))>::value) { \
			return tc::lazy_detail::lvalue_or_decay<std::is_reference<decltype((__VA_ARGS__))>::value>(__VA_ARGS__); \
		} else { \
			return __VA_ARGS__; \
		} \
	})

template<typename Char>
auto foo() {
    return tc_lazy(HYBRIDSTR("abc")(std::type_identity<Char>()))(); // fails in template function from clang 15 onwards
}

void bar() {
    tc_lazy(0)();
    tc_lazy(HYBRIDSTR("abc")(std::type_identity<char16_t>()))(); // compiles
    foo<char16_t>();
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    clang:frontendLanguage frontend issues, e.g. anything involving "Sema"diverges-from:gccDoes the clang frontend diverge from gcc on this issuediverges-from:msvcDoes the clang frontend diverge from msvc on this issuelambdaC++11 lambda expressionsneeds-reductionLarge reproducer that should be reduced into a simpler form

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions