Uploaded image for project: 'Core Server'
  1. Core Server
  2. SERVER-76921

toolchain v4 clang-format unaware of C++20 `requires` clauses

    • Type: Icon: Improvement Improvement
    • Resolution: Duplicate
    • Priority: Icon: Major - P3 Major - P3
    • None
    • Affects Version/s: None
    • Component/s: None
    • Labels:
      None
    • Server Development Platform

      I'm deploying C++20 `requires` clauses as expansions of the corresponding `concepts.h` macros.

      https://github.com/10gen/mongo/pull/12708

      As you can see in the PR, the `requires` clauses are not handled gracefully by our version of clang-format. This may be just our config options, but it's more likely that we will need a more modern version of clang-format for this C++20 feature.

      Example:

      What our clang-format.py produces:

      Incorrect indentation:

      template <typename Map>
          requires std::is_convertible_v<decltype(std::declval<Map>().begin()->first), StringData>
              Derived& append(StringData fieldName, const Map& map) {
      

      Merging requires clause with function signature:

         template <int...>
          requires(!std::is_same_v<int64_t, long long>) void appendNum(int64_t j) {
      

      It probably considers the `requires` clause to be grammatically part of the function's return type or something like that.

      Proper modern formatting (per https://gcc.godbolt.org/z/vabc8aqnr):

      template <typename A, typename B>
          requires(!(std::is_convertible_v<A, StringData> &&
                     std::is_convertible_v<B, StringData>) &&
                   !(std::is_pointer_v<A> && std::is_pointer_v<B>) &&
                   !(std::is_array_v<A> && std::is_array_v<B>))
      static ComparisonAssertion make(const char* theFile, unsigned theLine,
                                      StringData aExpression, StringData bExpression,
                                      const A& a, const B& b) {
          return ComparisonAssertion(theFile, theLine, aExpression, bExpression, a,
                                     b);
      }
      
      template <typename... Ps>
      class function_ref {
          template <typename T>
              requires(!std::is_function_v<std::remove_pointer_t<T>>)
          function_ref& operator=(T) = delete;
      };
      

            Assignee:
            backlog-server-devplatform [DO NOT ASSIGN] Backlog - Server Development Platform Team (SDP) (Inactive)
            Reporter:
            billy.donahue@mongodb.com Billy Donahue
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: