Skip to content

[concepts] Clang (11 to 16) crash when using generic lambda in template function #61589

@gracicot

Description

@gracicot

I tried reducing as much as possible, but clang seems very fragile on reproducing this issue:

#include <type_traits>
#include <utility>
#include <concepts>

#define FWD(...) static_cast<decltype(__VA_ARGS__)&&>(__VA_ARGS__)

template<typename F, typename... Args>
concept callable = requires(F&& f, Args&&... args) {
    FWD(f)(FWD(args)...);
};

template<typename T>
concept object = std::is_object_v<T>;

template<typename T>
concept constraint =
        object<T>
    and requires {
        requires std::same_as<typename T::tag, void>;
    };

struct member {
    using tag = void;
};

template<typename>
struct specialize {};

template<typename, typename, typename>
inline constexpr bool callbale_with_nth_parameter_being_expand = false;

template<typename T, typename F, typename S>
inline constexpr bool callbale_with_nth_parameter_being_expand<
    T, F,
    specialize<S>
> = callable<
    F,
    T
>;

template<typename T, typename F, typename>
concept callbale_with_nth_parameter_being = callbale_with_nth_parameter_being_expand<
    T, F,
    specialize<int>
>;

template<typename... Args>
inline constexpr auto invoke_impl(
    auto&& function,
    Args... args
) -> decltype(auto) {
	int arr[] = {0, callbale_with_nth_parameter_being<int, decltype(function), Args>...};
    return FWD(function)(args...);
}

template<constraint... Args>
inline constexpr auto invoke(callable<Args...> auto&& function, Args... args) -> decltype(auto) {
    return invoke_impl(FWD(function), args...);
}

struct my_type {
    member a;
};

template<typename... Functions>
struct overload : Functions... {
    using Functions::operator()...;
};

template<typename... Functions>
overload(Functions...) -> overload<Functions...>;

template<typename Type>
inline constexpr auto constructor() {
    auto const call_constructor = overload{
        [](int, auto&&... args) -> decltype(Type(FWD(args)...)) {
            return Type(FWD(args)...);
        },
        [](void*, auto&&... args) -> decltype(Type{FWD(args)...}) {
            return Type{FWD(args)...};
        },
    };
    return [call_constructor](auto&&... args) -> decltype(call_constructor(0, FWD(args)...)) {
        return call_constructor(0, FWD(args)...);
    };
}

auto main() -> int {
    invoke(constructor<my_type>(), member{});
}

Observations:

  • Removing the #include <utility> will make clang go into infinite loop
  • Changing template<constraint... Args> to template<typename... Args> will also make clang go into infinite loop
  • Changing the constaint concept in any way seem to fix the crash.
  • Changing the callable<Args...> auto&& function seems to fix the crash
  • Changing the callbale_with_nth_parameter_being_expand variable to not be specialized seems to fix the crash
  • Taking auto const call_constructor = overload{...} out of the constructor function seems to fix the crash
  • Inlining the object concept into constaint seems to fix the crash

Let me know if more information is needed to fix this issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    c++20clang:frontendLanguage frontend issues, e.g. anything involving "Sema"conceptsC++20 conceptsconfirmedVerified by a second partycrash-on-validworksformeResolved as "works for me"

    Type

    No type

    Projects

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions