Skip to content

Commit

Permalink
fix: explicitly disable several checks for clang-18.1
Browse files Browse the repository at this point in the history
  • Loading branch information
DNKpp committed Sep 25, 2024
1 parent 6d09f7a commit 5453228
Show file tree
Hide file tree
Showing 2 changed files with 212 additions and 33 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -209,3 +209,7 @@ The coverage is generated via ``gcov`` and evaluated by
| AppleClang-18.1.6 | - | x | x | x |

As new compilers become available, they will be added to the workflow, but older compilers will probably never be supported.

## Known Issues

* Clang-18.1 introduced a regression regarding the ``std::invocable`` concept and a default parameter of type ``std::source_location``. On this version, all invocable checks will fail. Clang-17 and Clang-19 do not suffer from this issue.
241 changes: 208 additions & 33 deletions test/unit-tests/Mock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,20 @@

using namespace mimicpp;

// This disables the std::invocable checks for Mocks, due to an issue on clang 18.1
// see: https://github.com/llvm/llvm-project/issues/106428
#if defined(__clang_major__) \
&& __clang_major__ == 18 \
&& __clang_minor__ == 1

#define CLANG_18_STD_INVOCABLE_REGRESSION

// Should fail, when the regression has been resolved.
// If so, enable the tests and remove the issue from the ``Known Issues`` section in the readme.
static_assert(!std::invocable<Mock<void()>>);

#endif

TEMPLATE_TEST_CASE(
"Mock is a non-copyable, but movable and default-constructible type.",
"[mock]",
Expand Down Expand Up @@ -66,23 +80,52 @@ TEMPLATE_TEST_CASE_SIG(
using NothrowMockT = Mock<signature_add_noexcept_t<Sig>>;

STATIC_REQUIRE(std::is_invocable_r_v<ReturnT, MockT, Args...>);
STATIC_REQUIRE(std::invocable<MockT, Args...>);
STATIC_REQUIRE(std::is_invocable_r_v<ReturnT, NothrowMockT, Args...>);
STATIC_REQUIRE(std::invocable<NothrowMockT, Args...>);

STATIC_REQUIRE(std::is_invocable_r_v<ReturnT, MockT&, Args...>);
STATIC_REQUIRE(std::invocable<MockT&, Args...>);
STATIC_REQUIRE(std::is_invocable_r_v<ReturnT, NothrowMockT&, Args...>);
STATIC_REQUIRE(std::invocable<NothrowMockT&, Args...>);

STATIC_REQUIRE(std::is_invocable_r_v<ReturnT, MockT&&, Args...>);
STATIC_REQUIRE(std::invocable<MockT&&, Args...>);
STATIC_REQUIRE(std::is_invocable_r_v<ReturnT, NothrowMockT&&, Args...>);

// negative checks

STATIC_REQUIRE(!std::is_invocable_r_v<ReturnT, const MockT, Args...>);
STATIC_REQUIRE(!std::is_invocable_r_v<ReturnT, const NothrowMockT, Args...>);

STATIC_REQUIRE(!std::is_invocable_r_v<ReturnT, const MockT&, Args...>);
STATIC_REQUIRE(!std::is_invocable_r_v<ReturnT, const NothrowMockT&, Args...>);

STATIC_REQUIRE(!std::is_invocable_r_v<ReturnT, const MockT&&, Args...>);
STATIC_REQUIRE(!std::is_invocable_r_v<ReturnT, const NothrowMockT&&, Args...>);

#ifndef CLANG_18_STD_INVOCABLE_REGRESSION

STATIC_REQUIRE(std::invocable<MockT, Args...>);
STATIC_REQUIRE(std::invocable<NothrowMockT, Args...>);

STATIC_REQUIRE(std::invocable<MockT&, Args...>);
STATIC_REQUIRE(std::invocable<NothrowMockT&, Args...>);

STATIC_REQUIRE(std::invocable<MockT&&, Args...>);
STATIC_REQUIRE(std::invocable<NothrowMockT&&, Args...>);

// negative checks

STATIC_REQUIRE(!std::invocable<const MockT, Args...>);
STATIC_REQUIRE(!std::invocable<const NothrowMockT, Args...>);

STATIC_REQUIRE(!std::invocable<const MockT&, Args...>);
STATIC_REQUIRE(!std::invocable<const NothrowMockT&, Args...>);

STATIC_REQUIRE(!std::invocable<const MockT&&, Args...>);
STATIC_REQUIRE(!std::invocable<const NothrowMockT&&, Args...>);

#endif
}

TEMPLATE_TEST_CASE_SIG(
"Mutable Mock specialization is an invocable type.",
"Const Mock specialization is an invocable type.",
"[mock]",
((bool dummy, typename Sig, typename... Args), dummy, Sig, Args...),
(true, void() const),
Expand All @@ -98,29 +141,44 @@ TEMPLATE_TEST_CASE_SIG(
using NothrowMockT = Mock<signature_add_noexcept_t<Sig>>;

STATIC_REQUIRE(std::is_invocable_r_v<ReturnT, MockT, Args...>);
STATIC_REQUIRE(std::invocable<MockT, Args...>);
STATIC_REQUIRE(std::is_invocable_r_v<ReturnT, NothrowMockT, Args...>);
STATIC_REQUIRE(std::invocable<NothrowMockT, Args...>);

STATIC_REQUIRE(std::is_invocable_r_v<ReturnT, const MockT, Args...>);
STATIC_REQUIRE(std::is_invocable_r_v<ReturnT, const NothrowMockT, Args...>);

STATIC_REQUIRE(std::is_invocable_r_v<ReturnT, MockT&, Args...>);
STATIC_REQUIRE(std::invocable<MockT&, Args...>);
STATIC_REQUIRE(std::is_invocable_r_v<ReturnT, NothrowMockT&, Args...>);
STATIC_REQUIRE(std::invocable<NothrowMockT&, Args...>);

STATIC_REQUIRE(std::is_invocable_r_v<ReturnT, const MockT&, Args...>);
STATIC_REQUIRE(std::invocable<const MockT&, Args...>);
STATIC_REQUIRE(std::is_invocable_r_v<ReturnT, const NothrowMockT&, Args...>);
STATIC_REQUIRE(std::invocable<const NothrowMockT&, Args...>);

STATIC_REQUIRE(std::is_invocable_r_v<ReturnT, MockT&&, Args...>);
STATIC_REQUIRE(std::invocable<MockT&&, Args...>);
STATIC_REQUIRE(std::is_invocable_r_v<ReturnT, NothrowMockT&&, Args...>);
STATIC_REQUIRE(std::invocable<NothrowMockT&&, Args...>);

STATIC_REQUIRE(std::is_invocable_r_v<ReturnT, const MockT&&, Args...>);
STATIC_REQUIRE(std::invocable<const MockT&&, Args...>);
STATIC_REQUIRE(std::is_invocable_r_v<ReturnT, const NothrowMockT&&, Args...>);

#ifndef CLANG_18_STD_INVOCABLE_REGRESSION

STATIC_REQUIRE(std::invocable<MockT, Args...>);
STATIC_REQUIRE(std::invocable<NothrowMockT, Args...>);

STATIC_REQUIRE(std::invocable<const MockT, Args...>);
STATIC_REQUIRE(std::invocable<const NothrowMockT, Args...>);

STATIC_REQUIRE(std::invocable<MockT&, Args...>);
STATIC_REQUIRE(std::invocable<NothrowMockT&, Args...>);

STATIC_REQUIRE(std::invocable<const MockT&, Args...>);
STATIC_REQUIRE(std::invocable<const NothrowMockT&, Args...>);

STATIC_REQUIRE(std::invocable<MockT&&, Args...>);
STATIC_REQUIRE(std::invocable<NothrowMockT&&, Args...>);

STATIC_REQUIRE(std::invocable<const MockT&&, Args...>);
STATIC_REQUIRE(std::invocable<const NothrowMockT&&, Args...>);

#endif
}

TEMPLATE_TEST_CASE_SIG(
Expand All @@ -140,9 +198,48 @@ TEMPLATE_TEST_CASE_SIG(
using NothrowMockT = Mock<signature_add_noexcept_t<Sig>>;

STATIC_REQUIRE(std::is_invocable_r_v<ReturnT, MockT&, Args...>);
STATIC_REQUIRE(std::invocable<MockT&, Args...>);
STATIC_REQUIRE(std::is_invocable_r_v<ReturnT, NothrowMockT&, Args...>);

// negative checks

STATIC_REQUIRE(!std::is_invocable_r_v<ReturnT, MockT, Args...>);
STATIC_REQUIRE(!std::is_invocable_r_v<ReturnT, NothrowMockT, Args...>);

STATIC_REQUIRE(!std::is_invocable_r_v<ReturnT, const MockT, Args...>);
STATIC_REQUIRE(!std::is_invocable_r_v<ReturnT, const NothrowMockT, Args...>);

STATIC_REQUIRE(!std::is_invocable_r_v<ReturnT, const MockT&, Args...>);
STATIC_REQUIRE(!std::is_invocable_r_v<ReturnT, const NothrowMockT&, Args...>);

STATIC_REQUIRE(!std::is_invocable_r_v<ReturnT, MockT&&, Args...>);
STATIC_REQUIRE(!std::is_invocable_r_v<ReturnT, NothrowMockT&&, Args...>);

STATIC_REQUIRE(!std::is_invocable_r_v<ReturnT, const MockT&&, Args...>);
STATIC_REQUIRE(!std::is_invocable_r_v<ReturnT, const NothrowMockT&&, Args...>);

#ifndef CLANG_18_STD_INVOCABLE_REGRESSION

STATIC_REQUIRE(std::invocable<MockT&, Args...>);
STATIC_REQUIRE(std::invocable<NothrowMockT&, Args...>);

// negative checks

STATIC_REQUIRE(!std::invocable<MockT, Args...>);
STATIC_REQUIRE(!std::invocable<NothrowMockT, Args...>);

STATIC_REQUIRE(!std::invocable<const MockT, Args...>);
STATIC_REQUIRE(!std::invocable<const NothrowMockT, Args...>);

STATIC_REQUIRE(!std::invocable<const MockT&, Args...>);
STATIC_REQUIRE(!std::invocable<const NothrowMockT&, Args...>);

STATIC_REQUIRE(!std::invocable<MockT&&, Args...>);
STATIC_REQUIRE(!std::invocable<NothrowMockT&&, Args...>);

STATIC_REQUIRE(!std::invocable<const MockT&&, Args...>);
STATIC_REQUIRE(!std::invocable<const NothrowMockT&&, Args...>);

#endif
}

TEMPLATE_TEST_CASE_SIG(
Expand All @@ -162,29 +259,44 @@ TEMPLATE_TEST_CASE_SIG(
using NothrowMockT = Mock<signature_add_noexcept_t<Sig>>;

STATIC_REQUIRE(std::is_invocable_r_v<ReturnT, MockT, Args...>);
STATIC_REQUIRE(std::invocable<MockT, Args...>);
STATIC_REQUIRE(std::is_invocable_r_v<ReturnT, NothrowMockT, Args...>);
STATIC_REQUIRE(std::invocable<NothrowMockT, Args...>);

STATIC_REQUIRE(std::is_invocable_r_v<ReturnT, const MockT, Args...>);
STATIC_REQUIRE(std::is_invocable_r_v<ReturnT, const NothrowMockT, Args...>);

STATIC_REQUIRE(std::is_invocable_r_v<ReturnT, MockT&, Args...>);
STATIC_REQUIRE(std::invocable<MockT&, Args...>);
STATIC_REQUIRE(std::is_invocable_r_v<ReturnT, NothrowMockT&, Args...>);
STATIC_REQUIRE(std::invocable<NothrowMockT&, Args...>);

STATIC_REQUIRE(std::is_invocable_r_v<ReturnT, const MockT&, Args...>);
STATIC_REQUIRE(std::invocable<const MockT&, Args...>);
STATIC_REQUIRE(std::is_invocable_r_v<ReturnT, const NothrowMockT&, Args...>);
STATIC_REQUIRE(std::invocable<const NothrowMockT&, Args...>);

STATIC_REQUIRE(std::is_invocable_r_v<ReturnT, MockT&&, Args...>);
STATIC_REQUIRE(std::invocable<MockT&&, Args...>);
STATIC_REQUIRE(std::is_invocable_r_v<ReturnT, NothrowMockT&&, Args...>);
STATIC_REQUIRE(std::invocable<NothrowMockT&&, Args...>);

STATIC_REQUIRE(std::is_invocable_r_v<ReturnT, const MockT&&, Args...>);
STATIC_REQUIRE(std::invocable<const MockT&&, Args...>);
STATIC_REQUIRE(std::is_invocable_r_v<ReturnT, const NothrowMockT&&, Args...>);

#ifndef CLANG_18_STD_INVOCABLE_REGRESSION

STATIC_REQUIRE(std::invocable<MockT, Args...>);
STATIC_REQUIRE(std::invocable<NothrowMockT, Args...>);

STATIC_REQUIRE(std::invocable<const MockT, Args...>);
STATIC_REQUIRE(std::invocable<const NothrowMockT, Args...>);

STATIC_REQUIRE(std::invocable<MockT&, Args...>);
STATIC_REQUIRE(std::invocable<NothrowMockT&, Args...>);

STATIC_REQUIRE(std::invocable<const MockT&, Args...>);
STATIC_REQUIRE(std::invocable<const NothrowMockT&, Args...>);

STATIC_REQUIRE(std::invocable<MockT&&, Args...>);
STATIC_REQUIRE(std::invocable<NothrowMockT&&, Args...>);

STATIC_REQUIRE(std::invocable<const MockT&&, Args...>);
STATIC_REQUIRE(std::invocable<const NothrowMockT&&, Args...>);

#endif
}

TEMPLATE_TEST_CASE_SIG(
Expand All @@ -204,14 +316,48 @@ TEMPLATE_TEST_CASE_SIG(
using NothrowMockT = Mock<signature_add_noexcept_t<Sig>>;

STATIC_REQUIRE(std::is_invocable_r_v<ReturnT, MockT, Args...>);
STATIC_REQUIRE(std::invocable<MockT, Args...>);
STATIC_REQUIRE(std::is_invocable_r_v<ReturnT, NothrowMockT, Args...>);
STATIC_REQUIRE(std::invocable<NothrowMockT, Args...>);

STATIC_REQUIRE(std::is_invocable_r_v<ReturnT, MockT&&, Args...>);
STATIC_REQUIRE(std::invocable<MockT&&, Args...>);
STATIC_REQUIRE(std::is_invocable_r_v<ReturnT, NothrowMockT&&, Args...>);

// negative checks

STATIC_REQUIRE(!std::is_invocable_r_v<ReturnT, const MockT, Args...>);
STATIC_REQUIRE(!std::is_invocable_r_v<ReturnT, const NothrowMockT, Args...>);

STATIC_REQUIRE(!std::is_invocable_r_v<ReturnT, MockT&, Args...>);
STATIC_REQUIRE(!std::is_invocable_r_v<ReturnT, NothrowMockT&, Args...>);

STATIC_REQUIRE(!std::is_invocable_r_v<ReturnT, const MockT&, Args...>);
STATIC_REQUIRE(!std::is_invocable_r_v<ReturnT, const NothrowMockT&, Args...>);

STATIC_REQUIRE(!std::is_invocable_r_v<ReturnT, const MockT&&, Args...>);
STATIC_REQUIRE(!std::is_invocable_r_v<ReturnT, const NothrowMockT&&, Args...>);

#ifndef CLANG_18_STD_INVOCABLE_REGRESSION

STATIC_REQUIRE(std::invocable<MockT, Args...>);
STATIC_REQUIRE(std::invocable<NothrowMockT, Args...>);

STATIC_REQUIRE(std::invocable<MockT&&, Args...>);
STATIC_REQUIRE(std::invocable<NothrowMockT&&, Args...>);

// negative checks

STATIC_REQUIRE(!std::invocable<const MockT, Args...>);
STATIC_REQUIRE(!std::invocable<const NothrowMockT, Args...>);

STATIC_REQUIRE(!std::invocable<MockT&, Args...>);
STATIC_REQUIRE(!std::invocable<NothrowMockT&, Args...>);

STATIC_REQUIRE(!std::invocable<const MockT&, Args...>);
STATIC_REQUIRE(!std::invocable<const NothrowMockT&, Args...>);

STATIC_REQUIRE(!std::invocable<const MockT&&, Args...>);
STATIC_REQUIRE(!std::invocable<const NothrowMockT&&, Args...>);

#endif
}

TEMPLATE_TEST_CASE_SIG(
Expand All @@ -231,19 +377,48 @@ TEMPLATE_TEST_CASE_SIG(
using NothrowMockT = Mock<signature_add_noexcept_t<Sig>>;

STATIC_REQUIRE(std::is_invocable_r_v<ReturnT, MockT, Args...>);
STATIC_REQUIRE(std::invocable<MockT, Args...>);
STATIC_REQUIRE(std::is_invocable_r_v<ReturnT, NothrowMockT, Args...>);
STATIC_REQUIRE(std::invocable<NothrowMockT, Args...>);

STATIC_REQUIRE(std::is_invocable_r_v<ReturnT, const MockT, Args...>);
STATIC_REQUIRE(std::is_invocable_r_v<ReturnT, const NothrowMockT, Args...>);

STATIC_REQUIRE(std::is_invocable_r_v<ReturnT, MockT&&, Args...>);
STATIC_REQUIRE(std::invocable<MockT&&, Args...>);
STATIC_REQUIRE(std::is_invocable_r_v<ReturnT, NothrowMockT&&, Args...>);
STATIC_REQUIRE(std::invocable<NothrowMockT&&, Args...>);

STATIC_REQUIRE(std::is_invocable_r_v<ReturnT, const MockT&&, Args...>);
STATIC_REQUIRE(std::invocable<const MockT&&, Args...>);
STATIC_REQUIRE(std::is_invocable_r_v<ReturnT, const NothrowMockT&&, Args...>);

// negative checks

STATIC_REQUIRE(!std::is_invocable_r_v<ReturnT, MockT&, Args...>);
STATIC_REQUIRE(!std::is_invocable_r_v<ReturnT, NothrowMockT&, Args...>);

STATIC_REQUIRE(!std::is_invocable_r_v<ReturnT, const MockT&, Args...>);
STATIC_REQUIRE(!std::is_invocable_r_v<ReturnT, const NothrowMockT&, Args...>);

#ifndef CLANG_18_STD_INVOCABLE_REGRESSION

STATIC_REQUIRE(std::invocable<MockT, Args...>);
STATIC_REQUIRE(std::invocable<NothrowMockT, Args...>);

STATIC_REQUIRE(std::invocable<const MockT, Args...>);
STATIC_REQUIRE(std::invocable<const NothrowMockT, Args...>);

STATIC_REQUIRE(std::invocable<MockT&&, Args...>);
STATIC_REQUIRE(std::invocable<NothrowMockT&&, Args...>);

STATIC_REQUIRE(std::invocable<const MockT&&, Args...>);
STATIC_REQUIRE(std::invocable<const NothrowMockT&&, Args...>);

// negative checks

STATIC_REQUIRE(!std::invocable<MockT&, Args...>);
STATIC_REQUIRE(!std::invocable<NothrowMockT&, Args...>);

STATIC_REQUIRE(!std::invocable<const MockT&, Args...>);
STATIC_REQUIRE(!std::invocable<const NothrowMockT&, Args...>);

#endif
}

TEST_CASE(
Expand Down

0 comments on commit 5453228

Please sign in to comment.