Skip to content

Too aggresive C++23 static call operator optimization #67976

@shtanko-sv

Description

@shtanko-sv

Hello,

It looks like clang is too aggressive for C++23 static call optimization. Here is the simplified example of real code:

#include <functional>
#include <iostream>

template <typename Tag>
struct Wrapper {
    template <typename F, typename... Args>
    static void operator()(F&& callable, Args&&... args) {
        Invoke(std::forward<F>(callable), std::forward<Args>(args)...);
    }

    template <typename F, typename... Args>
    static void Invoke(F&& callable, Args&&... args) {
        std::invoke(std::forward<F>(callable), std::forward<Args>(args)...);
    }
};

struct Manager {
    template <typename SingletonClass>
    static SingletonClass& Get() {
        std::cout << "get call\n";
        static SingletonClass instance;
        return instance;
    }
};

struct Tag {};

int main()
{
    using TaggedWrapper = Wrapper<Tag>;
    Manager::Get<TaggedWrapper>()([] { std::cout << "Function\n"; });
}

We assume that Manager::Get() will be called and get call will be printed, but it doesn't happen. If change call in main to Manager::Get<TaggedWrapper>().Invoke([] { std::cout << "Function\n"; }); it works as expected. get cal also will be printed if remove static from operator(). It reproducible even with -O0. clang-17.0.1

Metadata

Metadata

Assignees

Labels

bugIndicates an unexpected problem or unintended behaviorc++23clang:codegenIR generation bugs: mangling, exceptions, etc.clang:frontendLanguage frontend issues, e.g. anything involving "Sema"

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions