[SERVER-76921] toolchain v4 clang-format unaware of C++20 `requires` clauses Created: 08/May/23  Updated: 25/Aug/23  Resolved: 08/May/23

Status: Closed
Project: Core Server
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Improvement Priority: Major - P3
Reporter: Billy Donahue Assignee: [DO NOT ASSIGN] Backlog - Server Development Platform Team (SDP) (Inactive)
Resolution: Duplicate Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Duplicate
duplicates SERVER-76702 Upgrade clang-format to v15+ Backlog
Related
is related to SERVER-80409 [CQF] Improve compile-time error mess... Backlog
Assigned Teams:
Server Development Platform
Participants:

 Description   

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;
};


Generated at Thu Feb 08 06:34:00 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.