diff --git a/CMakeLists.txt b/CMakeLists.txt index 0821d1ab..b73d35af 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,7 +25,7 @@ include(cmake/string_catalog.cmake) add_versioned_package("gh:boostorg/mp11#boost-1.83.0") fmt_recipe(10.2.1) add_versioned_package("gh:intel/cpp-baremetal-concurrency#7c5b26c") -add_versioned_package("gh:intel/cpp-std-extensions#5530b5d") +add_versioned_package("gh:intel/cpp-std-extensions#73569fe") add_versioned_package("gh:intel/cpp-baremetal-senders-and-receivers#73d95bc") add_library(cib INTERFACE) diff --git a/include/flow/graph_builder.hpp b/include/flow/graph_builder.hpp index dd470d68..d71796be 100644 --- a/include/flow/graph_builder.hpp +++ b/include/flow/graph_builder.hpp @@ -4,12 +4,12 @@ #include #include -#include #include #include #include #include #include +#include #include #include #include @@ -52,31 +52,10 @@ template using name_for = typename T::name_t; }); } -template struct sequence_conditions; - -template struct INFO_flow_name_; - -template struct INFO_step_a_name_; - -template struct INFO_step_a_condition_; - -template struct INFO_step_b_name_; - -template struct INFO_step_b_condition_; - -template struct INFO_sequence_condition_; - -template struct INFO_sequence_missing_predicate_; - -template constexpr bool ERROR_DETAILS_ = false; - -template struct INFO_missing_steps_; - -template struct INFO_duplicated_steps_; - template typename Impl> struct graph_builder { + // NOLINTBEGIN(readability-function-cognitive-complexity) template [[nodiscard]] constexpr static auto make_graph(auto const &nodes, auto const &edges) { @@ -93,6 +72,8 @@ struct graph_builder { using lhs_t = std::remove_cvref_t; using rhs_t = std::remove_cvref_t; + using lhs_cond_t = std::remove_cvref_t; + using rhs_cond_t = std::remove_cvref_t; using edge_ps_t = decltype(Cond::predicates); auto node_ps = stdx::to_unsorted_set(stdx::tuple_cat( @@ -100,31 +81,17 @@ struct graph_builder { stdx::for_each( [&](P const &) { - if constexpr (not stdx::contains_type) { - static_assert( - ERROR_DETAILS_< - INFO_flow_name_, - INFO_step_a_name_, - INFO_step_a_condition_< - lhs_t::condition.ct_name>, - INFO_step_b_name_, - INFO_step_b_condition_< - rhs_t::condition.ct_name>, - INFO_sequence_condition_, - INFO_sequence_missing_predicate_

>, - - "The conditions on this sequence " - "(step_a >> step_b) are weaker than those on " - "step_a and/or step_b. The sequence could be " - "enabled while step_a and/or step_b is not. " - "Specifically, the sequence is missing the " - "predicate identified in " - "`INFO_sequence_missing_predicate_`. TIP: " - "Look for 'ERROR_DETAILS_` and `INFO_` in " - "the compiler error message for details on " - "the sequence, the step names, and the " - "conditions."); - } + STATIC_ASSERT( + (stdx::contains_type), + "The conditions on the sequence ({} >> {})[{}] are " + "weaker than those on {}[{}] or {}[{}]. " + "Specifically, the sequence is missing the " + "predicate: {}", + CX_VALUE(lhs_t::ct_name), CX_VALUE(rhs_t::ct_name), + CX_VALUE(Cond::ct_name), CX_VALUE(lhs_t::ct_name), + CX_VALUE(lhs_cond_t::ct_name), + CX_VALUE(rhs_t::ct_name), + CX_VALUE(rhs_cond_t::ct_name), CX_VALUE(P)); }, node_ps); @@ -133,6 +100,7 @@ struct graph_builder { edges); return g; } + // NOLINTEND(readability-function-cognitive-complexity) template [[nodiscard]] constexpr static auto is_source_of(Node const &node, @@ -191,6 +159,15 @@ struct graph_builder { return std::optional{std::in_place, span_t{ordered_list}}; } + template + constexpr static auto error_steps = + stdx::transform([](auto N) { return stdx::ct_string_from_type(N); }, + T{}) + .join(stdx::ct_string{""}, [](auto x, auto y) { + using namespace stdx::literals; + return x + ", "_cts + y; + }); + constexpr static void check_for_missing_nodes(auto nodes, auto mentioned_nodes) { constexpr auto get_name = [](N) -> @@ -201,52 +178,24 @@ struct graph_builder { using node_names_t = decltype(stdx::to_sorted_set(node_names)); using mentioned_node_names_t = decltype(stdx::to_sorted_set(mentioned_node_names)); - - if constexpr (not std::is_same_v) { - using missing_nodes_t = - boost::mp11::mp_set_difference; - - constexpr auto missing_nodes = missing_nodes_t{}; - constexpr auto missing_nodes_ct_strings = stdx::transform( - [](N) { return stdx::ct_string_from_type(N{}); }, - missing_nodes); - - [&](std::index_sequence) { - using error_details_t = INFO_missing_steps_( - missing_nodes_ct_strings)...>; - - static_assert( - ERROR_DETAILS_, error_details_t>, - "One or more steps are referenced in the flow but not " - "explicitly added with the * operator. The " - "beginning of this error shows you which steps are " - "missing."); - }(std::make_index_sequence< - stdx::tuple_size_v>{}); - } - - if constexpr (stdx::tuple_size_v != - stdx::tuple_size_v) { - constexpr auto duplicates = stdx::transform( - [](auto e) { - return stdx::ct_string_from_type(stdx::get<0>(e)); - }, - stdx::filter(stdx::gather(node_names))); - - [&](std::index_sequence) { - using error_details_t = - INFO_duplicated_steps_(duplicates)...>; - - static_assert( - ERROR_DETAILS_, error_details_t>, - "One or more steps are explicitly added more than once " - "using the * operator. The beginning of this " - "error shows you which steps are duplicated."); - }(std::make_index_sequence< - stdx::tuple_size_v>{}); - } + using missing_nodes_t = + boost::mp11::mp_set_difference; + STATIC_ASSERT( + (std::is_same_v), + "One or more steps are referenced in the flow ({}) but not " + "explicitly added with the * operator. The missing steps are: {}.", + CX_VALUE(Name), CX_VALUE(error_steps)); + + constexpr auto duplicates = stdx::transform( + [](auto e) { return stdx::get<0>(e); }, + stdx::filter(stdx::gather(node_names))); + using duplicate_nodes_t = decltype(duplicates); + STATIC_ASSERT( + stdx::tuple_size_v == 0, + "One or more steps in the flow ({}) are explicitly added more than " + "once using the * operator. The duplicate steps are: {}.", + CX_VALUE(Name), CX_VALUE(error_steps)); } template diff --git a/test/flow/fail/CMakeLists.txt b/test/flow/fail/CMakeLists.txt index 7c41db00..d33bcb49 100644 --- a/test/flow/fail/CMakeLists.txt +++ b/test/flow/fail/CMakeLists.txt @@ -1,5 +1,16 @@ -add_compile_fail_test(cyclic_flow.cpp LIBRARIES warnings cib) -add_compile_fail_test(only_reference_added.cpp LIBRARIES warnings cib) -add_compile_fail_test(mismatched_flow_runtime_conditional.cpp LIBRARIES - warnings cib) -add_compile_fail_test(node_explicitly_added_twice.cpp LIBRARIES warnings cib) +add_compile_fail_test(cyclic_flow.cpp LIBRARIES cib) + +function(add_formatted_errors_tests) + add_compile_fail_test(only_reference_added.cpp LIBRARIES cib) + add_compile_fail_test(mismatched_flow_runtime_conditional.cpp LIBRARIES cib) + add_compile_fail_test(node_explicitly_added_twice.cpp LIBRARIES cib) +endfunction() + +if(${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang" AND ${CMAKE_CXX_COMPILER_VERSION} + VERSION_GREATER_EQUAL 15) + add_formatted_errors_tests() +endif() +if(${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU" AND ${CMAKE_CXX_COMPILER_VERSION} + VERSION_GREATER_EQUAL 13.2) + add_formatted_errors_tests() +endif() diff --git a/test/flow/fail/mismatched_flow_runtime_conditional.cpp b/test/flow/fail/mismatched_flow_runtime_conditional.cpp index 32c16854..999f7116 100644 --- a/test/flow/fail/mismatched_flow_runtime_conditional.cpp +++ b/test/flow/fail/mismatched_flow_runtime_conditional.cpp @@ -1,7 +1,7 @@ #include #include -// EXPECT: The conditions on this sequence +// EXPECT: The conditions on the sequence namespace { using namespace flow::literals; diff --git a/test/flow/fail/node_explicitly_added_twice.cpp b/test/flow/fail/node_explicitly_added_twice.cpp index ba99bb4f..1d89e508 100644 --- a/test/flow/fail/node_explicitly_added_twice.cpp +++ b/test/flow/fail/node_explicitly_added_twice.cpp @@ -1,14 +1,14 @@ #include #include -// EXPECT: One or more steps are explicitly added more than once +// EXPECT: are explicitly added more than once namespace { using namespace flow::literals; constexpr auto a = flow::milestone<"a">(); -struct TestFlowAlpha : public flow::service<> {}; +struct TestFlowAlpha : public flow::service<"alpha"> {}; struct FlowConfig { constexpr static auto config = cib::config( diff --git a/test/flow/fail/only_reference_added.cpp b/test/flow/fail/only_reference_added.cpp index 44130097..cd9f4c48 100644 --- a/test/flow/fail/only_reference_added.cpp +++ b/test/flow/fail/only_reference_added.cpp @@ -1,14 +1,14 @@ #include #include -// EXPECT: One or more steps are referenced in the flow but not explicitly +// EXPECT: One or more steps are referenced in the flow namespace { using namespace flow::literals; constexpr auto a = flow::milestone<"a">(); -struct TestFlowAlpha : public flow::service<> {}; +struct TestFlowAlpha : public flow::service<"alpha"> {}; struct FlowConfig { constexpr static auto config =