Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[clang-format] Combining C++20 designated initializers and lambdas gets formatting messed up #55325

Closed
ifarbod opened this issue May 7, 2022 · 4 comments
Labels
bug Indicates an unexpected problem or unintended behavior clang-format

Comments

@ifarbod
Copy link

ifarbod commented May 7, 2022

This is the code I have:

#include <functional>
#include <iostream>

namespace zsl
{

template <typename T>
class Property
{
public:
    using Getter = std::function<const T&(T&)>;
    using Setter = std::function<void(T&, T)>;

    struct GetterSetter
    {
        Getter get;
        Setter set;
    };

    constexpr Property(T& ref, GetterSetter gettersetter =
        {
            .get = [](auto& var) constexpr { return var;},
            .set = [](auto& var, auto value) { var = value; }
        }) noexcept
        : m_ref(ref), m_gettersetter(gettersetter)
    {}

    constexpr operator T() const noexcept
    {
        return m_gettersetter.get == nullptr ? m_ref : m_gettersetter.get(m_ref);
    }

    constexpr T& operator=(T value) noexcept
    {
        if (m_gettersetter.set != nullptr)
        {
            m_gettersetter.set(m_ref, value);
        }

        return m_ref;
    }

private:
    T& m_ref;
    GetterSetter m_gettersetter;
};

}  // namespace zsl

class ProperyTest
{
public:
    zsl::Property<int> prop{m_something,
        {
            .get = [this](auto& var) constexpr
            {
                return var + 2;
            },
            .set = [this](auto& var, auto value) constexpr
            {
                var = value;
            }}};

private:
    int m_something = 0;
};

auto main(int argc, char** argv) -> int
{
    ProperyTest t;
    t.prop = 123;
    std::cout << t.prop;
    return 0;
}

What I get, after formatting with clang-format -i Code.cpp:

#include <functional>
#include <iostream>

namespace zsl {

template <typename T> class Property {
public:
  using Getter = std::function<const T &(T &)>;
  using Setter = std::function<void(T &, T)>;

  struct GetterSetter {
    Getter get;
    Setter set;
  };

    constexpr Property(T& ref, GetterSetter gettersetter =
        {
            .get = [](auto& var) constexpr { return var;
}, .set = [](auto &var, auto value) { var = value; }
} // namespace zsl
) noexcept
        : m_ref(ref), m_gettersetter(gettersetter)
    {}

constexpr operator T() const noexcept {
  return m_gettersetter.get == nullptr ? m_ref : m_gettersetter.get(m_ref);
}

constexpr T &operator=(T value) noexcept {
  if (m_gettersetter.set != nullptr) {
    m_gettersetter.set(m_ref, value);
  }

  return m_ref;
}

private:
T &m_ref;
GetterSetter m_gettersetter;
}
;

} // namespace zsl

class ProperyTest {
public:
  zsl::Property<int> prop{m_something,
                          {.get = [this](auto &var) constexpr {return var + 2;
}, .set = [this](auto &var, auto value) constexpr {
  var = value;
}
}
}
;

private:
int m_something = 0;
}
;

auto main(int argc, char **argv) -> int {
  ProperyTest t;
  t.prop = 123;
  std::cout << t.prop;
  return 0;
}

Notice the namespace comment in the middle of the namespace.

To reproduce, simply copy my input code and try to format it with any of the default styles, I tried WebKit and Microsoft but they look ugly too.

@llvmbot
Copy link
Collaborator

llvmbot commented May 7, 2022

@llvm/issue-subscribers-clang-format

@mkurdej
Copy link
Member

mkurdej commented May 9, 2022

Minimal repro (adding incorrect namespace comments):

namespace ns
{
class Class
{
    constexpr Class(Param param =
        {
            .get = [](auto& var) constexpr { return var;},
            .set = [](auto& var, auto value) { var = value; }
        })
    {}
};
}  // namespace ns

or (misformatted but no additional comment):

constexpr Class(Param param =
{
        .get = [](auto& var) constexpr { return var; },
        .set = [](auto& var, auto value) { var = value; }
})
{}

@mkurdej mkurdej added the bug Indicates an unexpected problem or unintended behavior label May 9, 2022
@llvmbot
Copy link
Collaborator

llvmbot commented May 9, 2022

@llvm/issue-subscribers-bug

@rymiel
Copy link
Member

rymiel commented Sep 15, 2022

This appears to be fixed by d2eda49, from what I can tell: (using -style='{}')

#include <functional>
#include <iostream>

namespace zsl {

template <typename T> class Property {
public:
  using Getter = std::function<const T &(T &)>;
  using Setter = std::function<void(T &, T)>;

  struct GetterSetter {
    Getter get;
    Setter set;
  };

  constexpr Property(T &ref,
                     GetterSetter gettersetter = {
                         .get = [](auto &var) constexpr { return var; },
                         .set = [](auto &var,
                                   auto value) { var = value; }}) noexcept
      : m_ref(ref), m_gettersetter(gettersetter) {}

  constexpr operator T() const noexcept {
    return m_gettersetter.get == nullptr ? m_ref : m_gettersetter.get(m_ref);
  }

  constexpr T &operator=(T value) noexcept {
    if (m_gettersetter.set != nullptr) {
      m_gettersetter.set(m_ref, value);
    }

    return m_ref;
  }

private:
  T &m_ref;
  GetterSetter m_gettersetter;
};

} // namespace zsl

class ProperyTest {
public:
  zsl::Property<int> prop{
      m_something,
      {.get = [this](auto &var) constexpr { return var + 2; },
       .set = [this](auto &var, auto value) constexpr { var = value; }}};

private:
  int m_something = 0;
};

auto main(int argc, char **argv) -> int {
  ProperyTest t;
  t.prop = 123;
  std::cout << t.prop;
  return 0;
}
namespace ns {
class Class {
  constexpr Class(Param param = {
                      .get = [](auto &var) constexpr { return var; },
                      .set = [](auto &var, auto value) { var = value; }}) {}
};
} // namespace ns
constexpr Class(Param param = {
                    .get = [](auto &var) constexpr { return var; },
                    .set = [](auto &var, auto value) { var = value; }}) {}

@ifarbod ifarbod closed this as completed Nov 28, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Indicates an unexpected problem or unintended behavior clang-format
Projects
None yet
Development

No branches or pull requests

5 participants