From 0e67441249e8151963b130585807ae6e3f4e2d5c Mon Sep 17 00:00:00 2001 From: Greg Sjaardema Date: Wed, 13 Sep 2023 09:36:42 -0600 Subject: [PATCH] Clang-tidy fixes --- .../seacas/applications/ejoin/EJ_mapping.C | 13 +- .../seacas/applications/ejoin/EJ_vector3d.C | 4 +- .../seacas/applications/ejoin/EJ_vector3d.h | 4 +- packages/seacas/applications/ejoin/EJoin.C | 20 +- .../seacas/applications/epu/EP_Internals.h | 17 +- .../applications/epu/EP_ParallelDisks.h | 9 +- .../applications/epu/EP_SystemInterface.C | 4 +- .../seacas/applications/epu/EP_Variables.h | 8 +- .../applications/exodiff/ED_SystemInterface.C | 6 +- .../seacas/applications/exodiff/edge_block.h | 8 +- .../seacas/applications/exodiff/exoII_read.C | 6 +- .../seacas/applications/exodiff/exoII_read.h | 4 +- .../seacas/applications/exodiff/exodiff.C | 3 +- .../seacas/applications/exodiff/face_block.h | 7 +- .../seacas/applications/exodiff/side_set.h | 7 +- .../exomatlab/EML_SystemInterface.C | 9 +- .../seacas/applications/mat2exo/mat2exo.C | 2 +- .../applications/nas2exo/N2EExoWriter.C | 27 +- .../applications/nas2exo/N2ENasReader.C | 4 +- .../seacas/applications/nas2exo/nas2exo.C | 2 +- .../applications/nem_slice/elb_loadbal.C | 4 +- .../nem_slice/fix_column_partitions.C | 12 +- .../applications/slice/SL_SystemInterface.C | 5 +- packages/seacas/applications/slice/Slice.C | 2 +- packages/seacas/applications/zellij/Cell.C | 3 +- .../seacas/libraries/aprepro_lib/FlexLexer.h | 5 +- .../libraries/aprepro_lib/apr_parser.cc | 64 +- .../libraries/aprepro_lib/aprepro_parser.h | 4 +- .../seacas/libraries/ioss/src/Ioss_Assembly.C | 6 +- .../libraries/ioss/src/Ioss_CodeTypes.h | 8 +- .../ioss/src/Ioss_ConcreteVariableType.C | 78 +- .../libraries/ioss/src/Ioss_ElementTopology.C | 2 +- .../libraries/ioss/src/Ioss_EntityBlock.C | 4 +- .../seacas/libraries/ioss/src/Ioss_Field.C | 32 +- .../libraries/ioss/src/Ioss_FieldManager.h | 6 +- .../seacas/libraries/ioss/src/Ioss_FileInfo.C | 4 +- .../seacas/libraries/ioss/src/Ioss_Glob.h | 18 +- .../libraries/ioss/src/Ioss_GroupingEntity.C | 4 +- .../libraries/ioss/src/Ioss_IOFactory.h | 2 +- .../seacas/libraries/ioss/src/Ioss_Property.C | 16 +- .../libraries/ioss/src/Ioss_PropertyManager.C | 5 - .../libraries/ioss/src/Ioss_PropertyManager.h | 4 +- .../seacas/libraries/ioss/src/Ioss_Region.C | 54 +- .../libraries/ioss/src/Ioss_ScopeGuard.h | 2 +- .../libraries/ioss/src/Ioss_SideBlock.C | 6 +- .../seacas/libraries/ioss/src/Ioss_SideSet.C | 6 +- .../libraries/ioss/src/Ioss_StructuredBlock.C | 12 +- .../seacas/libraries/ioss/src/Ioss_Utils.C | 68 +- .../libraries/ioss/src/Ioss_VariableType.h | 2 +- .../libraries/ioss/src/cgns/Iocgns_Utils.h | 8 +- packages/seacas/libraries/ioss/src/doctest.h | 8564 +++++++++-------- .../ioss/src/exodus/Ioex_Internals.C | 5 +- .../ioss/src/exodus/Ioex_Internals.h | 6 +- .../ioss/src/exodus/Ioex_SuperElement.C | 12 +- .../libraries/ioss/src/exodus/Ioex_Utils.C | 2 +- .../ioss/src/exonull/Ioexnl_SuperElement.C | 12 +- .../ioss/src/generated/Iogn_DashSurfaceMesh.h | 6 +- .../ioss/src/heartbeat/Iohb_DatabaseIO.C | 6 +- .../ioss/src/hopscotch_growth_policy.h | 541 +- .../libraries/ioss/src/hopscotch_hash.h | 8 +- .../libraries/ioss/src/main/cgns_decomp.C | 2 +- .../ioss/src/main/cth_pressure_map.C | 118 +- .../libraries/ioss/src/main/shell_interface.C | 2 +- .../libraries/ioss/src/main/shell_interface.h | 2 +- .../libraries/ioss/src/main/shell_to_hex.C | 35 +- .../seacas/libraries/ioss/src/main/skinner.C | 5 +- .../seacas/libraries/ioss/src/main/sphgen.C | 23 +- .../seacas/libraries/ioss/src/main/vector3d.C | 4 +- .../seacas/libraries/ioss/src/main/vector3d.h | 4 +- .../libraries/ioss/src/robin_growth_policy.h | 541 +- .../seacas/libraries/ioss/src/robin_hash.h | 2491 +++-- .../ioss/src/text_mesh/Iotm_TextMesh.C | 10 +- .../ioss/src/utest/Utst_IofxDatabaseIO.C | 36 +- .../seacas/libraries/suplib_cpp/FileInfo.C | 4 +- packages/seacas/libraries/suplib_cpp/glob.h | 124 +- .../seacas/libraries/suplib_cpp/pdqsort.h | 6 +- .../seacas/libraries/suplib_cpp/scopeguard.h | 5 +- .../libraries/suplib_cpp/smart_assert.C | 5 +- .../libraries/suplib_cpp/smart_assert.h | 22 +- .../seacas/libraries/suplib_cpp/time_stamp.C | 2 +- packages/zoltan/siMPI/pyMPI/siMPI/mpi.h | 4 +- .../siMPI/pyMPI/siMPI/mpi_implementation.h | 4 +- packages/zoltan/src/include/zoltan.h | 4 +- packages/zoltan/src/include/zoltan_cpp.h | 86 +- 84 files changed, 6889 insertions(+), 6422 deletions(-) diff --git a/packages/seacas/applications/ejoin/EJ_mapping.C b/packages/seacas/applications/ejoin/EJ_mapping.C index 86fa21a8b7..0feb37494d 100644 --- a/packages/seacas/applications/ejoin/EJ_mapping.C +++ b/packages/seacas/applications/ejoin/EJ_mapping.C @@ -213,8 +213,8 @@ void build_local_element_map(RegionVector &part_mesh, std::vector &local_el size_t offset = 0; for (auto &p : part_mesh) { - const Ioss::ElementBlockContainer &ebs = p->get_element_blocks(); - Ioss::ElementBlockContainer::const_iterator i = ebs.begin(); + const auto &ebs = p->get_element_blocks(); + auto i = ebs.begin(); while (i != ebs.end()) { const auto *eb = *i++; @@ -255,12 +255,9 @@ void generate_element_ids(RegionVector &part_mesh, const std::vector &local bool has_map = false; size_t offset = 0; for (auto &p : part_mesh) { - const Ioss::ElementBlockContainer &ebs = p->get_element_blocks(); - Ioss::ElementBlockContainer::const_iterator i = ebs.begin(); - - while (i != ebs.end()) { - Ioss::ElementBlock *eb = *i++; - INT num_elem = eb->entity_count(); + const auto &ebs = p->get_element_blocks(); + for (auto *eb : ebs) { + INT num_elem = eb->entity_count(); if (!entity_is_omitted(eb)) { std::vector part_ids; eb->get_field_data("ids", part_ids); diff --git a/packages/seacas/applications/ejoin/EJ_vector3d.C b/packages/seacas/applications/ejoin/EJ_vector3d.C index 1a96a09b7e..4778bf3a38 100644 --- a/packages/seacas/applications/ejoin/EJ_vector3d.C +++ b/packages/seacas/applications/ejoin/EJ_vector3d.C @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2020 National Technology & Engineering Solutions +// Copyright(C) 1999-2020, 2023 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -90,7 +90,7 @@ vector3d operator/(const vector3d &lhs, double scalar) return tmp /= scalar; } - return vector3d(HUGE_VAL, HUGE_VAL, HUGE_VAL); + return {HUGE_VAL, HUGE_VAL, HUGE_VAL}; } vector3d &vector3d::operator/=(double scalar) diff --git a/packages/seacas/applications/ejoin/EJ_vector3d.h b/packages/seacas/applications/ejoin/EJ_vector3d.h index 01415102cc..0afb3c9195 100644 --- a/packages/seacas/applications/ejoin/EJ_vector3d.h +++ b/packages/seacas/applications/ejoin/EJ_vector3d.h @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2020, 2022 National Technology & Engineering Solutions +// Copyright(C) 1999-2020, 2022, 2023 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -47,7 +47,7 @@ vector3d operator-(const vector3d &lhs, const vector3d &rhs); //---------------------------------------------------------------------------- inline vector3d vector3d::cross(const vector3d &from) const { - return vector3d(y * from.z - z * from.y, z * from.x - x * from.z, x * from.y - y * from.x); + return {y * from.z - z * from.y, z * from.x - x * from.z, x * from.y - y * from.x}; } //---------------------------------------------------------------------------- inline vector3d &vector3d::operator+=(const vector3d &from) diff --git a/packages/seacas/applications/ejoin/EJoin.C b/packages/seacas/applications/ejoin/EJoin.C index d1054dc8ee..1a19581107 100644 --- a/packages/seacas/applications/ejoin/EJoin.C +++ b/packages/seacas/applications/ejoin/EJoin.C @@ -1010,7 +1010,7 @@ namespace { // Assuming (with checks) that the output side blocks will be // iterated in same order as input side blocks... - Ioss::SideBlockContainer::const_iterator II = out_eb.begin(); + auto II = out_eb.begin(); for (const auto &pm : part_mesh) { size_t element_offset = pm->get_property("element_offset").get_int(); @@ -1201,7 +1201,7 @@ namespace { // Assuming (with checks) that the output side blocks will be // iterated in same order as input side blocks... - Ioss::SideBlockContainer::const_iterator II = out_eb.begin(); + auto II = out_eb.begin(); for (const auto &pm : part_mesh) { const Ioss::SideSetContainer &is = pm->get_sidesets(); @@ -1438,29 +1438,29 @@ namespace { if (!variable_list.empty() && variable_list[0].first == "none") { return; } - const Ioss::SideSetContainer &os = output_region.get_sidesets(); + const auto &os = output_region.get_sidesets(); Ioss::SideBlockContainer out_eb; // Put all output side blocks in the same list... for (const auto &oss : os) { - const Ioss::SideBlockContainer &obs = oss->get_side_blocks(); + const auto &obs = oss->get_side_blocks(); std::copy(obs.begin(), obs.end(), std::back_inserter(out_eb)); } // Assuming (with checks) that the output side blocks will be // iterated in same order as input side blocks... - Ioss::SideBlockContainer::const_iterator II = out_eb.begin(); + auto II = out_eb.begin(); for (const auto &pm : part_mesh) { - const Ioss::SideSetContainer &is = pm->get_sidesets(); + const auto &is = pm->get_sidesets(); for (const auto &iss : is) { if (!entity_is_omitted(iss)) { - size_t id = iss->get_property("id").get_int(); - const Ioss::SideBlockContainer &ebs = iss->get_side_blocks(); + size_t id = iss->get_property("id").get_int(); + const auto &ebs = iss->get_side_blocks(); for (const auto &eb : ebs) { SMART_ASSERT((pm->name() + "_" + eb->name() == (*II)->name()) || (eb->name() == (*II)->name())); - Ioss::NameList fields = eb->field_describe(Ioss::Field::TRANSIENT); + auto fields = eb->field_describe(Ioss::Field::TRANSIENT); for (const auto &field_name : fields) { if (valid_variable(field_name, id, variable_list)) { Ioss::Field field = eb->get_field(field_name); @@ -1478,7 +1478,7 @@ namespace { Ioss::Field::RoleType role, const std::string &prefix) { // Check for transient fields... - Ioss::NameList fields = ige->field_describe(role); + auto fields = ige->field_describe(role); // Iterate through results fields and transfer to output // database... If a prefix is specified, only transfer fields diff --git a/packages/seacas/applications/epu/EP_Internals.h b/packages/seacas/applications/epu/EP_Internals.h index 40f27376ab..1eccd8e184 100644 --- a/packages/seacas/applications/epu/EP_Internals.h +++ b/packages/seacas/applications/epu/EP_Internals.h @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2020, 2022 National Technology & Engineering Solutions + * Copyright(C) 1999-2020, 2022, 2023 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * @@ -92,8 +92,7 @@ namespace Excn { { public: Internals(int exoid, int maximum_name_length) - : exodusFilePtr(exoid), nodeMapVarID(), elementMapVarID(), commIndexVar(0), - elemCommIndexVar(0), maximumNameLength(maximum_name_length) + : exodusFilePtr(exoid), maximumNameLength(maximum_name_length) { } @@ -126,11 +125,11 @@ namespace Excn { int put_non_define_data(const std::vector> &edgeblocks); int put_non_define_data(const std::vector> &faceblocks); - int exodusFilePtr; - int nodeMapVarID[3]; - int elementMapVarID[2]; - int commIndexVar; - int elemCommIndexVar; - int maximumNameLength; + int exodusFilePtr{}; + int nodeMapVarID[3]{}; + int elementMapVarID[2]{}; + int commIndexVar{}; + int elemCommIndexVar{}; + int maximumNameLength{}; }; } // namespace Excn diff --git a/packages/seacas/applications/epu/EP_ParallelDisks.h b/packages/seacas/applications/epu/EP_ParallelDisks.h index 5b5216dcec..0099782f03 100644 --- a/packages/seacas/applications/epu/EP_ParallelDisks.h +++ b/packages/seacas/applications/epu/EP_ParallelDisks.h @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2020, 2022 National Technology & Engineering Solutions + * Copyright(C) 1999-2020, 2022, 2023 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * @@ -20,15 +20,12 @@ namespace Excn { public: ParallelDisks(); ~ParallelDisks(); + ParallelDisks(const ParallelDisks &) = delete; + ParallelDisks &operator=(const ParallelDisks &) = delete; static void Create_IO_Filename(std::string & /*name*/, int processor, int num_processors); void rename_file_for_mp(const std::string &rootdir, const std::string &subdir, std::string &name, int node, int numproc) const; - - private: - // not defined (the parallel disks object is unique!) - ParallelDisks(const ParallelDisks &); - ParallelDisks &operator=(const ParallelDisks &); }; } // namespace Excn diff --git a/packages/seacas/applications/epu/EP_SystemInterface.C b/packages/seacas/applications/epu/EP_SystemInterface.C index 97150ff740..db29e83e2a 100644 --- a/packages/seacas/applications/epu/EP_SystemInterface.C +++ b/packages/seacas/applications/epu/EP_SystemInterface.C @@ -663,13 +663,13 @@ namespace { StringVector name_id = SLIB::tokenize(*I, ":"); std::string var_name = LowerCase(name_id[0]); if (name_id.size() == 1) { - (*variable_list).push_back(std::make_pair(var_name, 0)); + (*variable_list).emplace_back(var_name, 0); } else { for (size_t i = 1; i < name_id.size(); i++) { // Convert string to integer... int id = std::stoi(name_id[i]); - (*variable_list).push_back(std::make_pair(var_name, id)); + (*variable_list).emplace_back(var_name, id); } } ++I; diff --git a/packages/seacas/applications/epu/EP_Variables.h b/packages/seacas/applications/epu/EP_Variables.h index 26d1fa7f1a..546be4d8a4 100644 --- a/packages/seacas/applications/epu/EP_Variables.h +++ b/packages/seacas/applications/epu/EP_Variables.h @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2020, 2022 National Technology & Engineering Solutions + * Copyright(C) 1999-2020, 2022, 2023 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * @@ -20,7 +20,7 @@ namespace Excn { struct Variables { - explicit Variables(ObjectType otype) : objectType(otype), outputCount(0), addProcessorId(false) + explicit Variables(ObjectType otype) : objectType(otype) { SMART_ASSERT(otype == Excn::ObjectType::EBLK || otype == Excn::ObjectType::NSET || otype == Excn::ObjectType::SSET || otype == Excn::ObjectType::NODE || @@ -69,8 +69,8 @@ namespace Excn { bool add_processor_id() const { return addProcessorId; } ObjectType objectType; - int outputCount; - bool addProcessorId; + int outputCount{0}; + bool addProcessorId{false}; IntVector index_{}; std::string type_{}; }; diff --git a/packages/seacas/applications/exodiff/ED_SystemInterface.C b/packages/seacas/applications/exodiff/ED_SystemInterface.C index aca898a814..d4d70711fa 100644 --- a/packages/seacas/applications/exodiff/ED_SystemInterface.C +++ b/packages/seacas/applications/exodiff/ED_SystemInterface.C @@ -632,14 +632,14 @@ bool SystemInterface::parse_options(int argc, char **argv) const char *temp = options_.retrieve("TimeStepOffset"); if (temp != nullptr) { errno = 0; - time_step_offset = strtol(temp, NULL, 10); + time_step_offset = strtol(temp, nullptr, 10); SMART_ASSERT(errno == 0); } else { const char *temp2 = options_.retrieve("T"); if (temp2 != nullptr) { errno = 0; - time_step_offset = strtol(temp2, NULL, 10); + time_step_offset = strtol(temp2, nullptr, 10); SMART_ASSERT(errno == 0); } } @@ -833,7 +833,7 @@ bool SystemInterface::parse_options(int argc, char **argv) const char *temp = options_.retrieve("max_warnings"); if (temp != nullptr) { errno = 0; - max_warnings = strtol(temp, NULL, 10); + max_warnings = strtol(temp, nullptr, 10); SMART_ASSERT(errno == 0); } } diff --git a/packages/seacas/applications/exodiff/edge_block.h b/packages/seacas/applications/exodiff/edge_block.h index f82ebf35df..7a3a09b6b1 100644 --- a/packages/seacas/applications/exodiff/edge_block.h +++ b/packages/seacas/applications/exodiff/edge_block.h @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2020, 2022 National Technology & Engineering Solutions +// Copyright(C) 1999-2020, 2022, 2023 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -16,6 +16,9 @@ template class Edge_Block : public Exo_Entity Edge_Block(); Edge_Block(int file_id, size_t id); Edge_Block(int file_id, size_t id, size_t ne); + Edge_Block(const Edge_Block &) = delete; // Not written. + const Edge_Block &operator=(const Edge_Block &) = delete; // Not written. + ~Edge_Block() override; size_t Edge_Index(size_t position) const; @@ -23,9 +26,6 @@ template class Edge_Block : public Exo_Entity int Check_State() const; private: - Edge_Block(const Edge_Block &) = delete; // Not written. - const Edge_Block &operator=(const Edge_Block &) = delete; // Not written. - void entity_load_params() override; EXOTYPE exodus_type() const override; diff --git a/packages/seacas/applications/exodiff/exoII_read.C b/packages/seacas/applications/exodiff/exoII_read.C index 31f086eff5..b55bd3ec70 100644 --- a/packages/seacas/applications/exodiff/exoII_read.C +++ b/packages/seacas/applications/exodiff/exoII_read.C @@ -33,7 +33,9 @@ namespace { template ExoII_Read::ExoII_Read() = default; -template ExoII_Read::ExoII_Read(const std::string &fname) : file_name(fname) {} +template ExoII_Read::ExoII_Read(std::string fname) : file_name(std::move(fname)) +{ +} template ExoII_Read::~ExoII_Read() { @@ -1005,7 +1007,7 @@ template void ExoII_Read::Get_Init_Data() coord_names.clear(); for (int i = 0; i < dimension; ++i) { - coord_names.push_back(coords[i]); + coord_names.emplace_back(coords[i]); } free_name_array(coords, 3); diff --git a/packages/seacas/applications/exodiff/exoII_read.h b/packages/seacas/applications/exodiff/exoII_read.h index 8fe5ab78a1..3cef8ec061 100644 --- a/packages/seacas/applications/exodiff/exoII_read.h +++ b/packages/seacas/applications/exodiff/exoII_read.h @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2022 National Technology & Engineering Solutions +// Copyright(C) 1999-2023 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -32,7 +32,7 @@ template class ExoII_Read { public: ExoII_Read(); - explicit ExoII_Read(const std::string &fname); + explicit ExoII_Read(std::string fname); virtual ~ExoII_Read(); const ExoII_Read &operator=(const ExoII_Read &) = delete; ExoII_Read(const ExoII_Read &) = delete; diff --git a/packages/seacas/applications/exodiff/exodiff.C b/packages/seacas/applications/exodiff/exodiff.C index 65b66f7bb1..3b4b1bb4e8 100644 --- a/packages/seacas/applications/exodiff/exodiff.C +++ b/packages/seacas/applications/exodiff/exodiff.C @@ -1063,8 +1063,7 @@ bool Equal_Values(const double *values, size_t count, double *value) { SMART_ASSERT(values != nullptr); *value = values[0]; - return (std::adjacent_find(values, values + count, std::not_equal_to()) == - values + count); + return (std::adjacent_find(values, values + count, std::not_equal_to<>()) == values + count); } template diff --git a/packages/seacas/applications/exodiff/face_block.h b/packages/seacas/applications/exodiff/face_block.h index db1e574ff7..7fe45473d7 100644 --- a/packages/seacas/applications/exodiff/face_block.h +++ b/packages/seacas/applications/exodiff/face_block.h @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2022 National Technology & Engineering Solutions +// Copyright(C) 1999-2023 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -17,15 +17,14 @@ template class Face_Block : public Exo_Entity Face_Block(int file_id, size_t id); Face_Block(int file_id, size_t id, size_t ne); ~Face_Block() override; + Face_Block(const Face_Block &) = delete; // Not written. + const Face_Block &operator=(const Face_Block &) = delete; // Not written. size_t Face_Index(size_t position) const; int Check_State() const; private: - Face_Block(const Face_Block &) = delete; // Not written. - const Face_Block &operator=(const Face_Block &) = delete; // Not written. - void entity_load_params() override; EXOTYPE exodus_type() const override; diff --git a/packages/seacas/applications/exodiff/side_set.h b/packages/seacas/applications/exodiff/side_set.h index 362b3f940c..4e923b18c2 100644 --- a/packages/seacas/applications/exodiff/side_set.h +++ b/packages/seacas/applications/exodiff/side_set.h @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2020, 2022 National Technology & Engineering Solutions +// Copyright(C) 1999-2020, 2022, 2023 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -17,6 +17,8 @@ template class Side_Set : public Exo_Entity Side_Set(int file_id, size_t id); Side_Set(int file_id, size_t id, size_t ns, size_t ndf = 0); ~Side_Set() override; + Side_Set(const Side_Set &) = delete; + const Side_Set &operator=(const Side_Set &) = delete; void apply_map(const std::vector &elmt_map); const INT *Elements() const; @@ -32,9 +34,6 @@ template class Side_Set : public Exo_Entity size_t Distribution_Factor_Count() const { return num_dist_factors; } private: - Side_Set(const Side_Set &); // Not written. - const Side_Set &operator=(const Side_Set &); // Not written. - void load_sides(const std::vector &elmt_map) const; void load_df() const; void entity_load_params() override; diff --git a/packages/seacas/applications/exomatlab/EML_SystemInterface.C b/packages/seacas/applications/exomatlab/EML_SystemInterface.C index 146daf9334..1a12e20a6b 100644 --- a/packages/seacas/applications/exomatlab/EML_SystemInterface.C +++ b/packages/seacas/applications/exomatlab/EML_SystemInterface.C @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2022 National Technology & Engineering Solutions + * Copyright(C) 1999-2023 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * @@ -107,7 +107,8 @@ bool SystemInterface::parse_options(int argc, char **argv) options_.usage(); fmt::print(stderr, "\n\tCan also set options via EXOMATLAB_OPTIONS environment variable.\n" - "\n\tDocumentation: https://sandialabs.github.io/seacas-docs/sphinx/html/index.html#exomatlab\n" + "\n\tDocumentation: " + "https://sandialabs.github.io/seacas-docs/sphinx/html/index.html#exomatlab\n" "\n\t->->-> Send email to gdsjaar@sandia.gov for exomatlab support.<-<-<-\n"); exit(EXIT_SUCCESS); @@ -246,13 +247,13 @@ namespace { StringVector name_id = SLIB::tokenize(*I, ":"); std::string var_name = LowerCase(name_id[0]); if (name_id.size() == 1) { - (*variable_list).push_back(std::make_pair(var_name, 0)); + (*variable_list).emplace_back(var_name, 0); } else { for (size_t i = 1; i < name_id.size(); i++) { // Convert string to integer... int id = std::stoi(name_id[i]); - (*variable_list).push_back(std::make_pair(var_name, id)); + (*variable_list).emplace_back(var_name, id); } } ++I; diff --git a/packages/seacas/applications/mat2exo/mat2exo.C b/packages/seacas/applications/mat2exo/mat2exo.C index cce94861af..4e78276f03 100644 --- a/packages/seacas/applications/mat2exo/mat2exo.C +++ b/packages/seacas/applications/mat2exo/mat2exo.C @@ -357,7 +357,7 @@ std::vector matGetStr(const std::string &name) { matvar_t *matvar = Mat_VarRead(mat_file, name.c_str()); if (matvar == nullptr) { - return std::vector(); + return {}; } if (matvar->dims[0] != 1) { diff --git a/packages/seacas/applications/nas2exo/N2EExoWriter.C b/packages/seacas/applications/nas2exo/N2EExoWriter.C index a564e1be66..163da40c34 100644 --- a/packages/seacas/applications/nas2exo/N2EExoWriter.C +++ b/packages/seacas/applications/nas2exo/N2EExoWriter.C @@ -97,23 +97,22 @@ namespace ExoModules { bool result{true}; // Now we write the nodes - size_t num_nodes = this->gridList.size(); - double *x = new double[num_nodes]; - double *y = new double[num_nodes]; - double *z = new double[num_nodes]; + size_t num_nodes = this->gridList.size(); + std::vector x; + std::vector y; + std::vector z; + x.reserve(num_nodes); + y.reserve(num_nodes); + z.reserve(num_nodes); for (size_t i = 0; i < num_nodes; i++) { N2EPoint3D crd = std::get<1>(this->gridList[i]); - x[i] = crd.x[0]; - y[i] = crd.x[1]; - z[i] = crd.x[2]; + x.push_back(crd.x[0]); + y.push_back(crd.x[1]); + z.push_back(crd.x[2]); } - int ret = ex_put_coord(this->exoFileID, x, y, z); - - delete[] x; - delete[] y; - delete[] z; + int ret = ex_put_coord(this->exoFileID, x.data(), y.data(), z.data()); if (ret != 0) { std::cerr << "Problem writing node coordinates in N2EExoWriter::writeFile(). punching out.\n"; @@ -192,8 +191,8 @@ namespace ExoModules { numNodesCopied += nodes_per_elem; } - retvalue = - ex_put_conn(this->exoFileID, thisElType.elementType, block, elemCon.data(), NULL, NULL); + retvalue = ex_put_conn(this->exoFileID, thisElType.elementType, block, elemCon.data(), + nullptr, nullptr); switch (thisElType.numNodesPerElem) { diff --git a/packages/seacas/applications/nas2exo/N2ENasReader.C b/packages/seacas/applications/nas2exo/N2ENasReader.C index f5f5aedaff..910355088b 100644 --- a/packages/seacas/applications/nas2exo/N2ENasReader.C +++ b/packages/seacas/applications/nas2exo/N2ENasReader.C @@ -2,7 +2,7 @@ // Name : testnas2exo.cpp // Author : Ramon J. Moral (STRA LLC), John Niederhaus (Coordinator, SNL) // Version : -// Copyright : (c) Sandia National Labs 2020, 2021, 2022 +// Copyright : (c) Sandia National Labs 2020, 2021, 2022, 2023 // Description : Testing nas2exo Library, C++ 14 //============================================================================ @@ -23,7 +23,7 @@ namespace NasModules { // C++ 14 version // this->inStream = make_unique(this->inFileName); // C++ 11 version - this->inStream.reset(new std::ifstream(this->inFileName)); + this->inStream = std::make_unique(this->inFileName); // Let's set the buffer this->inStream->rdbuf()->pubsetbuf(this->_readBuffer, sizeof(this->_readBuffer)); diff --git a/packages/seacas/applications/nas2exo/nas2exo.C b/packages/seacas/applications/nas2exo/nas2exo.C index 53e67590b8..4e01d573f3 100644 --- a/packages/seacas/applications/nas2exo/nas2exo.C +++ b/packages/seacas/applications/nas2exo/nas2exo.C @@ -103,7 +103,7 @@ int main(int argc, char *argv[]) } // Save some memory - reader.reset(NULL); + reader.reset(nullptr); if (!writer.writeFile()) { diff --git a/packages/seacas/applications/nem_slice/elb_loadbal.C b/packages/seacas/applications/nem_slice/elb_loadbal.C index 29bb2c0c3b..8cfbccd210 100644 --- a/packages/seacas/applications/nem_slice/elb_loadbal.C +++ b/packages/seacas/applications/nem_slice/elb_loadbal.C @@ -1998,8 +1998,8 @@ namespace { */ time1 = get_time(); for (INT pcnt = 1; pcnt < machine->num_procs; pcnt++) { - int save_fv1 = 0; - int64_t size = + int save_fv1 = 0; + auto size = static_cast(lb->e_cmap_procs[pcnt].size()); /* Define shortcuts size and procs */ std::vector procs = lb->e_cmap_procs[pcnt]; diff --git a/packages/seacas/applications/nem_slice/fix_column_partitions.C b/packages/seacas/applications/nem_slice/fix_column_partitions.C index 7a7f9d2825..0414d72de7 100644 --- a/packages/seacas/applications/nem_slice/fix_column_partitions.C +++ b/packages/seacas/applications/nem_slice/fix_column_partitions.C @@ -317,14 +317,14 @@ int fix_column_partitions(LB_Description *lb, Mesh_Description const * std::vector colelems; colelems.reserve(nabove + nbelow + 1); - typename std::vector::reverse_iterator rit = above_list.rbegin(); + auto rit = above_list.rbegin(); while (rit != above_list.rend()) { colelems.push_back(*rit); ++rit; } colelems.push_back(i); - typename std::vector::iterator it = below_list.begin(); + auto it = below_list.begin(); while (it != below_list.end()) { colelems.push_back(*it); ++it; @@ -347,16 +347,16 @@ int fix_column_partitions(LB_Description *lb, Mesh_Description const * std::pair::iterator, bool> status = procid_elcount.insert(std::pair(procid, 1)); if (!status.second) { // procid already in map; could not insert - std::map::iterator itmap = status.first; + auto itmap = status.first; (itmap->second)++; } ++it; } // Which processor has a dominant presence in this column? - int max_procid = -1; - int max_elems = 0; - std::map::iterator itmap = procid_elcount.begin(); + int max_procid = -1; + int max_elems = 0; + auto itmap = procid_elcount.begin(); while (itmap != procid_elcount.end()) { if (itmap->second > max_elems) { max_procid = itmap->first; diff --git a/packages/seacas/applications/slice/SL_SystemInterface.C b/packages/seacas/applications/slice/SL_SystemInterface.C index e27c084785..b7e7c7c676 100644 --- a/packages/seacas/applications/slice/SL_SystemInterface.C +++ b/packages/seacas/applications/slice/SL_SystemInterface.C @@ -431,10 +431,7 @@ void SystemInterface::parse_step_option(const char *tokens) if (strchr(tokens, ':') != nullptr) { // The string contains a separator - int vals[3]; - vals[0] = stepMin_; - vals[1] = stepMax_; - vals[2] = stepInterval_; + std::array vals = {stepMin_, stepMax_, stepInterval_}; int j = 0; for (int &val : vals) { diff --git a/packages/seacas/applications/slice/Slice.C b/packages/seacas/applications/slice/Slice.C index 13ed891489..29274e3c5b 100644 --- a/packages/seacas/applications/slice/Slice.C +++ b/packages/seacas/applications/slice/Slice.C @@ -1287,7 +1287,7 @@ namespace { } } for (size_t p = 0; p < proc_count; p++) { - Ioss::NodeBlock *nb = + auto *nb = new Ioss::NodeBlock(proc_region[p]->get_database(), "node_block1", on_proc_count[p], 3); proc_region[p]->add(nb); if (debug_level & 2) { diff --git a/packages/seacas/applications/zellij/Cell.C b/packages/seacas/applications/zellij/Cell.C index 3d67a38282..20841364e8 100644 --- a/packages/seacas/applications/zellij/Cell.C +++ b/packages/seacas/applications/zellij/Cell.C @@ -260,8 +260,7 @@ size_t Cell::processor_boundary_node_count() const // Iterate `ranks` and for each rank, "color" the `bnd_nodes` that that rank touches... // Skip center. size_t b_count = 0; - for (int i = 0; i < (int)ranks.size(); i++) { - auto the_rank = ranks[i]; + for (auto the_rank : ranks) { if (the_rank == rank(Loc::C)) { continue; } diff --git a/packages/seacas/libraries/aprepro_lib/FlexLexer.h b/packages/seacas/libraries/aprepro_lib/FlexLexer.h index 863c8d4137..b3b37d033a 100644 --- a/packages/seacas/libraries/aprepro_lib/FlexLexer.h +++ b/packages/seacas/libraries/aprepro_lib/FlexLexer.h @@ -2,7 +2,7 @@ // FlexLexer.h -- define interfaces for lexical analyzer classes generated // by flex -// Copyright (c) 1993 The Regents of the University of California. +// Copyright (c) 1993, 2023 The Regents of the University of California. // All rights reserved. // // This code is derived from software contributed to Berkeley by @@ -51,7 +51,7 @@ #include "aprepro_parser.h" extern "C++" { - +// NOLINTBEGIN struct yy_buffer_state; typedef int yy_state_type; @@ -194,6 +194,7 @@ class yyFlexLexer : public FlexLexer int yy_more_offset; int yy_prev_more_offset; }; +// NOLINTEND } #endif // yyFlexLexer || ! yyFlexLexerOnce diff --git a/packages/seacas/libraries/aprepro_lib/apr_parser.cc b/packages/seacas/libraries/aprepro_lib/apr_parser.cc index b381df7df5..46814d8450 100644 --- a/packages/seacas/libraries/aprepro_lib/apr_parser.cc +++ b/packages/seacas/libraries/aprepro_lib/apr_parser.cc @@ -555,7 +555,7 @@ namespace SEAMS { case 6: // line: LBRACE sexp RBRACE #line 137 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { - if (echo && (yystack_[1].value.string) != NULL) { + if (echo && (yystack_[1].value.string) != nullptr) { aprepro.lexer->LexerOutput((yystack_[1].value.string), strlen((yystack_[1].value.string))); } @@ -779,7 +779,7 @@ namespace SEAMS { #line 172 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[3].value.tptr), - (yystack_[3].value.tptr)->value.arrfnct_c == NULL)) + (yystack_[3].value.tptr)->value.arrfnct_c == nullptr)) (yylhs.value.arrval) = (*((yystack_[3].value.tptr)->value.arrfnct_c))((yystack_[1].value.string)); else @@ -792,7 +792,7 @@ namespace SEAMS { #line 178 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[5].value.tptr), - (yystack_[5].value.tptr)->value.arrfnct_cd == NULL)) + (yystack_[5].value.tptr)->value.arrfnct_cd == nullptr)) (yylhs.value.arrval) = (*((yystack_[5].value.tptr)->value.arrfnct_cd))( (yystack_[3].value.string), (yystack_[1].value.val)); else @@ -805,7 +805,7 @@ namespace SEAMS { #line 184 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[5].value.tptr), - (yystack_[5].value.tptr)->value.arrfnct_cc == NULL)) + (yystack_[5].value.tptr)->value.arrfnct_cc == nullptr)) (yylhs.value.arrval) = (*((yystack_[5].value.tptr)->value.arrfnct_cc))( (yystack_[3].value.string), (yystack_[1].value.string)); else @@ -818,7 +818,7 @@ namespace SEAMS { #line 190 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[7].value.tptr), - (yystack_[7].value.tptr)->value.arrfnct_ddd == NULL)) + (yystack_[7].value.tptr)->value.arrfnct_ddd == nullptr)) (yylhs.value.arrval) = (*((yystack_[7].value.tptr)->value.arrfnct_ddd))( (yystack_[5].value.val), (yystack_[3].value.val), (yystack_[1].value.val)); else @@ -831,7 +831,7 @@ namespace SEAMS { #line 196 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[5].value.tptr), - (yystack_[5].value.tptr)->value.arrfnct_dd == NULL)) + (yystack_[5].value.tptr)->value.arrfnct_dd == nullptr)) (yylhs.value.arrval) = (*((yystack_[5].value.tptr)->value.arrfnct_dd))( (yystack_[3].value.val), (yystack_[1].value.val)); else @@ -844,7 +844,7 @@ namespace SEAMS { #line 202 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[3].value.tptr), - (yystack_[3].value.tptr)->value.arrfnct_d == NULL)) + (yystack_[3].value.tptr)->value.arrfnct_d == nullptr)) (yylhs.value.arrval) = (*((yystack_[3].value.tptr)->value.arrfnct_d))((yystack_[1].value.val)); else @@ -857,7 +857,7 @@ namespace SEAMS { #line 208 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[3].value.tptr), - (yystack_[3].value.tptr)->value.arrfnct_a == NULL)) + (yystack_[3].value.tptr)->value.arrfnct_a == nullptr)) (yylhs.value.arrval) = (*((yystack_[3].value.tptr)->value.arrfnct_a))((yystack_[1].value.arrval)); else @@ -1080,7 +1080,7 @@ namespace SEAMS { #line 276 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[3].value.tptr), - (yystack_[3].value.tptr)->value.strfnct_c == NULL)) + (yystack_[3].value.tptr)->value.strfnct_c == nullptr)) (yylhs.value.string) = (char *)(*((yystack_[3].value.tptr)->value.strfnct_c))( (yystack_[1].value.string)); else @@ -1093,7 +1093,7 @@ namespace SEAMS { #line 282 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[2].value.tptr), - (yystack_[2].value.tptr)->value.strfnct == NULL)) + (yystack_[2].value.tptr)->value.strfnct == nullptr)) (yylhs.value.string) = (char *)(*((yystack_[2].value.tptr)->value.strfnct))(); else (yylhs.value.string) = (char *)""; @@ -1105,7 +1105,7 @@ namespace SEAMS { #line 288 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[3].value.tptr), - (yystack_[3].value.tptr)->value.strfnct_d == NULL)) + (yystack_[3].value.tptr)->value.strfnct_d == nullptr)) (yylhs.value.string) = (char *)(*((yystack_[3].value.tptr)->value.strfnct_d))((yystack_[1].value.val)); else @@ -1118,7 +1118,7 @@ namespace SEAMS { #line 294 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[3].value.tptr), - (yystack_[3].value.tptr)->value.strfnct_a == NULL)) + (yystack_[3].value.tptr)->value.strfnct_a == nullptr)) (yylhs.value.string) = (char *)(*((yystack_[3].value.tptr)->value.strfnct_a))( (yystack_[1].value.arrval)); else @@ -1140,7 +1140,7 @@ namespace SEAMS { #line 301 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[5].value.tptr), - (yystack_[5].value.tptr)->value.strfnct_dd == NULL)) + (yystack_[5].value.tptr)->value.strfnct_dd == nullptr)) (yylhs.value.string) = (char *)(*((yystack_[5].value.tptr)->value.strfnct_dd))( (yystack_[3].value.val), (yystack_[1].value.val)); else @@ -1153,7 +1153,7 @@ namespace SEAMS { #line 307 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[11].value.tptr), - (yystack_[11].value.tptr)->value.strfnct_dcccc == NULL)) + (yystack_[11].value.tptr)->value.strfnct_dcccc == nullptr)) (yylhs.value.string) = (char *)(*((yystack_[11].value.tptr)->value.strfnct_dcccc))( (yystack_[9].value.val), (yystack_[7].value.string), (yystack_[5].value.string), (yystack_[3].value.string), (yystack_[1].value.string)); @@ -1167,7 +1167,7 @@ namespace SEAMS { #line 313 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[7].value.tptr), - (yystack_[7].value.tptr)->value.strfnct_dcc == NULL)) + (yystack_[7].value.tptr)->value.strfnct_dcc == nullptr)) (yylhs.value.string) = (char *)(*((yystack_[7].value.tptr)->value.strfnct_dcc))( (yystack_[5].value.val), (yystack_[3].value.string), (yystack_[1].value.string)); else @@ -1180,7 +1180,7 @@ namespace SEAMS { #line 319 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[7].value.tptr), - (yystack_[7].value.tptr)->value.strfnct_ccc == NULL)) + (yystack_[7].value.tptr)->value.strfnct_ccc == nullptr)) (yylhs.value.string) = (char *)(*((yystack_[7].value.tptr)->value.strfnct_ccc))( (yystack_[5].value.string), (yystack_[3].value.string), (yystack_[1].value.string)); @@ -1194,7 +1194,7 @@ namespace SEAMS { #line 325 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[5].value.tptr), - (yystack_[5].value.tptr)->value.strfnct_cc == NULL)) + (yystack_[5].value.tptr)->value.strfnct_cc == nullptr)) (yylhs.value.string) = (char *)(*((yystack_[5].value.tptr)->value.strfnct_cc))( (yystack_[3].value.string), (yystack_[1].value.string)); else @@ -1585,7 +1585,7 @@ namespace SEAMS { #line 408 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[2].value.tptr), - (yystack_[2].value.tptr)->value.fnctptr == NULL)) + (yystack_[2].value.tptr)->value.fnctptr == nullptr)) (yylhs.value.val) = (*((yystack_[2].value.tptr)->value.fnctptr))(); else (yylhs.value.val) = 0.0; @@ -1597,7 +1597,7 @@ namespace SEAMS { #line 415 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[3].value.tptr), - (yystack_[3].value.tptr)->value.fnctptr_d == NULL)) + (yystack_[3].value.tptr)->value.fnctptr_d == nullptr)) (yylhs.value.val) = (*((yystack_[3].value.tptr)->value.fnctptr_d))((yystack_[1].value.val)); else @@ -1610,7 +1610,7 @@ namespace SEAMS { #line 422 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[3].value.tptr), - (yystack_[3].value.tptr)->value.fnctptr_c == NULL)) + (yystack_[3].value.tptr)->value.fnctptr_c == nullptr)) (yylhs.value.val) = (*((yystack_[3].value.tptr)->value.fnctptr_c))((yystack_[1].value.string)); else @@ -1623,7 +1623,7 @@ namespace SEAMS { #line 429 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[3].value.tptr), - (yystack_[3].value.tptr)->value.fnctptr_a == NULL)) + (yystack_[3].value.tptr)->value.fnctptr_a == nullptr)) (yylhs.value.val) = (*((yystack_[3].value.tptr)->value.fnctptr_a))((yystack_[1].value.arrval)); else @@ -1636,7 +1636,7 @@ namespace SEAMS { #line 436 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[5].value.tptr), - (yystack_[5].value.tptr)->value.fnctptr_cd == NULL)) + (yystack_[5].value.tptr)->value.fnctptr_cd == nullptr)) (yylhs.value.val) = (*((yystack_[5].value.tptr)->value.fnctptr_cd))( (yystack_[3].value.string), (yystack_[1].value.val)); else @@ -1649,7 +1649,7 @@ namespace SEAMS { #line 443 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[5].value.tptr), - (yystack_[5].value.tptr)->value.fnctptr_dc == NULL)) + (yystack_[5].value.tptr)->value.fnctptr_dc == nullptr)) (yylhs.value.val) = (*((yystack_[5].value.tptr)->value.fnctptr_dc))( (yystack_[3].value.val), (yystack_[1].value.string)); else @@ -1662,7 +1662,7 @@ namespace SEAMS { #line 450 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[5].value.tptr), - (yystack_[5].value.tptr)->value.fnctptr_cc == NULL)) + (yystack_[5].value.tptr)->value.fnctptr_cc == nullptr)) (yylhs.value.val) = (*((yystack_[5].value.tptr)->value.fnctptr_cc))( (yystack_[3].value.string), (yystack_[1].value.string)); else @@ -1675,7 +1675,7 @@ namespace SEAMS { #line 457 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[7].value.tptr), - (yystack_[7].value.tptr)->value.fnctptr_ccc == NULL)) + (yystack_[7].value.tptr)->value.fnctptr_ccc == nullptr)) (yylhs.value.val) = (*((yystack_[7].value.tptr)->value.fnctptr_ccc))( (yystack_[5].value.string), (yystack_[3].value.string), (yystack_[1].value.string)); @@ -1689,7 +1689,7 @@ namespace SEAMS { #line 464 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[5].value.tptr), - (yystack_[5].value.tptr)->value.fnctptr_dd == NULL)) + (yystack_[5].value.tptr)->value.fnctptr_dd == nullptr)) (yylhs.value.val) = (*((yystack_[5].value.tptr)->value.fnctptr_dd))( (yystack_[3].value.val), (yystack_[1].value.val)); else @@ -1702,7 +1702,7 @@ namespace SEAMS { #line 470 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[7].value.tptr), - (yystack_[7].value.tptr)->value.fnctptr_ddd == NULL)) + (yystack_[7].value.tptr)->value.fnctptr_ddd == nullptr)) (yylhs.value.val) = (*((yystack_[7].value.tptr)->value.fnctptr_ddd))( (yystack_[5].value.val), (yystack_[3].value.val), (yystack_[1].value.val)); else @@ -1715,7 +1715,7 @@ namespace SEAMS { #line 476 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[7].value.tptr), - (yystack_[7].value.tptr)->value.fnctptr_ccd == NULL)) + (yystack_[7].value.tptr)->value.fnctptr_ccd == nullptr)) (yylhs.value.val) = (*((yystack_[7].value.tptr)->value.fnctptr_ccd))( (yystack_[5].value.string), (yystack_[3].value.string), (yystack_[1].value.val)); else @@ -1728,7 +1728,7 @@ namespace SEAMS { #line 482 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[9].value.tptr), - (yystack_[9].value.tptr)->value.fnctptr_dddd == NULL)) + (yystack_[9].value.tptr)->value.fnctptr_dddd == nullptr)) (yylhs.value.val) = (*((yystack_[9].value.tptr)->value.fnctptr_dddd))( (yystack_[7].value.val), (yystack_[5].value.val), (yystack_[3].value.val), (yystack_[1].value.val)); @@ -1742,7 +1742,7 @@ namespace SEAMS { #line 488 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[9].value.tptr), - (yystack_[9].value.tptr)->value.fnctptr_dddd == NULL)) + (yystack_[9].value.tptr)->value.fnctptr_dddd == nullptr)) (yylhs.value.val) = (*((yystack_[9].value.tptr)->value.fnctptr_dddd))( (yystack_[7].value.val), (yystack_[5].value.val), (yystack_[3].value.val), (yystack_[1].value.val)); @@ -1756,7 +1756,7 @@ namespace SEAMS { #line 494 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[11].value.tptr), - (yystack_[11].value.tptr)->value.fnctptr_ddddc == NULL)) + (yystack_[11].value.tptr)->value.fnctptr_ddddc == nullptr)) (yylhs.value.val) = (*((yystack_[11].value.tptr)->value.fnctptr_ddddc))( (yystack_[9].value.val), (yystack_[7].value.val), (yystack_[5].value.val), (yystack_[3].value.val), (yystack_[1].value.string)); @@ -1770,7 +1770,7 @@ namespace SEAMS { #line 500 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[13].value.tptr), - (yystack_[13].value.tptr)->value.fnctptr_dddddd == NULL)) + (yystack_[13].value.tptr)->value.fnctptr_dddddd == nullptr)) (yylhs.value.val) = (*((yystack_[13].value.tptr)->value.fnctptr_dddddd))( (yystack_[11].value.val), (yystack_[9].value.val), (yystack_[7].value.val), (yystack_[5].value.val), (yystack_[3].value.val), (yystack_[1].value.val)); diff --git a/packages/seacas/libraries/aprepro_lib/aprepro_parser.h b/packages/seacas/libraries/aprepro_lib/aprepro_parser.h index 56f294416e..3c99dfe7d8 100644 --- a/packages/seacas/libraries/aprepro_lib/aprepro_parser.h +++ b/packages/seacas/libraries/aprepro_lib/aprepro_parser.h @@ -2,7 +2,7 @@ // Skeleton interface for Bison LALR(1) parsers in C++ -// Copyright (C) 2002-2015, 2018-2021 Free Software Foundation, Inc. +// Copyright (C) 2002-2015, 2018-2021, 2023 Free Software Foundation, Inc. // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -44,6 +44,7 @@ #ifndef YY_SEAMS_APREPRO_PARSER_H_INCLUDED #define YY_SEAMS_APREPRO_PARSER_H_INCLUDED +// NOLINTBEGIN #include // std::abort #include #include @@ -792,4 +793,5 @@ namespace SEAMS { } // namespace SEAMS #line 881 "aprepro_parser.h" +// NOLINTEND #endif // !YY_SEAMS_APREPRO_PARSER_H_INCLUDED diff --git a/packages/seacas/libraries/ioss/src/Ioss_Assembly.C b/packages/seacas/libraries/ioss/src/Ioss_Assembly.C index 4325e5d7fb..468567a5b6 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_Assembly.C +++ b/packages/seacas/libraries/ioss/src/Ioss_Assembly.C @@ -17,7 +17,7 @@ #include namespace { - std::string id_str() { return std::string("id"); } + std::string id_str() { return {"id"}; } void check_is_valid(const Ioss::Assembly *assem, const Ioss::GroupingEntity *member) { // Ensure that `member` is not already a member and that its type matches @@ -147,10 +147,10 @@ int64_t Ioss::Assembly::internal_get_zc_field_data(const Field &field, void **da Ioss::Property Ioss::Assembly::get_implicit_property(const std::string &my_name) const { if (my_name == "member_count") { - return Ioss::Property(my_name, static_cast(m_members.size())); + return {my_name, static_cast(m_members.size())}; } if (my_name == "member_type") { - return Ioss::Property(my_name, static_cast(m_type)); + return {my_name, static_cast(m_type)}; } return Ioss::GroupingEntity::get_implicit_property(my_name); diff --git a/packages/seacas/libraries/ioss/src/Ioss_CodeTypes.h b/packages/seacas/libraries/ioss/src/Ioss_CodeTypes.h index 9b978eae03..ff8eb0609e 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_CodeTypes.h +++ b/packages/seacas/libraries/ioss/src/Ioss_CodeTypes.h @@ -24,10 +24,10 @@ namespace Ioss { using IJK_t = std::array; } // namespace Ioss -inline std::string IOSS_SCALAR() { return std::string("scalar"); } -inline std::string IOSS_VECTOR_2D() { return std::string("vector_2d"); } -inline std::string IOSS_VECTOR_3D() { return std::string("vector_3d"); } -inline std::string IOSS_SYM_TENSOR() { return std::string("sym_tensor_33"); } +inline std::string IOSS_SCALAR() { return {"scalar"}; } +inline std::string IOSS_VECTOR_2D() { return {"vector_2d"}; } +inline std::string IOSS_VECTOR_3D() { return {"vector_3d"}; } +inline std::string IOSS_SYM_TENSOR() { return {"sym_tensor_33"}; } #if defined(BUILT_IN_SIERRA) #define SEACAS_HAVE_MPI diff --git a/packages/seacas/libraries/ioss/src/Ioss_ConcreteVariableType.C b/packages/seacas/libraries/ioss/src/Ioss_ConcreteVariableType.C index 221dbb9096..66d7351ccd 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_ConcreteVariableType.C +++ b/packages/seacas/libraries/ioss/src/Ioss_ConcreteVariableType.C @@ -11,45 +11,45 @@ #include namespace { - std::string X() { return std::string("x"); } - std::string Y() { return std::string("y"); } - std::string Z() { return std::string("z"); } - std::string Q() { return std::string("q"); } - std::string S() { return std::string("s"); } - - std::string XX() { return std::string("xx"); } - std::string YY() { return std::string("yy"); } - std::string ZZ() { return std::string("zz"); } - std::string XY() { return std::string("xy"); } - std::string YZ() { return std::string("yz"); } - std::string ZX() { return std::string("zx"); } - std::string YX() { return std::string("yx"); } - std::string ZY() { return std::string("zy"); } - std::string XZ() { return std::string("xz"); } - - std::string invalid() { return std::string("invalid"); } - std::string scalar() { return std::string("scalar"); } - std::string vector_2d() { return std::string("vector_2d"); } - std::string vector_3d() { return std::string("vector_3d"); } - std::string quaternion_2d() { return std::string("quaternion_2d"); } - std::string quaternion_3d() { return std::string("quaternion_3d"); } - std::string full_tensor_36() { return std::string("full_tensor_36"); } - std::string full_tensor_32() { return std::string("full_tensor_32"); } - std::string full_tensor_22() { return std::string("full_tensor_22"); } - std::string full_tensor_16() { return std::string("full_tensor_16"); } - std::string full_tensor_12() { return std::string("full_tensor_12"); } - std::string sym_tensor_33() { return std::string("sym_tensor_33"); } - std::string sym_tensor_31() { return std::string("sym_tensor_31"); } - std::string sym_tensor_21() { return std::string("sym_tensor_21"); } - std::string sym_tensor_13() { return std::string("sym_tensor_13"); } - std::string sym_tensor_11() { return std::string("sym_tensor_11"); } - std::string sym_tensor_10() { return std::string("sym_tensor_10"); } - std::string asym_tensor_03() { return std::string("asym_tensor_03"); } - std::string asym_tensor_02() { return std::string("asym_tensor_02"); } - std::string asym_tensor_01() { return std::string("asym_tensor_01"); } - std::string matrix_22() { return std::string("matrix_22"); } - std::string matrix_33() { return std::string("matrix_33"); } - std::string testonly() { return std::string("testonly"); } + std::string X() { return {"x"}; } + std::string Y() { return {"y"}; } + std::string Z() { return {"z"}; } + std::string Q() { return {"q"}; } + std::string S() { return {"s"}; } + + std::string XX() { return {"xx"}; } + std::string YY() { return {"yy"}; } + std::string ZZ() { return {"zz"}; } + std::string XY() { return {"xy"}; } + std::string YZ() { return {"yz"}; } + std::string ZX() { return {"zx"}; } + std::string YX() { return {"yx"}; } + std::string ZY() { return {"zy"}; } + std::string XZ() { return {"xz"}; } + + std::string invalid() { return {"invalid"}; } + std::string scalar() { return {"scalar"}; } + std::string vector_2d() { return {"vector_2d"}; } + std::string vector_3d() { return {"vector_3d"}; } + std::string quaternion_2d() { return {"quaternion_2d"}; } + std::string quaternion_3d() { return {"quaternion_3d"}; } + std::string full_tensor_36() { return {"full_tensor_36"}; } + std::string full_tensor_32() { return {"full_tensor_32"}; } + std::string full_tensor_22() { return {"full_tensor_22"}; } + std::string full_tensor_16() { return {"full_tensor_16"}; } + std::string full_tensor_12() { return {"full_tensor_12"}; } + std::string sym_tensor_33() { return {"sym_tensor_33"}; } + std::string sym_tensor_31() { return {"sym_tensor_31"}; } + std::string sym_tensor_21() { return {"sym_tensor_21"}; } + std::string sym_tensor_13() { return {"sym_tensor_13"}; } + std::string sym_tensor_11() { return {"sym_tensor_11"}; } + std::string sym_tensor_10() { return {"sym_tensor_10"}; } + std::string asym_tensor_03() { return {"asym_tensor_03"}; } + std::string asym_tensor_02() { return {"asym_tensor_02"}; } + std::string asym_tensor_01() { return {"asym_tensor_01"}; } + std::string matrix_22() { return {"matrix_22"}; } + std::string matrix_33() { return {"matrix_33"}; } + std::string testonly() { return {"testonly"}; } } // namespace Ioss::StorageInitializer::StorageInitializer() diff --git a/packages/seacas/libraries/ioss/src/Ioss_ElementTopology.C b/packages/seacas/libraries/ioss/src/Ioss_ElementTopology.C index 1fc7dac108..0e4bea10c0 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_ElementTopology.C +++ b/packages/seacas/libraries/ioss/src/Ioss_ElementTopology.C @@ -298,7 +298,7 @@ Ioss::IntVector Ioss::ElementTopology::boundary_connectivity(int bnd_number) con return Ioss::IntVector{bnd_number - 1}; } } - return Ioss::IntVector(); + return {}; } Ioss::ElementTopology *Ioss::ElementTopology::boundary_type(int bnd_number) const diff --git a/packages/seacas/libraries/ioss/src/Ioss_EntityBlock.C b/packages/seacas/libraries/ioss/src/Ioss_EntityBlock.C index 303705dcda..279cf69ac9 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_EntityBlock.C +++ b/packages/seacas/libraries/ioss/src/Ioss_EntityBlock.C @@ -71,10 +71,10 @@ Ioss::EntityBlock::EntityBlock(Ioss::DatabaseIO *io_database, const std::string Ioss::Property Ioss::EntityBlock::get_implicit_property(const std::string &my_name) const { if (my_name == "topology_node_count") { - return Ioss::Property(my_name, topology()->number_nodes()); + return {my_name, topology()->number_nodes()}; } if (my_name == "topology_type") { - return Ioss::Property(my_name, topology()->name()); + return {my_name, topology()->name()}; } return Ioss::GroupingEntity::get_implicit_property(my_name); diff --git a/packages/seacas/libraries/ioss/src/Ioss_Field.C b/packages/seacas/libraries/ioss/src/Ioss_Field.C index 994064ed62..f36e599938 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_Field.C +++ b/packages/seacas/libraries/ioss/src/Ioss_Field.C @@ -347,14 +347,14 @@ std::string Ioss::Field::type_string() const { return type_string(get_type()); } std::string Ioss::Field::type_string(Ioss::Field::BasicType type) { switch (type) { - case Ioss::Field::REAL: return std::string("real"); - case Ioss::Field::INTEGER: return std::string("integer"); - case Ioss::Field::INT64: return std::string("64-bit integer"); - case Ioss::Field::COMPLEX: return std::string("complex"); - case Ioss::Field::STRING: return std::string("string"); - case Ioss::Field::CHARACTER: return std::string("char"); - case Ioss::Field::INVALID: return std::string("invalid"); - default: return std::string("internal error"); + case Ioss::Field::REAL: return {"real"}; + case Ioss::Field::INTEGER: return {"integer"}; + case Ioss::Field::INT64: return {"64-bit integer"}; + case Ioss::Field::COMPLEX: return {"complex"}; + case Ioss::Field::STRING: return {"string"}; + case Ioss::Field::CHARACTER: return {"char"}; + case Ioss::Field::INVALID: return {"invalid"}; + default: return {"internal error"}; } } @@ -363,14 +363,14 @@ std::string Ioss::Field::role_string() const { return role_string(get_role()); } std::string Ioss::Field::role_string(Ioss::Field::RoleType role) { switch (role) { - case Ioss::Field::INTERNAL: return std::string("Internal"); - case Ioss::Field::MESH: return std::string("Mesh"); - case Ioss::Field::ATTRIBUTE: return std::string("Attribute"); - case Ioss::Field::COMMUNICATION: return std::string("Communication"); - case Ioss::Field::MESH_REDUCTION: return std::string("Mesh Reduction"); - case Ioss::Field::REDUCTION: return std::string("Reduction"); - case Ioss::Field::TRANSIENT: return std::string("Transient"); - default: return std::string("internal error"); + case Ioss::Field::INTERNAL: return {"Internal"}; + case Ioss::Field::MESH: return {"Mesh"}; + case Ioss::Field::ATTRIBUTE: return {"Attribute"}; + case Ioss::Field::COMMUNICATION: return {"Communication"}; + case Ioss::Field::MESH_REDUCTION: return {"Mesh Reduction"}; + case Ioss::Field::REDUCTION: return {"Reduction"}; + case Ioss::Field::TRANSIENT: return {"Transient"}; + default: return {"internal error"}; } } diff --git a/packages/seacas/libraries/ioss/src/Ioss_FieldManager.h b/packages/seacas/libraries/ioss/src/Ioss_FieldManager.h index 15cb457960..c843a4c189 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_FieldManager.h +++ b/packages/seacas/libraries/ioss/src/Ioss_FieldManager.h @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2022 National Technology & Engineering Solutions +// Copyright(C) 1999-2023 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -34,8 +34,8 @@ namespace Ioss { class IOSS_EXPORT FieldManager { public: - FieldManager() = default; - FieldManager(const FieldManager &other) : fields(other.fields) {} + FieldManager() = default; + FieldManager(const FieldManager &other) = default; FieldManager &operator=(const FieldManager &) = delete; ~FieldManager() = default; diff --git a/packages/seacas/libraries/ioss/src/Ioss_FileInfo.C b/packages/seacas/libraries/ioss/src/Ioss_FileInfo.C index 5b3450fd03..b806b95377 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_FileInfo.C +++ b/packages/seacas/libraries/ioss/src/Ioss_FileInfo.C @@ -283,7 +283,7 @@ namespace Ioss { return filename_.substr(ind + 1, filename_.size()); } - return std::string(); + return {}; } std::string FileInfo::pathname() const @@ -293,7 +293,7 @@ namespace Ioss { return filename_.substr(0, ind); } - return std::string(); + return {}; } std::string FileInfo::tailname() const diff --git a/packages/seacas/libraries/ioss/src/Ioss_Glob.h b/packages/seacas/libraries/ioss/src/Ioss_Glob.h index b8f574e446..b5862a0c7a 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_Glob.h +++ b/packages/seacas/libraries/ioss/src/Ioss_Glob.h @@ -22,7 +22,7 @@ namespace Ioss::glob { class IOSS_EXPORT Error : public std::exception { public: - explicit Error(const std::string &msg) : msg_{msg} {} + explicit Error(std::string msg) : msg_{std::move(msg)} {} ~Error() override; const char *what() const noexcept override { return msg_.c_str(); } @@ -94,7 +94,7 @@ namespace Ioss::glob { std::tuple Next(const String &, size_t pos) override { - return std::tuple(0, ++pos); + return {0, ++pos}; } }; @@ -107,7 +107,7 @@ namespace Ioss::glob { std::tuple Next(const String &, size_t pos) override { - return std::tuple(0, ++pos); + return {0, ++pos}; } }; @@ -205,14 +205,14 @@ namespace Ioss::glob { // the string if (comp_end) { if ((state_pos == match_state_) && (str_pos == str.length())) { - return std::tuple(state_pos == match_state_, str_pos); + return {state_pos == match_state_, str_pos}; } - return std::tuple(false, str_pos); + return {false, str_pos}; } // if comp_end is false, compare only if the states reached the // match state - return std::tuple(state_pos == match_state_, str_pos); + return {state_pos == match_state_, str_pos}; } void ResetStates() @@ -422,11 +422,11 @@ namespace Ioss::glob { for (auto &automata : automatas_) { std::tie(r, str_pos) = automata->Exec(str_part, false); if (r) { - return std::tuple(r, pos + str_pos); + return {r, pos + str_pos}; } } - return std::tuple(false, pos + str_pos); + return {false, pos + str_pos}; } bool Check(const String &str, size_t pos) override @@ -472,7 +472,7 @@ namespace Ioss::glob { return NextNeg(str, pos); } } - return std::tuple(0, 0); + return {0, 0}; } std::tuple NextNeg(const String &str, size_t pos) diff --git a/packages/seacas/libraries/ioss/src/Ioss_GroupingEntity.C b/packages/seacas/libraries/ioss/src/Ioss_GroupingEntity.C index 9083663786..e60be1f52d 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_GroupingEntity.C +++ b/packages/seacas/libraries/ioss/src/Ioss_GroupingEntity.C @@ -106,7 +106,7 @@ std::string Ioss::GroupingEntity::get_filename() const { // Ok for database_ to be nullptr at this point. if (database_ == nullptr) { - return std::string(); + return {}; } return database_->get_filename(); @@ -159,7 +159,7 @@ Ioss::Property Ioss::GroupingEntity::get_implicit_property(const std::string &my // These include: if (my_name == "attribute_count") { count_attributes(); - return Ioss::Property(my_name, static_cast(attributeCount)); + return {my_name, static_cast(attributeCount)}; } // End of the line. No property of this name exists. diff --git a/packages/seacas/libraries/ioss/src/Ioss_IOFactory.h b/packages/seacas/libraries/ioss/src/Ioss_IOFactory.h index 2b3f0c7b37..7f609d038a 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_IOFactory.h +++ b/packages/seacas/libraries/ioss/src/Ioss_IOFactory.h @@ -52,7 +52,7 @@ namespace Ioss { Ioss_MPI_Comm communicator, const Ioss::PropertyManager &properties) const = 0; - virtual std::string show_config() const { return std::string(""); } + virtual std::string show_config() const { return {""}; } static void alias(const std::string &base, const std::string &syn); diff --git a/packages/seacas/libraries/ioss/src/Ioss_Property.C b/packages/seacas/libraries/ioss/src/Ioss_Property.C index 55ef27c425..e5635885c8 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_Property.C +++ b/packages/seacas/libraries/ioss/src/Ioss_Property.C @@ -16,14 +16,14 @@ namespace { std::string type_string(Ioss::Property::BasicType type) { switch (type) { - case Ioss::Property::INVALID: return std::string("invalid"); - case Ioss::Property::REAL: return std::string("real"); - case Ioss::Property::INTEGER: return std::string("integer"); - case Ioss::Property::POINTER: return std::string("pointer"); - case Ioss::Property::STRING: return std::string("string"); - case Ioss::Property::VEC_INTEGER: return std::string("vector"); - case Ioss::Property::VEC_DOUBLE: return std::string("vector"); - default: return std::string("internal error"); + case Ioss::Property::INVALID: return {"invalid"}; + case Ioss::Property::REAL: return {"real"}; + case Ioss::Property::INTEGER: return {"integer"}; + case Ioss::Property::POINTER: return {"pointer"}; + case Ioss::Property::STRING: return {"string"}; + case Ioss::Property::VEC_INTEGER: return {"vector"}; + case Ioss::Property::VEC_DOUBLE: return {"vector"}; + default: return {"internal error"}; } } diff --git a/packages/seacas/libraries/ioss/src/Ioss_PropertyManager.C b/packages/seacas/libraries/ioss/src/Ioss_PropertyManager.C index 6d492ff6fd..0392e5616d 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_PropertyManager.C +++ b/packages/seacas/libraries/ioss/src/Ioss_PropertyManager.C @@ -14,11 +14,6 @@ #include #include -Ioss::PropertyManager::PropertyManager(const PropertyManager &from) - : m_properties(from.m_properties) -{ -} - Ioss::PropertyManager::~PropertyManager() { try { diff --git a/packages/seacas/libraries/ioss/src/Ioss_PropertyManager.h b/packages/seacas/libraries/ioss/src/Ioss_PropertyManager.h index 828a8a95bd..b6957204cf 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_PropertyManager.h +++ b/packages/seacas/libraries/ioss/src/Ioss_PropertyManager.h @@ -34,8 +34,8 @@ namespace Ioss { class IOSS_EXPORT PropertyManager { public: - PropertyManager() = default; - PropertyManager(const PropertyManager &from); + PropertyManager() = default; + PropertyManager(const PropertyManager &from) = default; PropertyManager &operator=(const PropertyManager &from) = delete; ~PropertyManager(); diff --git a/packages/seacas/libraries/ioss/src/Ioss_Region.C b/packages/seacas/libraries/ioss/src/Ioss_Region.C index b2c102ef8b..478d86a7f5 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_Region.C +++ b/packages/seacas/libraries/ioss/src/Ioss_Region.C @@ -51,10 +51,10 @@ #include namespace { - std::string id_str() { return std::string("id"); } - std::string db_name_str() { return std::string("db_name"); } - std::string orig_topo_str() { return std::string("original_topology_type"); } - std::string orig_block_order() { return std::string("original_block_order"); } + std::string id_str() { return {"id"}; } + std::string db_name_str() { return {"db_name"}; } + std::string orig_topo_str() { return {"original_topology_type"}; } + std::string orig_block_order() { return {"original_block_order"}; } template Ioss::GroupingEntity *get_entity_internal(int64_t id, const std::vector &entities) @@ -2414,71 +2414,71 @@ namespace Ioss { return nodeBlocks[0]->get_property("component_degree"); } - return Property(my_name, 0); + return {my_name, 0}; } if (my_name == "node_block_count") { - return Property(my_name, static_cast(nodeBlocks.size())); + return {my_name, static_cast(nodeBlocks.size())}; } if (my_name == "edge_block_count") { - return Property(my_name, static_cast(edgeBlocks.size())); + return {my_name, static_cast(edgeBlocks.size())}; } if (my_name == "face_block_count") { - return Property(my_name, static_cast(faceBlocks.size())); + return {my_name, static_cast(faceBlocks.size())}; } if (my_name == "element_block_count") { - return Property(my_name, static_cast(elementBlocks.size())); + return {my_name, static_cast(elementBlocks.size())}; } if (my_name == "structured_block_count") { - return Property(my_name, static_cast(structuredBlocks.size())); + return {my_name, static_cast(structuredBlocks.size())}; } if (my_name == "assembly_count") { - return Property(my_name, static_cast(assemblies.size())); + return {my_name, static_cast(assemblies.size())}; } if (my_name == "blob_count") { - return Property(my_name, static_cast(blobs.size())); + return {my_name, static_cast(blobs.size())}; } if (my_name == "side_set_count") { - return Property(my_name, static_cast(sideSets.size())); + return {my_name, static_cast(sideSets.size())}; } if (my_name == "node_set_count") { - return Property(my_name, static_cast(nodeSets.size())); + return {my_name, static_cast(nodeSets.size())}; } if (my_name == "edge_set_count") { - return Property(my_name, static_cast(edgeSets.size())); + return {my_name, static_cast(edgeSets.size())}; } if (my_name == "face_set_count") { - return Property(my_name, static_cast(faceSets.size())); + return {my_name, static_cast(faceSets.size())}; } if (my_name == "element_set_count") { - return Property(my_name, static_cast(elementSets.size())); + return {my_name, static_cast(elementSets.size())}; } if (my_name == "comm_set_count") { - return Property(my_name, static_cast(commSets.size())); + return {my_name, static_cast(commSets.size())}; } if (my_name == "coordinate_frame_count") { - return Property(my_name, static_cast(coordinateFrames.size())); + return {my_name, static_cast(coordinateFrames.size())}; } if (my_name == "state_count") { - return Property(my_name, stateCount); + return {my_name, stateCount}; } if (my_name == "current_state") { - return Property(my_name, currentState); + return {my_name, currentState}; } if (my_name == "element_count") { @@ -2486,7 +2486,7 @@ namespace Ioss { for (const auto &eb : elementBlocks) { count += eb->entity_count(); } - return Property(my_name, count); + return {my_name, count}; } if (my_name == "cell_count") { @@ -2494,7 +2494,7 @@ namespace Ioss { for (const auto &eb : structuredBlocks) { count += eb->get_property("cell_count").get_int(); } - return Property(my_name, count); + return {my_name, count}; } if (my_name == "face_count") { @@ -2502,7 +2502,7 @@ namespace Ioss { for (const auto &fb : faceBlocks) { count += fb->entity_count(); } - return Property(my_name, count); + return {my_name, count}; } if (my_name == "edge_count") { @@ -2510,7 +2510,7 @@ namespace Ioss { for (const auto &eb : edgeBlocks) { count += eb->entity_count(); } - return Property(my_name, count); + return {my_name, count}; } if (my_name == "node_count") { @@ -2518,12 +2518,12 @@ namespace Ioss { for (const auto &nb : nodeBlocks) { count += nb->entity_count(); } - return Property(my_name, count); + return {my_name, count}; } if (my_name == "database_name") { std::string filename = get_database()->get_filename(); - return Property(my_name, filename); + return {my_name, filename}; } { diff --git a/packages/seacas/libraries/ioss/src/Ioss_ScopeGuard.h b/packages/seacas/libraries/ioss/src/Ioss_ScopeGuard.h index 4f298234be..03be69d349 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_ScopeGuard.h +++ b/packages/seacas/libraries/ioss/src/Ioss_ScopeGuard.h @@ -61,7 +61,7 @@ namespace Ioss { #ifndef _MSC_VER __attribute__((unused)) #endif - typedef const ScopeGuardImplBase &ScopeGuard; + typedef const ScopeGuardImplBase &ScopeGuard; // NOLINT template class ScopeGuardImpl0 : public ScopeGuardImplBase { diff --git a/packages/seacas/libraries/ioss/src/Ioss_SideBlock.C b/packages/seacas/libraries/ioss/src/Ioss_SideBlock.C index bf7b193f66..422f62a1c7 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_SideBlock.C +++ b/packages/seacas/libraries/ioss/src/Ioss_SideBlock.C @@ -131,12 +131,12 @@ Ioss::Property Ioss::SideBlock::get_implicit_property(const std::string &my_name if (field_exists("distribution_factors")) { int64_t nnodes = topology()->number_nodes(); int64_t nside = entity_count(); - return Ioss::Property(my_name, nnodes * nside); + return {my_name, nnodes * nside}; } - return Ioss::Property(my_name, 0); + return {my_name, 0}; } if (my_name == "parent_topology_type") { - return Ioss::Property(my_name, parent_element_topology()->name()); + return {my_name, parent_element_topology()->name()}; } return Ioss::EntityBlock::get_implicit_property(my_name); diff --git a/packages/seacas/libraries/ioss/src/Ioss_SideSet.C b/packages/seacas/libraries/ioss/src/Ioss_SideSet.C index 1405e59d1c..ef9cbe3bce 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_SideSet.C +++ b/packages/seacas/libraries/ioss/src/Ioss_SideSet.C @@ -20,7 +20,7 @@ #include "Ioss_PropertyManager.h" namespace { - std::string id_str() { return std::string("id"); } + std::string id_str() { return {"id"}; } void check_for_duplicate_names(const Ioss::SideSet *sset, const Ioss::SideBlock *side_block) { const std::string &name = side_block->name(); @@ -134,10 +134,10 @@ int64_t Ioss::SideSet::internal_get_zc_field_data(const Field &field, void **dat Ioss::Property Ioss::SideSet::get_implicit_property(const std::string &my_name) const { if (my_name == "side_block_count") { - return Ioss::Property(my_name, static_cast(sideBlocks.size())); + return {my_name, static_cast(sideBlocks.size())}; } if (my_name == "block_count") { - return Ioss::Property(my_name, static_cast(sideBlocks.size())); + return {my_name, static_cast(sideBlocks.size())}; } return Ioss::GroupingEntity::get_implicit_property(my_name); diff --git a/packages/seacas/libraries/ioss/src/Ioss_StructuredBlock.C b/packages/seacas/libraries/ioss/src/Ioss_StructuredBlock.C index fea2dc0a89..999a2dd7eb 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_StructuredBlock.C +++ b/packages/seacas/libraries/ioss/src/Ioss_StructuredBlock.C @@ -274,22 +274,22 @@ namespace Ioss { Property StructuredBlock::get_implicit_property(const std::string &my_name) const { if (my_name == "ni_global") { - return Ioss::Property(my_name, m_ijkGlobal[0]); + return {my_name, m_ijkGlobal[0]}; } if (my_name == "nj_global") { - return Ioss::Property(my_name, m_ijkGlobal[1]); + return {my_name, m_ijkGlobal[1]}; } if (my_name == "nk_global") { - return Ioss::Property(my_name, m_ijkGlobal[2]); + return {my_name, m_ijkGlobal[2]}; } if (my_name == "offset_i") { - return Ioss::Property(my_name, m_offset[0]); + return {my_name, m_offset[0]}; } if (my_name == "offset_j") { - return Ioss::Property(my_name, m_offset[1]); + return {my_name, m_offset[1]}; } if (my_name == "offset_k") { - return Ioss::Property(my_name, m_offset[2]); + return {my_name, m_offset[2]}; } return EntityBlock::get_implicit_property(my_name); } diff --git a/packages/seacas/libraries/ioss/src/Ioss_Utils.C b/packages/seacas/libraries/ioss/src/Ioss_Utils.C index 4e9477d871..fa64c33959 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_Utils.C +++ b/packages/seacas/libraries/ioss/src/Ioss_Utils.C @@ -486,7 +486,7 @@ namespace { if (!found_valid) { // Return an invalid field... - return Ioss::Field("", Ioss::Field::INVALID, IOSS_SCALAR(), fld_role, 1); + return {"", Ioss::Field::INVALID, IOSS_SCALAR(), fld_role, 1}; } // At this point, name[index] should be a valid potential field @@ -617,7 +617,7 @@ namespace { } suffix_size--; } - return Ioss::Field("", Ioss::Field::INVALID, IOSS_SCALAR(), fld_role, 1); + return {"", Ioss::Field::INVALID, IOSS_SCALAR(), fld_role, 1}; } // common @@ -953,44 +953,44 @@ int64_t Ioss::Utils::get_side_offset(const Ioss::SideBlock *sb) std::string Ioss::Utils::shape_to_string(const Ioss::ElementShape &shape) { switch (shape) { - case Ioss::ElementShape::UNKNOWN: return std::string("Unknown"); - case Ioss::ElementShape::POINT: return std::string("Point"); - case Ioss::ElementShape::SPHERE: return std::string("Sphere"); - case Ioss::ElementShape::LINE: return std::string("Line"); - case Ioss::ElementShape::SPRING: return std::string("Spring"); - case Ioss::ElementShape::TRI: return std::string("Tri"); - case Ioss::ElementShape::QUAD: return std::string("Quad"); - case Ioss::ElementShape::TET: return std::string("Tet"); - case Ioss::ElementShape::PYRAMID: return std::string("Pyramid"); - case Ioss::ElementShape::WEDGE: return std::string("Wedge"); - case Ioss::ElementShape::HEX: return std::string("Hex"); - case Ioss::ElementShape::SUPER: return std::string("Super"); + case Ioss::ElementShape::UNKNOWN: return {"Unknown"}; + case Ioss::ElementShape::POINT: return {"Point"}; + case Ioss::ElementShape::SPHERE: return {"Sphere"}; + case Ioss::ElementShape::LINE: return {"Line"}; + case Ioss::ElementShape::SPRING: return {"Spring"}; + case Ioss::ElementShape::TRI: return {"Tri"}; + case Ioss::ElementShape::QUAD: return {"Quad"}; + case Ioss::ElementShape::TET: return {"Tet"}; + case Ioss::ElementShape::PYRAMID: return {"Pyramid"}; + case Ioss::ElementShape::WEDGE: return {"Wedge"}; + case Ioss::ElementShape::HEX: return {"Hex"}; + case Ioss::ElementShape::SUPER: return {"Super"}; } - return std::string("Invalid shape [") + std::to_string(unsigned(shape)) + std::string("]"); + return fmt::format("Invalid shape [{}]", unsigned(shape)); } std::string Ioss::Utils::entity_type_to_string(const Ioss::EntityType &type) { switch (type) { - case Ioss::EntityType::NODEBLOCK: return std::string("NODEBLOCK"); - case Ioss::EntityType::EDGEBLOCK: return std::string("EDGEBLOCK"); - case Ioss::EntityType::FACEBLOCK: return std::string("FACEBLOCK"); - case Ioss::EntityType::ELEMENTBLOCK: return std::string("ELEMENTBLOCK"); - case Ioss::EntityType::NODESET: return std::string("NODESET"); - case Ioss::EntityType::EDGESET: return std::string("EDGESET"); - case Ioss::EntityType::FACESET: return std::string("FACESET"); - case Ioss::EntityType::ELEMENTSET: return std::string("ELEMENTSET"); - case Ioss::EntityType::SIDESET: return std::string("SIDESET"); - case Ioss::EntityType::COMMSET: return std::string("COMMSET"); - case Ioss::EntityType::SIDEBLOCK: return std::string("SIDEBLOCK"); - case Ioss::EntityType::REGION: return std::string("REGION"); - case Ioss::EntityType::SUPERELEMENT: return std::string("SUPERELEMENT"); - case Ioss::EntityType::STRUCTUREDBLOCK: return std::string("STRUCTUREDBLOCK"); - case Ioss::EntityType::ASSEMBLY: return std::string("ASSEMBLY"); - case Ioss::EntityType::BLOB: return std::string("BLOB"); - case Ioss::EntityType::INVALID_TYPE: return std::string("INVALID_TYPE"); + case Ioss::EntityType::NODEBLOCK: return {"NODEBLOCK"}; + case Ioss::EntityType::EDGEBLOCK: return {"EDGEBLOCK"}; + case Ioss::EntityType::FACEBLOCK: return {"FACEBLOCK"}; + case Ioss::EntityType::ELEMENTBLOCK: return {"ELEMENTBLOCK"}; + case Ioss::EntityType::NODESET: return {"NODESET"}; + case Ioss::EntityType::EDGESET: return {"EDGESET"}; + case Ioss::EntityType::FACESET: return {"FACESET"}; + case Ioss::EntityType::ELEMENTSET: return {"ELEMENTSET"}; + case Ioss::EntityType::SIDESET: return {"SIDESET"}; + case Ioss::EntityType::COMMSET: return {"COMMSET"}; + case Ioss::EntityType::SIDEBLOCK: return {"SIDEBLOCK"}; + case Ioss::EntityType::REGION: return {"REGION"}; + case Ioss::EntityType::SUPERELEMENT: return {"SUPERELEMENT"}; + case Ioss::EntityType::STRUCTUREDBLOCK: return {"STRUCTUREDBLOCK"}; + case Ioss::EntityType::ASSEMBLY: return {"ASSEMBLY"}; + case Ioss::EntityType::BLOB: return {"BLOB"}; + case Ioss::EntityType::INVALID_TYPE: return {"INVALID_TYPE"}; } - return std::string("Invalid entity type [") + std::to_string(unsigned(type)) + std::string("]"); + return fmt::format("Invalid entity type [{}]", unsigned(type)); } unsigned int Ioss::Utils::hash(const std::string &name) @@ -1159,7 +1159,7 @@ namespace { // Convert to base-26 'number' hashval %= HASHSIZE; char word[3] = {char(hashval / 26 + 'a'), char(hashval % 26 + 'a'), '\0'}; - return (std::string(word)); + return {word}; } } // namespace diff --git a/packages/seacas/libraries/ioss/src/Ioss_VariableType.h b/packages/seacas/libraries/ioss/src/Ioss_VariableType.h index 0f4cc035ec..ec74a3ca1b 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_VariableType.h +++ b/packages/seacas/libraries/ioss/src/Ioss_VariableType.h @@ -43,7 +43,7 @@ namespace Ioss { struct IOSS_EXPORT Suffix { explicit Suffix(const char *new_data) : m_data(new_data) {} - explicit Suffix(const std::string &new_data) : m_data(new_data) {} + explicit Suffix(std::string new_data) : m_data(std::move(new_data)) {} bool operator==(const std::string &str) const { return Utils::str_equal(m_data, str); } bool operator!=(const std::string &str) const { return !Utils::str_equal(m_data, str); } bool is_uppercase() const { return isalpha(m_data[0]) && isupper(m_data[0]); } diff --git a/packages/seacas/libraries/ioss/src/cgns/Iocgns_Utils.h b/packages/seacas/libraries/ioss/src/cgns/Iocgns_Utils.h index 6d99694a27..fa3affb691 100644 --- a/packages/seacas/libraries/ioss/src/cgns/Iocgns_Utils.h +++ b/packages/seacas/libraries/ioss/src/cgns/Iocgns_Utils.h @@ -184,21 +184,21 @@ namespace Iocgns { switch (parent_topo->shape()) { case Ioss::ElementShape::HEX: { - static int hex_map[] = {0, 5, 1, 2, 3, 4, 6}; + static std::array hex_map = {0, 5, 1, 2, 3, 4, 6}; for (size_t i = 0; i < num_to_get; i++) { idata[2 * i + 1] = hex_map[idata[2 * i + 1]]; } } break; case Ioss::ElementShape::TET: { - static int tet_map[] = {0, 4, 1, 2, 3}; + static std::array tet_map = {0, 4, 1, 2, 3}; for (size_t i = 0; i < num_to_get; i++) { idata[2 * i + 1] = tet_map[idata[2 * i + 1]]; } } break; case Ioss::ElementShape::PYRAMID: { - static int pyr_map[] = {0, 5, 1, 2, 3, 4}; + static std::array pyr_map = {0, 5, 1, 2, 3, 4}; for (size_t i = 0; i < num_to_get; i++) { idata[2 * i + 1] = pyr_map[idata[2 * i + 1]]; } @@ -206,7 +206,7 @@ namespace Iocgns { case Ioss::ElementShape::WEDGE: #if 0 - static int wed_map[] = {0, 1, 2, 3, 4, 5}; // Same + static std::array wed_map = {0, 1, 2, 3, 4, 5}; // Same // Not needed -- maps 1 to 1 for (size_t i=0; i < num_to_get; i++) { idata[2*i+1] = wed_map[idata[2*i+1]]; diff --git a/packages/seacas/libraries/ioss/src/doctest.h b/packages/seacas/libraries/ioss/src/doctest.h index 5c754cde08..0c7a9a0e86 100644 --- a/packages/seacas/libraries/ioss/src/doctest.h +++ b/packages/seacas/libraries/ioss/src/doctest.h @@ -1,4 +1,5 @@ -// ====================================================================== lgtm [cpp/missing-header-guard] +// ====================================================================== lgtm +// [cpp/missing-header-guard] // == DO NOT MODIFY THIS FILE BY HAND - IT IS AUTO GENERATED BY CMAKE! == // ====================================================================== // @@ -42,6 +43,7 @@ #ifndef DOCTEST_LIBRARY_INCLUDED #define DOCTEST_LIBRARY_INCLUDED +// NOLINTBEGIN // ================================================================================================= // == VERSION ====================================================================================== // ================================================================================================= @@ -52,15 +54,14 @@ // util we need here #define DOCTEST_TOSTR_IMPL(x) #x -#define DOCTEST_TOSTR(x) DOCTEST_TOSTR_IMPL(x) +#define DOCTEST_TOSTR(x) DOCTEST_TOSTR_IMPL(x) #define DOCTEST_VERSION_STR \ - DOCTEST_TOSTR(DOCTEST_VERSION_MAJOR) "." \ - DOCTEST_TOSTR(DOCTEST_VERSION_MINOR) "." \ - DOCTEST_TOSTR(DOCTEST_VERSION_PATCH) + DOCTEST_TOSTR(DOCTEST_VERSION_MAJOR) \ + "." DOCTEST_TOSTR(DOCTEST_VERSION_MINOR) "." DOCTEST_TOSTR(DOCTEST_VERSION_PATCH) #define DOCTEST_VERSION \ - (DOCTEST_VERSION_MAJOR * 10000 + DOCTEST_VERSION_MINOR * 100 + DOCTEST_VERSION_PATCH) + (DOCTEST_VERSION_MAJOR * 10000 + DOCTEST_VERSION_MINOR * 100 + DOCTEST_VERSION_PATCH) // ================================================================================================= // == COMPILER VERSION ============================================================================= @@ -82,13 +83,13 @@ #define DOCTEST_MSVC DOCTEST_COMPILER(_MSC_VER / 100, _MSC_VER % 100, _MSC_FULL_VER % 10000) #else // MSVC #define DOCTEST_MSVC \ - DOCTEST_COMPILER(_MSC_VER / 100, (_MSC_FULL_VER / 100000) % 100, _MSC_FULL_VER % 100000) + DOCTEST_COMPILER(_MSC_VER / 100, (_MSC_FULL_VER / 100000) % 100, _MSC_FULL_VER % 100000) #endif // MSVC #endif // MSVC #if defined(__clang__) && defined(__clang_minor__) && defined(__clang_patchlevel__) #define DOCTEST_CLANG DOCTEST_COMPILER(__clang_major__, __clang_minor__, __clang_patchlevel__) #elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) && \ - !defined(__INTEL_COMPILER) + !defined(__INTEL_COMPILER) #define DOCTEST_GCC DOCTEST_COMPILER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) #endif // GCC #if defined(__INTEL_COMPILER) @@ -113,12 +114,12 @@ // ================================================================================================= #if DOCTEST_CLANG && !DOCTEST_ICC -#define DOCTEST_PRAGMA_TO_STR(x) _Pragma(#x) +#define DOCTEST_PRAGMA_TO_STR(x) _Pragma(#x) #define DOCTEST_CLANG_SUPPRESS_WARNING_PUSH _Pragma("clang diagnostic push") -#define DOCTEST_CLANG_SUPPRESS_WARNING(w) DOCTEST_PRAGMA_TO_STR(clang diagnostic ignored w) -#define DOCTEST_CLANG_SUPPRESS_WARNING_POP _Pragma("clang diagnostic pop") +#define DOCTEST_CLANG_SUPPRESS_WARNING(w) DOCTEST_PRAGMA_TO_STR(clang diagnostic ignored w) +#define DOCTEST_CLANG_SUPPRESS_WARNING_POP _Pragma("clang diagnostic pop") #define DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH(w) \ - DOCTEST_CLANG_SUPPRESS_WARNING_PUSH DOCTEST_CLANG_SUPPRESS_WARNING(w) + DOCTEST_CLANG_SUPPRESS_WARNING_PUSH DOCTEST_CLANG_SUPPRESS_WARNING(w) #else // DOCTEST_CLANG #define DOCTEST_CLANG_SUPPRESS_WARNING_PUSH #define DOCTEST_CLANG_SUPPRESS_WARNING(w) @@ -127,12 +128,12 @@ #endif // DOCTEST_CLANG #if DOCTEST_GCC -#define DOCTEST_PRAGMA_TO_STR(x) _Pragma(#x) +#define DOCTEST_PRAGMA_TO_STR(x) _Pragma(#x) #define DOCTEST_GCC_SUPPRESS_WARNING_PUSH _Pragma("GCC diagnostic push") -#define DOCTEST_GCC_SUPPRESS_WARNING(w) DOCTEST_PRAGMA_TO_STR(GCC diagnostic ignored w) -#define DOCTEST_GCC_SUPPRESS_WARNING_POP _Pragma("GCC diagnostic pop") +#define DOCTEST_GCC_SUPPRESS_WARNING(w) DOCTEST_PRAGMA_TO_STR(GCC diagnostic ignored w) +#define DOCTEST_GCC_SUPPRESS_WARNING_POP _Pragma("GCC diagnostic pop") #define DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH(w) \ - DOCTEST_GCC_SUPPRESS_WARNING_PUSH DOCTEST_GCC_SUPPRESS_WARNING(w) + DOCTEST_GCC_SUPPRESS_WARNING_PUSH DOCTEST_GCC_SUPPRESS_WARNING(w) #else // DOCTEST_GCC #define DOCTEST_GCC_SUPPRESS_WARNING_PUSH #define DOCTEST_GCC_SUPPRESS_WARNING(w) @@ -142,10 +143,10 @@ #if DOCTEST_MSVC #define DOCTEST_MSVC_SUPPRESS_WARNING_PUSH __pragma(warning(push)) -#define DOCTEST_MSVC_SUPPRESS_WARNING(w) __pragma(warning(disable : w)) -#define DOCTEST_MSVC_SUPPRESS_WARNING_POP __pragma(warning(pop)) +#define DOCTEST_MSVC_SUPPRESS_WARNING(w) __pragma(warning(disable : w)) +#define DOCTEST_MSVC_SUPPRESS_WARNING_POP __pragma(warning(pop)) #define DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(w) \ - DOCTEST_MSVC_SUPPRESS_WARNING_PUSH DOCTEST_MSVC_SUPPRESS_WARNING(w) + DOCTEST_MSVC_SUPPRESS_WARNING_PUSH DOCTEST_MSVC_SUPPRESS_WARNING(w) #else // DOCTEST_MSVC #define DOCTEST_MSVC_SUPPRESS_WARNING_PUSH #define DOCTEST_MSVC_SUPPRESS_WARNING(w) @@ -160,56 +161,56 @@ // both the header and the implementation suppress all of these, // so it only makes sense to aggregate them like so #define DOCTEST_SUPPRESS_COMMON_WARNINGS_PUSH \ - DOCTEST_CLANG_SUPPRESS_WARNING_PUSH \ - DOCTEST_CLANG_SUPPRESS_WARNING("-Wunknown-pragmas") \ - DOCTEST_CLANG_SUPPRESS_WARNING("-Wweak-vtables") \ - DOCTEST_CLANG_SUPPRESS_WARNING("-Wpadded") \ - DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-prototypes") \ - DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat") \ - DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat-pedantic") \ + DOCTEST_CLANG_SUPPRESS_WARNING_PUSH \ + DOCTEST_CLANG_SUPPRESS_WARNING("-Wunknown-pragmas") \ + DOCTEST_CLANG_SUPPRESS_WARNING("-Wweak-vtables") \ + DOCTEST_CLANG_SUPPRESS_WARNING("-Wpadded") \ + DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-prototypes") \ + DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat") \ + DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat-pedantic") \ \ - DOCTEST_GCC_SUPPRESS_WARNING_PUSH \ - DOCTEST_GCC_SUPPRESS_WARNING("-Wunknown-pragmas") \ - DOCTEST_GCC_SUPPRESS_WARNING("-Wpragmas") \ - DOCTEST_GCC_SUPPRESS_WARNING("-Weffc++") \ - DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-overflow") \ - DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-aliasing") \ - DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-declarations") \ - DOCTEST_GCC_SUPPRESS_WARNING("-Wuseless-cast") \ - DOCTEST_GCC_SUPPRESS_WARNING("-Wnoexcept") \ + DOCTEST_GCC_SUPPRESS_WARNING_PUSH \ + DOCTEST_GCC_SUPPRESS_WARNING("-Wunknown-pragmas") \ + DOCTEST_GCC_SUPPRESS_WARNING("-Wpragmas") \ + DOCTEST_GCC_SUPPRESS_WARNING("-Weffc++") \ + DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-overflow") \ + DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-aliasing") \ + DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-declarations") \ + DOCTEST_GCC_SUPPRESS_WARNING("-Wuseless-cast") \ + DOCTEST_GCC_SUPPRESS_WARNING("-Wnoexcept") \ \ - DOCTEST_MSVC_SUPPRESS_WARNING_PUSH \ - /* these 4 also disabled globally via cmake: */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4514) /* unreferenced inline function has been removed */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4571) /* SEH related */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4710) /* function not inlined */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4711) /* function selected for inline expansion*/ \ - /* common ones */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4616) /* invalid compiler warning */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4619) /* invalid compiler warning */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4996) /* The compiler encountered a deprecated declaration */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4706) /* assignment within conditional expression */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4512) /* 'class' : assignment operator could not be generated */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4127) /* conditional expression is constant */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4820) /* padding */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4625) /* copy constructor was implicitly deleted */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4626) /* assignment operator was implicitly deleted */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(5027) /* move assignment operator implicitly deleted */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(5026) /* move constructor was implicitly deleted */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4640) /* construction of local static object not thread-safe */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(5045) /* Spectre mitigation for memory load */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(5264) /* 'variable-name': 'const' variable is not used */ \ - /* static analysis */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(26439) /* Function may not throw. Declare it 'noexcept' */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(26495) /* Always initialize a member variable */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(26451) /* Arithmetic overflow ... */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(26444) /* Avoid unnamed objects with custom ctor and dtor... */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(26812) /* Prefer 'enum class' over 'enum' */ + DOCTEST_MSVC_SUPPRESS_WARNING_PUSH \ + /* these 4 also disabled globally via cmake: */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4514) /* unreferenced inline function has been removed */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4571) /* SEH related */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4710) /* function not inlined */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4711) /* function selected for inline expansion*/ \ + /* common ones */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4616) /* invalid compiler warning */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4619) /* invalid compiler warning */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4996) /* The compiler encountered a deprecated declaration */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4706) /* assignment within conditional expression */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4512) /* 'class' : assignment operator could not be generated */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4127) /* conditional expression is constant */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4820) /* padding */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4625) /* copy constructor was implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4626) /* assignment operator was implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5027) /* move assignment operator implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5026) /* move constructor was implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4640) /* construction of local static object not thread-safe */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5045) /* Spectre mitigation for memory load */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5264) /* 'variable-name': 'const' variable is not used */ \ + /* static analysis */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(26439) /* Function may not throw. Declare it 'noexcept' */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(26495) /* Always initialize a member variable */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(26451) /* Arithmetic overflow ... */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(26444) /* Avoid unnamed objects with custom ctor and dtor... */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(26812) /* Prefer 'enum class' over 'enum' */ #define DOCTEST_SUPPRESS_COMMON_WARNINGS_POP \ - DOCTEST_CLANG_SUPPRESS_WARNING_POP \ - DOCTEST_GCC_SUPPRESS_WARNING_POP \ - DOCTEST_MSVC_SUPPRESS_WARNING_POP + DOCTEST_CLANG_SUPPRESS_WARNING_POP \ + DOCTEST_GCC_SUPPRESS_WARNING_POP \ + DOCTEST_MSVC_SUPPRESS_WARNING_POP DOCTEST_SUPPRESS_COMMON_WARNINGS_PUSH @@ -226,25 +227,25 @@ DOCTEST_MSVC_SUPPRESS_WARNING_PUSH DOCTEST_MSVC_SUPPRESS_WARNING(4623) // default constructor was implicitly defined as deleted #define DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN \ - DOCTEST_MSVC_SUPPRESS_WARNING_PUSH \ - DOCTEST_MSVC_SUPPRESS_WARNING(4548) /* before comma no effect; expected side - effect */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4265) /* virtual functions, but destructor is not virtual */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4986) /* exception specification does not match previous */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4350) /* 'member1' called instead of 'member2' */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4668) /* not defined as a preprocessor macro */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4365) /* signed/unsigned mismatch */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4774) /* format string not a string literal */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4820) /* padding */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4625) /* copy constructor was implicitly deleted */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4626) /* assignment operator was implicitly deleted */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(5027) /* move assignment operator implicitly deleted */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(5026) /* move constructor was implicitly deleted */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4623) /* default constructor was implicitly deleted */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(5039) /* pointer to pot. throwing function passed to extern C */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(5045) /* Spectre mitigation for memory load */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(5105) /* macro producing 'defined' has undefined behavior */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4738) /* storing float result in memory, loss of performance */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(5262) /* implicit fall-through */ + DOCTEST_MSVC_SUPPRESS_WARNING_PUSH \ + DOCTEST_MSVC_SUPPRESS_WARNING(4548) /* before comma no effect; expected side - effect */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4265) /* virtual functions, but destructor is not virtual */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4986) /* exception specification does not match previous */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4350) /* 'member1' called instead of 'member2' */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4668) /* not defined as a preprocessor macro */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4365) /* signed/unsigned mismatch */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4774) /* format string not a string literal */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4820) /* padding */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4625) /* copy constructor was implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4626) /* assignment operator was implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5027) /* move assignment operator implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5026) /* move constructor was implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4623) /* default constructor was implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5039) /* pointer to pot. throwing function passed to extern C */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5045) /* Spectre mitigation for memory load */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5105) /* macro producing 'defined' has undefined behavior */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4738) /* storing float result in memory, loss of performance */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5262) /* implicit fall-through */ #define DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END DOCTEST_MSVC_SUPPRESS_WARNING_POP @@ -279,7 +280,7 @@ DOCTEST_MSVC_SUPPRESS_WARNING(4623) // default constructor was implicitly define #endif // DOCTEST_CONFIG_NO_WINDOWS_SEH #if !defined(_WIN32) && !defined(__QNX__) && !defined(DOCTEST_CONFIG_POSIX_SIGNALS) && \ - !defined(__EMSCRIPTEN__) && !defined(__wasi__) + !defined(__EMSCRIPTEN__) && !defined(__wasi__) #define DOCTEST_CONFIG_POSIX_SIGNALS #endif // _WIN32 #if defined(DOCTEST_CONFIG_NO_POSIX_SIGNALS) && defined(DOCTEST_CONFIG_POSIX_SIGNALS) @@ -287,8 +288,8 @@ DOCTEST_MSVC_SUPPRESS_WARNING(4623) // default constructor was implicitly define #endif // DOCTEST_CONFIG_NO_POSIX_SIGNALS #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS -#if !defined(__cpp_exceptions) && !defined(__EXCEPTIONS) && !defined(_CPPUNWIND) \ - || defined(__wasi__) +#if !defined(__cpp_exceptions) && !defined(__EXCEPTIONS) && !defined(_CPPUNWIND) || \ + defined(__wasi__) #define DOCTEST_CONFIG_NO_EXCEPTIONS #endif // no exceptions #endif // DOCTEST_CONFIG_NO_EXCEPTIONS @@ -355,8 +356,8 @@ DOCTEST_MSVC_SUPPRESS_WARNING(4623) // default constructor was implicitly define #define DOCTEST_UNUSED #define DOCTEST_ALIGNMENT(x) #else -#define DOCTEST_NOINLINE __attribute__((noinline)) -#define DOCTEST_UNUSED __attribute__((unused)) +#define DOCTEST_NOINLINE __attribute__((noinline)) +#define DOCTEST_UNUSED __attribute__((unused)) #define DOCTEST_ALIGNMENT(x) __attribute__((aligned(x))) #endif @@ -384,10 +385,10 @@ DOCTEST_MSVC_SUPPRESS_WARNING(4623) // default constructor was implicitly define #ifndef DOCTEST_CONSTEXPR #if DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0)) -#define DOCTEST_CONSTEXPR const +#define DOCTEST_CONSTEXPR const #define DOCTEST_CONSTEXPR_FUNC inline #else // DOCTEST_MSVC -#define DOCTEST_CONSTEXPR constexpr +#define DOCTEST_CONSTEXPR constexpr #define DOCTEST_CONSTEXPR_FUNC constexpr #endif // DOCTEST_MSVC #endif // DOCTEST_CONSTEXPR @@ -405,19 +406,18 @@ DOCTEST_MSVC_SUPPRESS_WARNING(4623) // default constructor was implicitly define // ================================================================================================= #define DOCTEST_DECLARE_INTERFACE(name) \ - virtual ~name(); \ - name() = default; \ - name(const name&) = delete; \ - name(name&&) = delete; \ - name& operator=(const name&) = delete; \ - name& operator=(name&&) = delete; + virtual ~name(); \ + name() = default; \ + name(const name &) = delete; \ + name(name &&) = delete; \ + name &operator=(const name &) = delete; \ + name &operator=(name &&) = delete; -#define DOCTEST_DEFINE_INTERFACE(name) \ - name::~name() = default; +#define DOCTEST_DEFINE_INTERFACE(name) name::~name() = default; // internal macros for string concatenation and anonymous variable name generation #define DOCTEST_CAT_IMPL(s1, s2) s1##s2 -#define DOCTEST_CAT(s1, s2) DOCTEST_CAT_IMPL(s1, s2) +#define DOCTEST_CAT(s1, s2) DOCTEST_CAT_IMPL(s1, s2) #ifdef __COUNTER__ // not standard and may be missing for some compilers #define DOCTEST_ANONYMOUS(x) DOCTEST_CAT(x, __COUNTER__) #else // __COUNTER__ @@ -425,7 +425,7 @@ DOCTEST_MSVC_SUPPRESS_WARNING(4623) // default constructor was implicitly define #endif // __COUNTER__ #ifndef DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE -#define DOCTEST_REF_WRAP(x) x& +#define DOCTEST_REF_WRAP(x) x & #else // DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE #define DOCTEST_REF_WRAP(x) x #endif // DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE @@ -443,14 +443,16 @@ DOCTEST_MSVC_SUPPRESS_WARNING(4623) // default constructor was implicitly define #define DOCTEST_PLATFORM_LINUX #endif // DOCTEST_PLATFORM -namespace doctest { namespace detail { - static DOCTEST_CONSTEXPR int consume(const int*, int) noexcept { return 0; } -}} +namespace doctest { + namespace detail { + static DOCTEST_CONSTEXPR int consume(const int *, int) noexcept { return 0; } + } // namespace detail +} // namespace doctest -#define DOCTEST_GLOBAL_NO_WARNINGS(var, ...) \ - DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wglobal-constructors") \ - static const int var = doctest::detail::consume(&var, __VA_ARGS__); \ - DOCTEST_CLANG_SUPPRESS_WARNING_POP +#define DOCTEST_GLOBAL_NO_WARNINGS(var, ...) \ + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wglobal-constructors") \ + static const int var = doctest::detail::consume(&var, __VA_ARGS__); \ + DOCTEST_CLANG_SUPPRESS_WARNING_POP #ifndef DOCTEST_BREAK_INTO_DEBUGGER // should probably take a look at https://github.com/scottt/debugbreak @@ -467,7 +469,11 @@ namespace doctest { namespace detail { #define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :) // NOLINT(hicpp-no-assembler) #elif defined(__ppc__) || defined(__ppc64__) // https://www.cocoawithlove.com/2008/03/break-into-debugger.html -#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n": : : "memory","r0","r3","r4") // NOLINT(hicpp-no-assembler) +#define DOCTEST_BREAK_INTO_DEBUGGER() \ + __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \ + : \ + : \ + : "memory", "r0", "r3", "r4") // NOLINT(hicpp-no-assembler) #else #define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("brk #0"); // NOLINT(hicpp-no-assembler) #endif @@ -511,39 +517,32 @@ DOCTEST_GCC_SUPPRESS_WARNING_POP #endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN #include -#include #include +#include DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END #else // DOCTEST_CONFIG_USE_STD_HEADERS // Forward declaring 'X' in namespace std is not permitted by the C++ Standard. DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4643) -namespace std { // NOLINT(cert-dcl58-cpp) -typedef decltype(nullptr) nullptr_t; // NOLINT(modernize-use-using) -typedef decltype(sizeof(void*)) size_t; // NOLINT(modernize-use-using) -template -struct char_traits; -template <> -struct char_traits; -template -class basic_ostream; // NOLINT(fuchsia-virtual-inheritance) -typedef basic_ostream> ostream; // NOLINT(modernize-use-using) -template -// NOLINTNEXTLINE -basic_ostream& operator<<(basic_ostream&, const char*); -template -class basic_istream; -typedef basic_istream> istream; // NOLINT(modernize-use-using) -template -class tuple; +namespace std { // NOLINT(cert-dcl58-cpp) + typedef decltype(nullptr) nullptr_t; // NOLINT(modernize-use-using) + typedef decltype(sizeof(void *)) size_t; // NOLINT(modernize-use-using) + template struct char_traits; + template <> struct char_traits; + template class basic_ostream; // NOLINT(fuchsia-virtual-inheritance) + typedef basic_ostream> ostream; // NOLINT(modernize-use-using) + template + // NOLINTNEXTLINE + basic_ostream &operator<<(basic_ostream &, const char *); + template class basic_istream; + typedef basic_istream> istream; // NOLINT(modernize-use-using) + template class tuple; #if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0) -// see this issue on why this is needed: https://github.com/doctest/doctest/issues/183 -template -class allocator; -template -class basic_string; -using string = basic_string, allocator>; + // see this issue on why this is needed: https://github.com/doctest/doctest/issues/183 + template class allocator; + template class basic_string; + using string = basic_string, allocator>; #endif // VS 2019 } // namespace std @@ -557,94 +556,95 @@ DOCTEST_MSVC_SUPPRESS_WARNING_POP namespace doctest { -using std::size_t; + using std::size_t; -DOCTEST_INTERFACE extern bool is_running_in_test; + DOCTEST_INTERFACE extern bool is_running_in_test; #ifndef DOCTEST_CONFIG_STRING_SIZE_TYPE #define DOCTEST_CONFIG_STRING_SIZE_TYPE unsigned #endif -// A 24 byte string class (can be as small as 17 for x64 and 13 for x86) that can hold strings with length -// of up to 23 chars on the stack before going on the heap - the last byte of the buffer is used for: -// - "is small" bit - the highest bit - if "0" then it is small - otherwise its "1" (128) -// - if small - capacity left before going on the heap - using the lowest 5 bits -// - if small - 2 bits are left unused - the second and third highest ones -// - if small - acts as a null terminator if strlen() is 23 (24 including the null terminator) -// and the "is small" bit remains "0" ("as well as the capacity left") so its OK -// Idea taken from this lecture about the string implementation of facebook/folly - fbstring -// https://www.youtube.com/watch?v=kPR8h4-qZdk -// TODO: -// - optimizations - like not deleting memory unnecessarily in operator= and etc. -// - resize/reserve/clear -// - replace -// - back/front -// - iterator stuff -// - find & friends -// - push_back/pop_back -// - assign/insert/erase -// - relational operators as free functions - taking const char* as one of the params -class DOCTEST_INTERFACE String -{ -public: + // A 24 byte string class (can be as small as 17 for x64 and 13 for x86) that can hold strings + // with length of up to 23 chars on the stack before going on the heap - the last byte of the + // buffer is used for: + // - "is small" bit - the highest bit - if "0" then it is small - otherwise its "1" (128) + // - if small - capacity left before going on the heap - using the lowest 5 bits + // - if small - 2 bits are left unused - the second and third highest ones + // - if small - acts as a null terminator if strlen() is 23 (24 including the null terminator) + // and the "is small" bit remains "0" ("as well as the capacity left") so its OK + // Idea taken from this lecture about the string implementation of facebook/folly - fbstring + // https://www.youtube.com/watch?v=kPR8h4-qZdk + // TODO: + // - optimizations - like not deleting memory unnecessarily in operator= and etc. + // - resize/reserve/clear + // - replace + // - back/front + // - iterator stuff + // - find & friends + // - push_back/pop_back + // - assign/insert/erase + // - relational operators as free functions - taking const char* as one of the params + class DOCTEST_INTERFACE String + { + public: using size_type = DOCTEST_CONFIG_STRING_SIZE_TYPE; -private: - static DOCTEST_CONSTEXPR size_type len = 24; //!OCLINT avoid private static members - static DOCTEST_CONSTEXPR size_type last = len - 1; //!OCLINT avoid private static members + private: + static DOCTEST_CONSTEXPR size_type len = 24; //! OCLINT avoid private static members + static DOCTEST_CONSTEXPR size_type last = len - 1; //! OCLINT avoid private static members struct view // len should be more than sizeof(view) - because of the final byte for flags { - char* ptr; - size_type size; - size_type capacity; + char *ptr; + size_type size; + size_type capacity; }; - union - { - char buf[len]; // NOLINT(*-avoid-c-arrays) - view data; + union { + char buf[len]; // NOLINT(*-avoid-c-arrays) + view data; }; - char* allocate(size_type sz); + char *allocate(size_type sz); bool isOnStack() const noexcept { return (buf[last] & 128) == 0; } void setOnHeap() noexcept; void setLast(size_type in = last) noexcept; void setSize(size_type sz) noexcept; - void copy(const String& other); + void copy(const String &other); -public: + public: static DOCTEST_CONSTEXPR size_type npos = static_cast(-1); String() noexcept; ~String(); // cppcheck-suppress noExplicitConstructor - String(const char* in); - String(const char* in, size_type in_size); + String(const char *in); + String(const char *in, size_type in_size); - String(std::istream& in, size_type in_size); + String(std::istream &in, size_type in_size); - String(const String& other); - String& operator=(const String& other); + String(const String &other); + String &operator=(const String &other); - String& operator+=(const String& other); + String &operator+=(const String &other); - String(String&& other) noexcept; - String& operator=(String&& other) noexcept; + String(String &&other) noexcept; + String &operator=(String &&other) noexcept; char operator[](size_type i) const; - char& operator[](size_type i); + char &operator[](size_type i); // the only functions I'm willing to leave in the interface - available for inlining - const char* c_str() const { return const_cast(this)->c_str(); } // NOLINT - char* c_str() { - if (isOnStack()) { - return reinterpret_cast(buf); - } - return data.ptr; + const char *c_str() const { return const_cast(this)->c_str(); } // NOLINT + char *c_str() + { + if (isOnStack()) { + return reinterpret_cast(buf); + } + return data.ptr; } size_type size() const; @@ -656,162 +656,161 @@ class DOCTEST_INTERFACE String size_type find(char ch, size_type pos = 0) const; size_type rfind(char ch, size_type pos = npos) const; - int compare(const char* other, bool no_case = false) const; - int compare(const String& other, bool no_case = false) const; + int compare(const char *other, bool no_case = false) const; + int compare(const String &other, bool no_case = false) const; -friend DOCTEST_INTERFACE std::ostream& operator<<(std::ostream& s, const String& in); -}; + friend DOCTEST_INTERFACE std::ostream &operator<<(std::ostream &s, const String &in); + }; -DOCTEST_INTERFACE String operator+(const String& lhs, const String& rhs); + DOCTEST_INTERFACE String operator+(const String &lhs, const String &rhs); -DOCTEST_INTERFACE bool operator==(const String& lhs, const String& rhs); -DOCTEST_INTERFACE bool operator!=(const String& lhs, const String& rhs); -DOCTEST_INTERFACE bool operator<(const String& lhs, const String& rhs); -DOCTEST_INTERFACE bool operator>(const String& lhs, const String& rhs); -DOCTEST_INTERFACE bool operator<=(const String& lhs, const String& rhs); -DOCTEST_INTERFACE bool operator>=(const String& lhs, const String& rhs); + DOCTEST_INTERFACE bool operator==(const String &lhs, const String &rhs); + DOCTEST_INTERFACE bool operator!=(const String &lhs, const String &rhs); + DOCTEST_INTERFACE bool operator<(const String &lhs, const String &rhs); + DOCTEST_INTERFACE bool operator>(const String &lhs, const String &rhs); + DOCTEST_INTERFACE bool operator<=(const String &lhs, const String &rhs); + DOCTEST_INTERFACE bool operator>=(const String &lhs, const String &rhs); -class DOCTEST_INTERFACE Contains { -public: - explicit Contains(const String& string); + class DOCTEST_INTERFACE Contains + { + public: + explicit Contains(const String &string); - bool checkWith(const String& other) const; + bool checkWith(const String &other) const; String string; -}; - -DOCTEST_INTERFACE String toString(const Contains& in); - -DOCTEST_INTERFACE bool operator==(const String& lhs, const Contains& rhs); -DOCTEST_INTERFACE bool operator==(const Contains& lhs, const String& rhs); -DOCTEST_INTERFACE bool operator!=(const String& lhs, const Contains& rhs); -DOCTEST_INTERFACE bool operator!=(const Contains& lhs, const String& rhs); - -namespace Color { - enum Enum - { - None = 0, - White, - Red, - Green, - Blue, - Cyan, - Yellow, - Grey, - - Bright = 0x10, - - BrightRed = Bright | Red, - BrightGreen = Bright | Green, - LightGrey = Bright | Grey, - BrightWhite = Bright | White + }; + + DOCTEST_INTERFACE String toString(const Contains &in); + + DOCTEST_INTERFACE bool operator==(const String &lhs, const Contains &rhs); + DOCTEST_INTERFACE bool operator==(const Contains &lhs, const String &rhs); + DOCTEST_INTERFACE bool operator!=(const String &lhs, const Contains &rhs); + DOCTEST_INTERFACE bool operator!=(const Contains &lhs, const String &rhs); + + namespace Color { + enum Enum { + None = 0, + White, + Red, + Green, + Blue, + Cyan, + Yellow, + Grey, + + Bright = 0x10, + + BrightRed = Bright | Red, + BrightGreen = Bright | Green, + LightGrey = Bright | Grey, + BrightWhite = Bright | White }; - DOCTEST_INTERFACE std::ostream& operator<<(std::ostream& s, Color::Enum code); -} // namespace Color + DOCTEST_INTERFACE std::ostream &operator<<(std::ostream &s, Color::Enum code); + } // namespace Color -namespace assertType { - enum Enum - { - // macro traits + namespace assertType { + enum Enum { + // macro traits - is_warn = 1, - is_check = 2 * is_warn, - is_require = 2 * is_check, + is_warn = 1, + is_check = 2 * is_warn, + is_require = 2 * is_check, - is_normal = 2 * is_require, - is_throws = 2 * is_normal, - is_throws_as = 2 * is_throws, - is_throws_with = 2 * is_throws_as, - is_nothrow = 2 * is_throws_with, + is_normal = 2 * is_require, + is_throws = 2 * is_normal, + is_throws_as = 2 * is_throws, + is_throws_with = 2 * is_throws_as, + is_nothrow = 2 * is_throws_with, - is_false = 2 * is_nothrow, - is_unary = 2 * is_false, // not checked anywhere - used just to distinguish the types + is_false = 2 * is_nothrow, + is_unary = 2 * is_false, // not checked anywhere - used just to distinguish the types - is_eq = 2 * is_unary, - is_ne = 2 * is_eq, + is_eq = 2 * is_unary, + is_ne = 2 * is_eq, - is_lt = 2 * is_ne, - is_gt = 2 * is_lt, + is_lt = 2 * is_ne, + is_gt = 2 * is_lt, - is_ge = 2 * is_gt, - is_le = 2 * is_ge, + is_ge = 2 * is_gt, + is_le = 2 * is_ge, - // macro types + // macro types - DT_WARN = is_normal | is_warn, - DT_CHECK = is_normal | is_check, - DT_REQUIRE = is_normal | is_require, + DT_WARN = is_normal | is_warn, + DT_CHECK = is_normal | is_check, + DT_REQUIRE = is_normal | is_require, - DT_WARN_FALSE = is_normal | is_false | is_warn, - DT_CHECK_FALSE = is_normal | is_false | is_check, - DT_REQUIRE_FALSE = is_normal | is_false | is_require, + DT_WARN_FALSE = is_normal | is_false | is_warn, + DT_CHECK_FALSE = is_normal | is_false | is_check, + DT_REQUIRE_FALSE = is_normal | is_false | is_require, - DT_WARN_THROWS = is_throws | is_warn, - DT_CHECK_THROWS = is_throws | is_check, - DT_REQUIRE_THROWS = is_throws | is_require, + DT_WARN_THROWS = is_throws | is_warn, + DT_CHECK_THROWS = is_throws | is_check, + DT_REQUIRE_THROWS = is_throws | is_require, - DT_WARN_THROWS_AS = is_throws_as | is_warn, - DT_CHECK_THROWS_AS = is_throws_as | is_check, - DT_REQUIRE_THROWS_AS = is_throws_as | is_require, + DT_WARN_THROWS_AS = is_throws_as | is_warn, + DT_CHECK_THROWS_AS = is_throws_as | is_check, + DT_REQUIRE_THROWS_AS = is_throws_as | is_require, - DT_WARN_THROWS_WITH = is_throws_with | is_warn, - DT_CHECK_THROWS_WITH = is_throws_with | is_check, - DT_REQUIRE_THROWS_WITH = is_throws_with | is_require, + DT_WARN_THROWS_WITH = is_throws_with | is_warn, + DT_CHECK_THROWS_WITH = is_throws_with | is_check, + DT_REQUIRE_THROWS_WITH = is_throws_with | is_require, - DT_WARN_THROWS_WITH_AS = is_throws_with | is_throws_as | is_warn, - DT_CHECK_THROWS_WITH_AS = is_throws_with | is_throws_as | is_check, - DT_REQUIRE_THROWS_WITH_AS = is_throws_with | is_throws_as | is_require, + DT_WARN_THROWS_WITH_AS = is_throws_with | is_throws_as | is_warn, + DT_CHECK_THROWS_WITH_AS = is_throws_with | is_throws_as | is_check, + DT_REQUIRE_THROWS_WITH_AS = is_throws_with | is_throws_as | is_require, - DT_WARN_NOTHROW = is_nothrow | is_warn, - DT_CHECK_NOTHROW = is_nothrow | is_check, - DT_REQUIRE_NOTHROW = is_nothrow | is_require, + DT_WARN_NOTHROW = is_nothrow | is_warn, + DT_CHECK_NOTHROW = is_nothrow | is_check, + DT_REQUIRE_NOTHROW = is_nothrow | is_require, - DT_WARN_EQ = is_normal | is_eq | is_warn, - DT_CHECK_EQ = is_normal | is_eq | is_check, - DT_REQUIRE_EQ = is_normal | is_eq | is_require, + DT_WARN_EQ = is_normal | is_eq | is_warn, + DT_CHECK_EQ = is_normal | is_eq | is_check, + DT_REQUIRE_EQ = is_normal | is_eq | is_require, - DT_WARN_NE = is_normal | is_ne | is_warn, - DT_CHECK_NE = is_normal | is_ne | is_check, - DT_REQUIRE_NE = is_normal | is_ne | is_require, + DT_WARN_NE = is_normal | is_ne | is_warn, + DT_CHECK_NE = is_normal | is_ne | is_check, + DT_REQUIRE_NE = is_normal | is_ne | is_require, - DT_WARN_GT = is_normal | is_gt | is_warn, - DT_CHECK_GT = is_normal | is_gt | is_check, - DT_REQUIRE_GT = is_normal | is_gt | is_require, + DT_WARN_GT = is_normal | is_gt | is_warn, + DT_CHECK_GT = is_normal | is_gt | is_check, + DT_REQUIRE_GT = is_normal | is_gt | is_require, - DT_WARN_LT = is_normal | is_lt | is_warn, - DT_CHECK_LT = is_normal | is_lt | is_check, - DT_REQUIRE_LT = is_normal | is_lt | is_require, + DT_WARN_LT = is_normal | is_lt | is_warn, + DT_CHECK_LT = is_normal | is_lt | is_check, + DT_REQUIRE_LT = is_normal | is_lt | is_require, - DT_WARN_GE = is_normal | is_ge | is_warn, - DT_CHECK_GE = is_normal | is_ge | is_check, - DT_REQUIRE_GE = is_normal | is_ge | is_require, + DT_WARN_GE = is_normal | is_ge | is_warn, + DT_CHECK_GE = is_normal | is_ge | is_check, + DT_REQUIRE_GE = is_normal | is_ge | is_require, - DT_WARN_LE = is_normal | is_le | is_warn, - DT_CHECK_LE = is_normal | is_le | is_check, - DT_REQUIRE_LE = is_normal | is_le | is_require, + DT_WARN_LE = is_normal | is_le | is_warn, + DT_CHECK_LE = is_normal | is_le | is_check, + DT_REQUIRE_LE = is_normal | is_le | is_require, - DT_WARN_UNARY = is_normal | is_unary | is_warn, - DT_CHECK_UNARY = is_normal | is_unary | is_check, - DT_REQUIRE_UNARY = is_normal | is_unary | is_require, + DT_WARN_UNARY = is_normal | is_unary | is_warn, + DT_CHECK_UNARY = is_normal | is_unary | is_check, + DT_REQUIRE_UNARY = is_normal | is_unary | is_require, - DT_WARN_UNARY_FALSE = is_normal | is_false | is_unary | is_warn, - DT_CHECK_UNARY_FALSE = is_normal | is_false | is_unary | is_check, - DT_REQUIRE_UNARY_FALSE = is_normal | is_false | is_unary | is_require, + DT_WARN_UNARY_FALSE = is_normal | is_false | is_unary | is_warn, + DT_CHECK_UNARY_FALSE = is_normal | is_false | is_unary | is_check, + DT_REQUIRE_UNARY_FALSE = is_normal | is_false | is_unary | is_require, }; -} // namespace assertType + } // namespace assertType -DOCTEST_INTERFACE const char* assertString(assertType::Enum at); -DOCTEST_INTERFACE const char* failureString(assertType::Enum at); -DOCTEST_INTERFACE const char* skipPathFromFilename(const char* file); + DOCTEST_INTERFACE const char *assertString(assertType::Enum at); + DOCTEST_INTERFACE const char *failureString(assertType::Enum at); + DOCTEST_INTERFACE const char *skipPathFromFilename(const char *file); -struct DOCTEST_INTERFACE TestCaseData -{ + struct DOCTEST_INTERFACE TestCaseData + { String m_file; // the file in which the test was registered (using String - see #350) unsigned m_line; // the line where the test was registered - const char* m_name; // name of the test case - const char* m_test_suite; // the test suite in which the test was added - const char* m_description; + const char *m_name; // name of the test case + const char *m_test_suite; // the test suite in which the test was added + const char *m_description; bool m_skip; bool m_no_breaks; bool m_no_output; @@ -819,16 +818,16 @@ struct DOCTEST_INTERFACE TestCaseData bool m_should_fail; int m_expected_failures; double m_timeout; -}; + }; -struct DOCTEST_INTERFACE AssertData -{ + struct DOCTEST_INTERFACE AssertData + { // common - for all asserts - const TestCaseData* m_test_case; + const TestCaseData *m_test_case; assertType::Enum m_at; - const char* m_file; + const char *m_file; int m_line; - const char* m_expr; + const char *m_expr; bool m_failed; // exception-related - for all asserts @@ -839,63 +838,67 @@ struct DOCTEST_INTERFACE AssertData String m_decomp; // for specific exception-related asserts - bool m_threw_as; - const char* m_exception_type; + bool m_threw_as; + const char *m_exception_type; - class DOCTEST_INTERFACE StringContains { - private: - Contains content; - bool isContains; + class DOCTEST_INTERFACE StringContains + { + private: + Contains content; + bool isContains; - public: - StringContains(const String& str) : content(str), isContains(false) { } - StringContains(Contains cntn) : content(static_cast(cntn)), isContains(true) { } + public: + StringContains(const String &str) : content(str), isContains(false) {} + StringContains(Contains cntn) : content(static_cast(cntn)), isContains(true) {} - bool check(const String& str) { return isContains ? (content == str) : (content.string == str); } + bool check(const String &str) + { + return isContains ? (content == str) : (content.string == str); + } - operator const String&() const { return content.string; } + operator const String &() const { return content.string; } - const char* c_str() const { return content.string.c_str(); } + const char *c_str() const { return content.string.c_str(); } } m_exception_string; - AssertData(assertType::Enum at, const char* file, int line, const char* expr, - const char* exception_type, const StringContains& exception_string); -}; + AssertData(assertType::Enum at, const char *file, int line, const char *expr, + const char *exception_type, const StringContains &exception_string); + }; -struct DOCTEST_INTERFACE MessageData -{ + struct DOCTEST_INTERFACE MessageData + { String m_string; - const char* m_file; + const char *m_file; int m_line; assertType::Enum m_severity; -}; + }; -struct DOCTEST_INTERFACE SubcaseSignature -{ + struct DOCTEST_INTERFACE SubcaseSignature + { String m_name; - const char* m_file; + const char *m_file; int m_line; - bool operator==(const SubcaseSignature& other) const; - bool operator<(const SubcaseSignature& other) const; -}; + bool operator==(const SubcaseSignature &other) const; + bool operator<(const SubcaseSignature &other) const; + }; -struct DOCTEST_INTERFACE IContextScope -{ + struct DOCTEST_INTERFACE IContextScope + { DOCTEST_DECLARE_INTERFACE(IContextScope) - virtual void stringify(std::ostream*) const = 0; -}; + virtual void stringify(std::ostream *) const = 0; + }; -namespace detail { + namespace detail { struct DOCTEST_INTERFACE TestCase; -} // namespace detail + } // namespace detail -struct ContextOptions //!OCLINT too many fields -{ - std::ostream* cout = nullptr; // stdout stream + struct ContextOptions //! OCLINT too many fields + { + std::ostream *cout = nullptr; // stdout stream String binary_name; // the test binary name - const detail::TestCase* currentTest = nullptr; + const detail::TestCase *currentTest = nullptr; // == parameters from the command line String out; // output filename @@ -936,150 +939,210 @@ struct ContextOptions //!OCLINT too many fields bool list_test_cases; // to list all tests matching the filters bool list_test_suites; // to list all suites matching the filters bool list_reporters; // lists all registered reporters -}; + }; -namespace detail { + namespace detail { namespace types { #ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS - using namespace std; + using namespace std; #else - template - struct enable_if { }; - - template - struct enable_if { using type = T; }; - - struct true_type { static DOCTEST_CONSTEXPR bool value = true; }; - struct false_type { static DOCTEST_CONSTEXPR bool value = false; }; - - template struct remove_reference { using type = T; }; - template struct remove_reference { using type = T; }; - template struct remove_reference { using type = T; }; - - template struct is_rvalue_reference : false_type { }; - template struct is_rvalue_reference : true_type { }; - - template struct remove_const { using type = T; }; - template struct remove_const { using type = T; }; - - // Compiler intrinsics - template struct is_enum { static DOCTEST_CONSTEXPR bool value = __is_enum(T); }; - template struct underlying_type { using type = __underlying_type(T); }; - - template struct is_pointer : false_type { }; - template struct is_pointer : true_type { }; - - template struct is_array : false_type { }; - // NOLINTNEXTLINE(*-avoid-c-arrays) - template struct is_array : true_type { }; + template struct enable_if + { + }; + + template struct enable_if + { + using type = T; + }; + + struct true_type + { + static DOCTEST_CONSTEXPR bool value = true; + }; + struct false_type + { + static DOCTEST_CONSTEXPR bool value = false; + }; + + template struct remove_reference + { + using type = T; + }; + template struct remove_reference + { + using type = T; + }; + template struct remove_reference + { + using type = T; + }; + + template struct is_rvalue_reference : false_type + { + }; + template struct is_rvalue_reference : true_type + { + }; + + template struct remove_const + { + using type = T; + }; + template struct remove_const + { + using type = T; + }; + + // Compiler intrinsics + template struct is_enum + { + static DOCTEST_CONSTEXPR bool value = __is_enum(T); + }; + template struct underlying_type + { + using type = __underlying_type(T); + }; + + template struct is_pointer : false_type + { + }; + template struct is_pointer : true_type + { + }; + + template struct is_array : false_type + { + }; + // NOLINTNEXTLINE(*-avoid-c-arrays) + template struct is_array : true_type + { + }; #endif - } + } // namespace types // - template - T&& declval(); + template T &&declval(); template - DOCTEST_CONSTEXPR_FUNC T&& forward(typename types::remove_reference::type& t) DOCTEST_NOEXCEPT { - return static_cast(t); + DOCTEST_CONSTEXPR_FUNC T && + forward(typename types::remove_reference::type &t) DOCTEST_NOEXCEPT + { + return static_cast(t); } template - DOCTEST_CONSTEXPR_FUNC T&& forward(typename types::remove_reference::type&& t) DOCTEST_NOEXCEPT { - return static_cast(t); + DOCTEST_CONSTEXPR_FUNC T && + forward(typename types::remove_reference::type &&t) DOCTEST_NOEXCEPT + { + return static_cast(t); } - template - struct deferred_false : types::false_type { }; + template struct deferred_false : types::false_type + { + }; // MSVS 2015 :( #if !DOCTEST_CLANG && defined(_MSC_VER) && _MSC_VER <= 1900 - template - struct has_global_insertion_operator : types::false_type { }; + template struct has_global_insertion_operator : types::false_type + { + }; template - struct has_global_insertion_operator(), declval()), void())> : types::true_type { }; + struct has_global_insertion_operator< + T, decltype(::operator<<(declval(), declval()), void())> + : types::true_type + { + }; - template - struct has_insertion_operator { static DOCTEST_CONSTEXPR bool value = has_global_insertion_operator::value; }; + template struct has_insertion_operator + { + static DOCTEST_CONSTEXPR bool value = has_global_insertion_operator::value; + }; - template - struct insert_hack; + template struct insert_hack; - template - struct insert_hack { - static void insert(std::ostream& os, const T& t) { ::operator<<(os, t); } + template struct insert_hack + { + static void insert(std::ostream &os, const T &t) { ::operator<<(os, t); } }; - template - struct insert_hack { - static void insert(std::ostream& os, const T& t) { operator<<(os, t); } + template struct insert_hack + { + static void insert(std::ostream &os, const T &t) { operator<<(os, t); } }; template using insert_hack_t = insert_hack::value>; #else - template - struct has_insertion_operator : types::false_type { }; + template struct has_insertion_operator : types::false_type + { + }; #endif template - struct has_insertion_operator(), declval()), void())> : types::true_type { }; + struct has_insertion_operator< + T, decltype(operator<<(declval(), declval()), void())> + : types::true_type + { + }; - template - struct should_stringify_as_underlying_type { - static DOCTEST_CONSTEXPR bool value = detail::types::is_enum::value && !doctest::detail::has_insertion_operator::value; + template struct should_stringify_as_underlying_type + { + static DOCTEST_CONSTEXPR bool value = + detail::types::is_enum::value && !doctest::detail::has_insertion_operator::value; }; - DOCTEST_INTERFACE std::ostream* tlssPush(); - DOCTEST_INTERFACE String tlssPop(); + DOCTEST_INTERFACE std::ostream *tlssPush(); + DOCTEST_INTERFACE String tlssPop(); - template - struct StringMakerBase { - template - static String convert(const DOCTEST_REF_WRAP(T)) { + template struct StringMakerBase + { + template static String convert(const DOCTEST_REF_WRAP(T)) + { #ifdef DOCTEST_CONFIG_REQUIRE_STRINGIFICATION_FOR_ALL_USED_TYPES - static_assert(deferred_false::value, "No stringification detected for type T. See string conversion manual"); + static_assert(deferred_false::value, + "No stringification detected for type T. See string conversion manual"); #endif - return "{?}"; - } + return "{?}"; + } }; - template - struct filldata; + template struct filldata; - template - void filloss(std::ostream* stream, const T& in) { - filldata::fill(stream, in); + template void filloss(std::ostream *stream, const T &in) + { + filldata::fill(stream, in); } - template - void filloss(std::ostream* stream, const T (&in)[N]) { // NOLINT(*-avoid-c-arrays) - // T[N], T(&)[N], T(&&)[N] have same behaviour. - // Hence remove reference. - filloss::type>(stream, in); + template void filloss(std::ostream *stream, const T (&in)[N]) + { // NOLINT(*-avoid-c-arrays) + // T[N], T(&)[N], T(&&)[N] have same behaviour. + // Hence remove reference. + filloss::type>(stream, in); } - template - String toStream(const T& in) { - std::ostream* stream = tlssPush(); - filloss(stream, in); - return tlssPop(); + template String toStream(const T &in) + { + std::ostream *stream = tlssPush(); + filloss(stream, in); + return tlssPop(); } - template <> - struct StringMakerBase { - template - static String convert(const DOCTEST_REF_WRAP(T) in) { - return toStream(in); - } + template <> struct StringMakerBase + { + template static String convert(const DOCTEST_REF_WRAP(T) in) + { + return toStream(in); + } }; -} // namespace detail + } // namespace detail -template -struct StringMaker : public detail::StringMakerBase< - detail::has_insertion_operator::value || detail::types::is_pointer::value || detail::types::is_array::value> -{}; + template + struct StringMaker : public detail::StringMakerBase::value || + detail::types::is_pointer::value || + detail::types::is_array::value> + { + }; #ifndef DOCTEST_STRINGIFY #ifdef DOCTEST_CONFIG_DOUBLE_STRINGIFY @@ -1089,157 +1152,172 @@ struct StringMaker : public detail::StringMakerBase< #endif #endif -template -String toString() { + template String toString() + { #if DOCTEST_CLANG == 0 && DOCTEST_GCC == 0 && DOCTEST_ICC == 0 String ret = __FUNCSIG__; // class doctest::String __cdecl doctest::toString(void) String::size_type beginPos = ret.find('<'); - return ret.substr(beginPos + 1, ret.size() - beginPos - static_cast(sizeof(">(void)"))); + return ret.substr(beginPos + 1, + ret.size() - beginPos - static_cast(sizeof(">(void)"))); #else - String ret = __PRETTY_FUNCTION__; // doctest::String toString() [with T = TYPE] + String ret = __PRETTY_FUNCTION__; // doctest::String toString() [with T = TYPE] String::size_type begin = ret.find('=') + 2; return ret.substr(begin, ret.size() - begin - 1); #endif -} + } -template ::value, bool>::type = true> -String toString(const DOCTEST_REF_WRAP(T) value) { + template ::value, bool>::type = true> + String toString(const DOCTEST_REF_WRAP(T) value) + { return StringMaker::convert(value); -} + } #ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING -DOCTEST_INTERFACE String toString(const char* in); + DOCTEST_INTERFACE String toString(const char *in); #endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING #if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0) -// see this issue on why this is needed: https://github.com/doctest/doctest/issues/183 -DOCTEST_INTERFACE String toString(const std::string& in); + // see this issue on why this is needed: https://github.com/doctest/doctest/issues/183 + DOCTEST_INTERFACE String toString(const std::string &in); #endif // VS 2019 -DOCTEST_INTERFACE String toString(String in); - -DOCTEST_INTERFACE String toString(std::nullptr_t); - -DOCTEST_INTERFACE String toString(bool in); - -DOCTEST_INTERFACE String toString(float in); -DOCTEST_INTERFACE String toString(double in); -DOCTEST_INTERFACE String toString(double long in); - -DOCTEST_INTERFACE String toString(char in); -DOCTEST_INTERFACE String toString(char signed in); -DOCTEST_INTERFACE String toString(char unsigned in); -DOCTEST_INTERFACE String toString(short in); -DOCTEST_INTERFACE String toString(short unsigned in); -DOCTEST_INTERFACE String toString(signed in); -DOCTEST_INTERFACE String toString(unsigned in); -DOCTEST_INTERFACE String toString(long in); -DOCTEST_INTERFACE String toString(long unsigned in); -DOCTEST_INTERFACE String toString(long long in); -DOCTEST_INTERFACE String toString(long long unsigned in); - -template ::value, bool>::type = true> -String toString(const DOCTEST_REF_WRAP(T) value) { + DOCTEST_INTERFACE String toString(String in); + + DOCTEST_INTERFACE String toString(std::nullptr_t); + + DOCTEST_INTERFACE String toString(bool in); + + DOCTEST_INTERFACE String toString(float in); + DOCTEST_INTERFACE String toString(double in); + DOCTEST_INTERFACE String toString(double long in); + + DOCTEST_INTERFACE String toString(char in); + DOCTEST_INTERFACE String toString(char signed in); + DOCTEST_INTERFACE String toString(char unsigned in); + DOCTEST_INTERFACE String toString(short in); + DOCTEST_INTERFACE String toString(short unsigned in); + DOCTEST_INTERFACE String toString(signed in); + DOCTEST_INTERFACE String toString(unsigned in); + DOCTEST_INTERFACE String toString(long in); + DOCTEST_INTERFACE String toString(long unsigned in); + DOCTEST_INTERFACE String toString(long long in); + DOCTEST_INTERFACE String toString(long long unsigned in); + + template ::value, + bool>::type = true> + String toString(const DOCTEST_REF_WRAP(T) value) + { using UT = typename detail::types::underlying_type::type; return (DOCTEST_STRINGIFY(static_cast(value))); -} + } -namespace detail { - template - struct filldata + namespace detail { + template struct filldata { - static void fill(std::ostream* stream, const T& in) { + static void fill(std::ostream *stream, const T &in) + { #if defined(_MSC_VER) && _MSC_VER <= 1900 insert_hack_t::insert(*stream, in); #else operator<<(*stream, in); #endif - } + } }; -DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4866) -// NOLINTBEGIN(*-avoid-c-arrays) - template - struct filldata { - static void fill(std::ostream* stream, const T(&in)[N]) { - *stream << "["; - for (size_t i = 0; i < N; i++) { - if (i != 0) { *stream << ", "; } - *stream << (DOCTEST_STRINGIFY(in[i])); - } - *stream << "]"; - } + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4866) + // NOLINTBEGIN(*-avoid-c-arrays) + template struct filldata + { + static void fill(std::ostream *stream, const T (&in)[N]) + { + *stream << "["; + for (size_t i = 0; i < N; i++) { + if (i != 0) { + *stream << ", "; + } + *stream << (DOCTEST_STRINGIFY(in[i])); + } + *stream << "]"; + } }; -// NOLINTEND(*-avoid-c-arrays) -DOCTEST_MSVC_SUPPRESS_WARNING_POP + // NOLINTEND(*-avoid-c-arrays) + DOCTEST_MSVC_SUPPRESS_WARNING_POP // Specialized since we don't want the terminating null byte! -// NOLINTBEGIN(*-avoid-c-arrays) - template - struct filldata { - static void fill(std::ostream* stream, const char (&in)[N]) { - *stream << String(in, in[N - 1] ? N : N - 1); - } // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks) + // NOLINTBEGIN(*-avoid-c-arrays) + template struct filldata + { + static void fill(std::ostream *stream, const char (&in)[N]) + { + *stream << String(in, in[N - 1] ? N : N - 1); + } // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks) }; -// NOLINTEND(*-avoid-c-arrays) + // NOLINTEND(*-avoid-c-arrays) - template <> - struct filldata { - static void fill(std::ostream* stream, const void* in); + template <> struct filldata + { + static void fill(std::ostream *stream, const void *in); }; - template - struct filldata { -DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4180) - static void fill(std::ostream* stream, const T* in) { -DOCTEST_MSVC_SUPPRESS_WARNING_POP -DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wmicrosoft-cast") - filldata::fill(stream, + template struct filldata + { + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4180) + static void fill(std::ostream *stream, const T *in) + { + DOCTEST_MSVC_SUPPRESS_WARNING_POP + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wmicrosoft-cast") + filldata::fill(stream, #if DOCTEST_GCC == 0 || DOCTEST_GCC >= DOCTEST_COMPILER(4, 9, 0) - reinterpret_cast(in) + reinterpret_cast(in) #else - *reinterpret_cast(&in) + *reinterpret_cast(&in) #endif - ); -DOCTEST_CLANG_SUPPRESS_WARNING_POP - } + ); + DOCTEST_CLANG_SUPPRESS_WARNING_POP + } }; -} + } // namespace detail -struct DOCTEST_INTERFACE Approx -{ + struct DOCTEST_INTERFACE Approx + { Approx(double value); Approx operator()(double value) const; #ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS template - explicit Approx(const T& value, - typename detail::types::enable_if::value>::type* = - static_cast(nullptr)) { - *this = static_cast(value); + explicit Approx(const T &value, + typename detail::types::enable_if::value>::type + * = static_cast(nullptr)) + { + *this = static_cast(value); } #endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS - Approx& epsilon(double newEpsilon); + Approx &epsilon(double newEpsilon); #ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS template - typename std::enable_if::value, Approx&>::type epsilon( - const T& newEpsilon) { - m_epsilon = static_cast(newEpsilon); - return *this; + typename std::enable_if::value, Approx &>::type + epsilon(const T &newEpsilon) + { + m_epsilon = static_cast(newEpsilon); + return *this; } #endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS - Approx& scale(double newScale); + Approx &scale(double newScale); #ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS template - typename std::enable_if::value, Approx&>::type scale( - const T& newScale) { - m_scale = static_cast(newScale); - return *this; + typename std::enable_if::value, Approx &>::type + scale(const T &newScale) + { + m_scale = static_cast(newScale); + return *this; } #endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS @@ -1281,32 +1359,32 @@ struct DOCTEST_INTERFACE Approx double m_epsilon; double m_scale; double m_value; -}; + }; -DOCTEST_INTERFACE String toString(const Approx& in); + DOCTEST_INTERFACE String toString(const Approx &in); -DOCTEST_INTERFACE const ContextOptions* getContextOptions(); + DOCTEST_INTERFACE const ContextOptions *getContextOptions(); -template -struct DOCTEST_INTERFACE_DECL IsNaN -{ - F value; bool flipped; - IsNaN(F f, bool flip = false) : value(f), flipped(flip) { } - IsNaN operator!() const { return { value, !flipped }; } + template struct DOCTEST_INTERFACE_DECL IsNaN + { + F value; + bool flipped; + IsNaN(F f, bool flip = false) : value(f), flipped(flip) {} + IsNaN operator!() const { return {value, !flipped}; } operator bool() const; -}; + }; #ifndef __MINGW32__ -extern template struct DOCTEST_INTERFACE_DECL IsNaN; -extern template struct DOCTEST_INTERFACE_DECL IsNaN; -extern template struct DOCTEST_INTERFACE_DECL IsNaN; + extern template struct DOCTEST_INTERFACE_DECL IsNaN; + extern template struct DOCTEST_INTERFACE_DECL IsNaN; + extern template struct DOCTEST_INTERFACE_DECL IsNaN; #endif -DOCTEST_INTERFACE String toString(IsNaN in); -DOCTEST_INTERFACE String toString(IsNaN in); -DOCTEST_INTERFACE String toString(IsNaN in); + DOCTEST_INTERFACE String toString(IsNaN in); + DOCTEST_INTERFACE String toString(IsNaN in); + DOCTEST_INTERFACE String toString(IsNaN in); #ifndef DOCTEST_CONFIG_DISABLE -namespace detail { + namespace detail { // clang-format off #ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING template struct decay_array { using type = T; }; @@ -1334,30 +1412,31 @@ namespace detail { struct DOCTEST_INTERFACE Subcase { - SubcaseSignature m_signature; - bool m_entered = false; + SubcaseSignature m_signature; + bool m_entered = false; - Subcase(const String& name, const char* file, int line); - Subcase(const Subcase&) = delete; - Subcase(Subcase&&) = delete; - Subcase& operator=(const Subcase&) = delete; - Subcase& operator=(Subcase&&) = delete; - ~Subcase(); + Subcase(const String &name, const char *file, int line); + Subcase(const Subcase &) = delete; + Subcase(Subcase &&) = delete; + Subcase &operator=(const Subcase &) = delete; + Subcase &operator=(Subcase &&) = delete; + ~Subcase(); - operator bool() const; + operator bool() const; - private: - bool checkFilters(); + private: + bool checkFilters(); }; template - String stringifyBinaryExpr(const DOCTEST_REF_WRAP(L) lhs, const char* op, - const DOCTEST_REF_WRAP(R) rhs) { - return (DOCTEST_STRINGIFY(lhs)) + op + (DOCTEST_STRINGIFY(rhs)); + String stringifyBinaryExpr(const DOCTEST_REF_WRAP(L) lhs, const char *op, + const DOCTEST_REF_WRAP(R) rhs) + { + return (DOCTEST_STRINGIFY(lhs)) + op + (DOCTEST_STRINGIFY(rhs)); } #if DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 6, 0) -DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-comparison") + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-comparison") #endif // This will check if there is any way it could find a operator like member or friend and uses it. @@ -1365,64 +1444,66 @@ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-comparison") // this template, the template won't be instantiated due to SFINAE. Once the template is not // instantiated it can look for global operator using normal conversions. #ifdef __NVCC__ -#define SFINAE_OP(ret,op) ret +#define SFINAE_OP(ret, op) ret #else -#define SFINAE_OP(ret,op) decltype((void)(doctest::detail::declval() op doctest::detail::declval()),ret{}) +#define SFINAE_OP(ret, op) \ + decltype((void)(doctest::detail::declval() op doctest::detail::declval()), ret{}) #endif #define DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(op, op_str, op_macro) \ - template \ - DOCTEST_NOINLINE SFINAE_OP(Result,op) operator op(R&& rhs) { \ + template DOCTEST_NOINLINE SFINAE_OP(Result, op) operator op(R &&rhs) \ + { \ bool res = op_macro(doctest::detail::forward(lhs), doctest::detail::forward(rhs)); \ - if(m_at & assertType::is_false) \ - res = !res; \ - if(!res || doctest::getContextOptions()->success) \ - return Result(res, stringifyBinaryExpr(lhs, op_str, rhs)); \ - return Result(res); \ - } + if (m_at & assertType::is_false) \ + res = !res; \ + if (!res || doctest::getContextOptions()->success) \ + return Result(res, stringifyBinaryExpr(lhs, op_str, rhs)); \ + return Result(res); \ + } // more checks could be added - like in Catch: // https://github.com/catchorg/Catch2/pull/1480/files // https://github.com/catchorg/Catch2/pull/1481/files #define DOCTEST_FORBIT_EXPRESSION(rt, op) \ - template \ - rt& operator op(const R&) { \ - static_assert(deferred_false::value, \ - "Expression Too Complex Please Rewrite As Binary Comparison!"); \ - return *this; \ - } + template rt &operator op(const R &) \ + { \ + static_assert(deferred_false::value, \ + "Expression Too Complex Please Rewrite As Binary Comparison!"); \ + return *this; \ + } struct DOCTEST_INTERFACE Result // NOLINT(*-member-init) { - bool m_passed; - String m_decomp; - - Result() = default; // TODO: Why do we need this? (To remove NOLINT) - Result(bool passed, const String& decomposition = String()); - - // forbidding some expressions based on this table: https://en.cppreference.com/w/cpp/language/operator_precedence - DOCTEST_FORBIT_EXPRESSION(Result, &) - DOCTEST_FORBIT_EXPRESSION(Result, ^) - DOCTEST_FORBIT_EXPRESSION(Result, |) - DOCTEST_FORBIT_EXPRESSION(Result, &&) - DOCTEST_FORBIT_EXPRESSION(Result, ||) - DOCTEST_FORBIT_EXPRESSION(Result, ==) - DOCTEST_FORBIT_EXPRESSION(Result, !=) - DOCTEST_FORBIT_EXPRESSION(Result, <) - DOCTEST_FORBIT_EXPRESSION(Result, >) - DOCTEST_FORBIT_EXPRESSION(Result, <=) - DOCTEST_FORBIT_EXPRESSION(Result, >=) - DOCTEST_FORBIT_EXPRESSION(Result, =) - DOCTEST_FORBIT_EXPRESSION(Result, +=) - DOCTEST_FORBIT_EXPRESSION(Result, -=) - DOCTEST_FORBIT_EXPRESSION(Result, *=) - DOCTEST_FORBIT_EXPRESSION(Result, /=) - DOCTEST_FORBIT_EXPRESSION(Result, %=) - DOCTEST_FORBIT_EXPRESSION(Result, <<=) - DOCTEST_FORBIT_EXPRESSION(Result, >>=) - DOCTEST_FORBIT_EXPRESSION(Result, &=) - DOCTEST_FORBIT_EXPRESSION(Result, ^=) - DOCTEST_FORBIT_EXPRESSION(Result, |=) + bool m_passed; + String m_decomp; + + Result() = default; // TODO: Why do we need this? (To remove NOLINT) + Result(bool passed, const String &decomposition = String()); + + // forbidding some expressions based on this table: + // https://en.cppreference.com/w/cpp/language/operator_precedence + DOCTEST_FORBIT_EXPRESSION(Result, &) + DOCTEST_FORBIT_EXPRESSION(Result, ^) + DOCTEST_FORBIT_EXPRESSION(Result, |) + DOCTEST_FORBIT_EXPRESSION(Result, &&) + DOCTEST_FORBIT_EXPRESSION(Result, ||) + DOCTEST_FORBIT_EXPRESSION(Result, ==) + DOCTEST_FORBIT_EXPRESSION(Result, !=) + DOCTEST_FORBIT_EXPRESSION(Result, <) + DOCTEST_FORBIT_EXPRESSION(Result, >) + DOCTEST_FORBIT_EXPRESSION(Result, <=) + DOCTEST_FORBIT_EXPRESSION(Result, >=) + DOCTEST_FORBIT_EXPRESSION(Result, =) + DOCTEST_FORBIT_EXPRESSION(Result, +=) + DOCTEST_FORBIT_EXPRESSION(Result, -=) + DOCTEST_FORBIT_EXPRESSION(Result, *=) + DOCTEST_FORBIT_EXPRESSION(Result, /=) + DOCTEST_FORBIT_EXPRESSION(Result, %=) + DOCTEST_FORBIT_EXPRESSION(Result, <<=) + DOCTEST_FORBIT_EXPRESSION(Result, >>=) + DOCTEST_FORBIT_EXPRESSION(Result, &=) + DOCTEST_FORBIT_EXPRESSION(Result, ^=) + DOCTEST_FORBIT_EXPRESSION(Result, |=) }; #ifndef DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION @@ -1430,23 +1511,24 @@ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-comparison") DOCTEST_CLANG_SUPPRESS_WARNING_PUSH DOCTEST_CLANG_SUPPRESS_WARNING("-Wsign-conversion") DOCTEST_CLANG_SUPPRESS_WARNING("-Wsign-compare") - //DOCTEST_CLANG_SUPPRESS_WARNING("-Wdouble-promotion") - //DOCTEST_CLANG_SUPPRESS_WARNING("-Wconversion") - //DOCTEST_CLANG_SUPPRESS_WARNING("-Wfloat-equal") + // DOCTEST_CLANG_SUPPRESS_WARNING("-Wdouble-promotion") + // DOCTEST_CLANG_SUPPRESS_WARNING("-Wconversion") + // DOCTEST_CLANG_SUPPRESS_WARNING("-Wfloat-equal") DOCTEST_GCC_SUPPRESS_WARNING_PUSH DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-conversion") DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-compare") - //DOCTEST_GCC_SUPPRESS_WARNING("-Wdouble-promotion") - //DOCTEST_GCC_SUPPRESS_WARNING("-Wconversion") - //DOCTEST_GCC_SUPPRESS_WARNING("-Wfloat-equal") + // DOCTEST_GCC_SUPPRESS_WARNING("-Wdouble-promotion") + // DOCTEST_GCC_SUPPRESS_WARNING("-Wconversion") + // DOCTEST_GCC_SUPPRESS_WARNING("-Wfloat-equal") DOCTEST_MSVC_SUPPRESS_WARNING_PUSH // https://stackoverflow.com/questions/39479163 what's the difference between 4018 and 4389 DOCTEST_MSVC_SUPPRESS_WARNING(4388) // signed/unsigned mismatch DOCTEST_MSVC_SUPPRESS_WARNING(4389) // 'operator' : signed/unsigned mismatch DOCTEST_MSVC_SUPPRESS_WARNING(4018) // 'expression' : signed/unsigned mismatch - //DOCTEST_MSVC_SUPPRESS_WARNING(4805) // 'operation' : unsafe mix of type 'type' and type 'type' in operation + // DOCTEST_MSVC_SUPPRESS_WARNING(4805) // 'operation' : unsafe mix of type 'type' and type + // 'type' in operation #endif // DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION @@ -1465,11 +1547,12 @@ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-comparison") // clang-format on #define DOCTEST_RELATIONAL_OP(name, op) \ - template \ - DOCTEST_COMPARISON_RETURN_TYPE name(const DOCTEST_REF_WRAP(L) lhs, \ - const DOCTEST_REF_WRAP(R) rhs) { \ - return lhs op rhs; \ - } + template \ + DOCTEST_COMPARISON_RETURN_TYPE name(const DOCTEST_REF_WRAP(L) lhs, \ + const DOCTEST_REF_WRAP(R) rhs) \ + { \ + return lhs op rhs; \ + } DOCTEST_RELATIONAL_OP(eq, ==) DOCTEST_RELATIONAL_OP(ne, !=) @@ -1498,61 +1581,62 @@ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-comparison") // cppcheck-suppress copyCtorAndEqOperator struct Expression_lhs { - L lhs; - assertType::Enum m_at; + L lhs; + assertType::Enum m_at; - explicit Expression_lhs(L&& in, assertType::Enum at) - : lhs(static_cast(in)) - , m_at(at) {} + explicit Expression_lhs(L &&in, assertType::Enum at) : lhs(static_cast(in)), m_at(at) {} - DOCTEST_NOINLINE operator Result() { -// this is needed only for MSVC 2015 -DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4800) // 'int': forcing value to bool - bool res = static_cast(lhs); -DOCTEST_MSVC_SUPPRESS_WARNING_POP - if(m_at & assertType::is_false) { //!OCLINT bitwise operator in conditional - res = !res; - } + DOCTEST_NOINLINE operator Result() + { + // this is needed only for MSVC 2015 + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4800) // 'int': forcing value to bool + bool res = static_cast(lhs); + DOCTEST_MSVC_SUPPRESS_WARNING_POP + if (m_at & assertType::is_false) { //! OCLINT bitwise operator in conditional + res = !res; + } - if(!res || getContextOptions()->success) { - return { res, (DOCTEST_STRINGIFY(lhs)) }; - } - return { res }; + if (!res || getContextOptions()->success) { + return {res, (DOCTEST_STRINGIFY(lhs))}; } + return {res}; + } - /* This is required for user-defined conversions from Expression_lhs to L */ - operator L() const { return lhs; } + /* This is required for user-defined conversions from Expression_lhs to L */ + operator L() const { return lhs; } - // clang-format off + // clang-format off DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>, " > ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<, " < ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional - // clang-format on - - // forbidding some expressions based on this table: https://en.cppreference.com/w/cpp/language/operator_precedence - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ^) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, |) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &&) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ||) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, =) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, +=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, -=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, *=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, /=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, %=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, <<=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, >>=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ^=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, |=) - // these 2 are unfortunate because they should be allowed - they have higher precedence over the comparisons, but the - // ExpressionDecomposer class uses the left shift operator to capture the left operand of the binary expression... - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, <<) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, >>) + // clang-format on + + // forbidding some expressions based on this table: + // https://en.cppreference.com/w/cpp/language/operator_precedence + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ^) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, |) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &&) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ||) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, =) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, +=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, -=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, *=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, /=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, %=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, <<=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, >>=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ^=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, |=) + // these 2 are unfortunate because they should be allowed - they have higher precedence over + // the comparisons, but the ExpressionDecomposer class uses the left shift operator to capture + // the left operand of the binary expression... + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, <<) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, >>) }; #ifndef DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION @@ -1564,104 +1648,100 @@ DOCTEST_MSVC_SUPPRESS_WARNING_POP #endif // DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION #if DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 6, 0) -DOCTEST_CLANG_SUPPRESS_WARNING_POP + DOCTEST_CLANG_SUPPRESS_WARNING_POP #endif struct DOCTEST_INTERFACE ExpressionDecomposer { - assertType::Enum m_at; - - ExpressionDecomposer(assertType::Enum at); - - // The right operator for capturing expressions is "<=" instead of "<<" (based on the operator precedence table) - // but then there will be warnings from GCC about "-Wparentheses" and since "_Pragma()" is problematic this will stay for now... - // https://github.com/catchorg/Catch2/issues/870 - // https://github.com/catchorg/Catch2/issues/565 - template - Expression_lhs operator<<(L&& operand) { - return Expression_lhs(static_cast(operand), m_at); - } - - template ::value,void >::type* = nullptr> - Expression_lhs operator<<(const L &operand) { - return Expression_lhs(operand, m_at); - } + assertType::Enum m_at; + + ExpressionDecomposer(assertType::Enum at); + + // The right operator for capturing expressions is "<=" instead of "<<" (based on the operator + // precedence table) but then there will be warnings from GCC about "-Wparentheses" and since + // "_Pragma()" is problematic this will stay for now... + // https://github.com/catchorg/Catch2/issues/870 + // https://github.com/catchorg/Catch2/issues/565 + template Expression_lhs operator<<(L &&operand) + { + return Expression_lhs(static_cast(operand), m_at); + } + + template ::value, + void>::type * = nullptr> + Expression_lhs operator<<(const L &operand) + { + return Expression_lhs(operand, m_at); + } }; struct DOCTEST_INTERFACE TestSuite { - const char* m_test_suite = nullptr; - const char* m_description = nullptr; - bool m_skip = false; - bool m_no_breaks = false; - bool m_no_output = false; - bool m_may_fail = false; - bool m_should_fail = false; - int m_expected_failures = 0; - double m_timeout = 0; - - TestSuite& operator*(const char* in); - - template - TestSuite& operator*(const T& in) { - in.fill(*this); - return *this; - } + const char *m_test_suite = nullptr; + const char *m_description = nullptr; + bool m_skip = false; + bool m_no_breaks = false; + bool m_no_output = false; + bool m_may_fail = false; + bool m_should_fail = false; + int m_expected_failures = 0; + double m_timeout = 0; + + TestSuite &operator*(const char *in); + + template TestSuite &operator*(const T &in) + { + in.fill(*this); + return *this; + } }; using funcType = void (*)(); struct DOCTEST_INTERFACE TestCase : public TestCaseData { - funcType m_test; // a function pointer to the test case + funcType m_test; // a function pointer to the test case - String m_type; // for templated test cases - gets appended to the real name - int m_template_id; // an ID used to distinguish between the different versions of a templated test case - String m_full_name; // contains the name (only for templated test cases!) + the template type + String m_type; // for templated test cases - gets appended to the real name + int m_template_id; // an ID used to distinguish between the different versions of a templated + // test case + String m_full_name; // contains the name (only for templated test cases!) + the template type - TestCase(funcType test, const char* file, unsigned line, const TestSuite& test_suite, - const String& type = String(), int template_id = -1); + TestCase(funcType test, const char *file, unsigned line, const TestSuite &test_suite, + const String &type = String(), int template_id = -1); - TestCase(const TestCase& other); - TestCase(TestCase&&) = delete; + TestCase(const TestCase &other); + TestCase(TestCase &&) = delete; - DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(26434) // hides a non-virtual function - TestCase& operator=(const TestCase& other); - DOCTEST_MSVC_SUPPRESS_WARNING_POP + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(26434) // hides a non-virtual function + TestCase &operator=(const TestCase &other); + DOCTEST_MSVC_SUPPRESS_WARNING_POP - TestCase& operator=(TestCase&&) = delete; + TestCase &operator=(TestCase &&) = delete; - TestCase& operator*(const char* in); + TestCase &operator*(const char *in); - template - TestCase& operator*(const T& in) { - in.fill(*this); - return *this; - } + template TestCase &operator*(const T &in) + { + in.fill(*this); + return *this; + } - bool operator<(const TestCase& other) const; + bool operator<(const TestCase &other) const; - ~TestCase() = default; + ~TestCase() = default; }; // forward declarations of functions used by the macros - DOCTEST_INTERFACE int regTest(const TestCase& tc); - DOCTEST_INTERFACE int setTestSuite(const TestSuite& ts); + DOCTEST_INTERFACE int regTest(const TestCase &tc); + DOCTEST_INTERFACE int setTestSuite(const TestSuite &ts); DOCTEST_INTERFACE bool isDebuggerActive(); - template - int instantiationHelper(const T&) { return 0; } + template int instantiationHelper(const T &) { return 0; } namespace binaryAssertComparison { - enum Enum - { - eq = 0, - ne, - gt, - lt, - ge, - le - }; + enum Enum { eq = 0, ne, gt, lt, ge, le }; } // namespace binaryAssertComparison // clang-format off @@ -1680,311 +1760,311 @@ DOCTEST_CLANG_SUPPRESS_WARNING_POP struct DOCTEST_INTERFACE ResultBuilder : public AssertData { - ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr, - const char* exception_type = "", const String& exception_string = ""); + ResultBuilder(assertType::Enum at, const char *file, int line, const char *expr, + const char *exception_type = "", const String &exception_string = ""); - ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr, - const char* exception_type, const Contains& exception_string); + ResultBuilder(assertType::Enum at, const char *file, int line, const char *expr, + const char *exception_type, const Contains &exception_string); - void setResult(const Result& res); + void setResult(const Result &res); - template - DOCTEST_NOINLINE bool binary_assert(const DOCTEST_REF_WRAP(L) lhs, - const DOCTEST_REF_WRAP(R) rhs) { - m_failed = !RelationalComparator()(lhs, rhs); - if (m_failed || getContextOptions()->success) { - m_decomp = stringifyBinaryExpr(lhs, ", ", rhs); - } - return !m_failed; + template + DOCTEST_NOINLINE bool binary_assert(const DOCTEST_REF_WRAP(L) lhs, + const DOCTEST_REF_WRAP(R) rhs) + { + m_failed = !RelationalComparator()(lhs, rhs); + if (m_failed || getContextOptions()->success) { + m_decomp = stringifyBinaryExpr(lhs, ", ", rhs); } + return !m_failed; + } - template - DOCTEST_NOINLINE bool unary_assert(const DOCTEST_REF_WRAP(L) val) { - m_failed = !val; - - if (m_at & assertType::is_false) { //!OCLINT bitwise operator in conditional - m_failed = !m_failed; - } + template DOCTEST_NOINLINE bool unary_assert(const DOCTEST_REF_WRAP(L) val) + { + m_failed = !val; - if (m_failed || getContextOptions()->success) { - m_decomp = (DOCTEST_STRINGIFY(val)); - } + if (m_at & assertType::is_false) { //! OCLINT bitwise operator in conditional + m_failed = !m_failed; + } - return !m_failed; + if (m_failed || getContextOptions()->success) { + m_decomp = (DOCTEST_STRINGIFY(val)); } - void translateException(); + return !m_failed; + } + + void translateException(); - bool log(); - void react() const; + bool log(); + void react() const; }; namespace assertAction { - enum Enum - { - nothing = 0, - dbgbreak = 1, - shouldthrow = 2 - }; + enum Enum { nothing = 0, dbgbreak = 1, shouldthrow = 2 }; } // namespace assertAction - DOCTEST_INTERFACE void failed_out_of_a_testing_context(const AssertData& ad); + DOCTEST_INTERFACE void failed_out_of_a_testing_context(const AssertData &ad); - DOCTEST_INTERFACE bool decomp_assert(assertType::Enum at, const char* file, int line, - const char* expr, const Result& result); + DOCTEST_INTERFACE bool decomp_assert(assertType::Enum at, const char *file, int line, + const char *expr, const Result &result); #define DOCTEST_ASSERT_OUT_OF_TESTS(decomp) \ - do { \ - if(!is_running_in_test) { \ - if(failed) { \ - ResultBuilder rb(at, file, line, expr); \ - rb.m_failed = failed; \ - rb.m_decomp = decomp; \ - failed_out_of_a_testing_context(rb); \ - if(isDebuggerActive() && !getContextOptions()->no_breaks) \ - DOCTEST_BREAK_INTO_DEBUGGER(); \ - if(checkIfShouldThrow(at)) \ - throwException(); \ - } \ - return !failed; \ - } \ - } while(false) + do { \ + if (!is_running_in_test) { \ + if (failed) { \ + ResultBuilder rb(at, file, line, expr); \ + rb.m_failed = failed; \ + rb.m_decomp = decomp; \ + failed_out_of_a_testing_context(rb); \ + if (isDebuggerActive() && !getContextOptions()->no_breaks) \ + DOCTEST_BREAK_INTO_DEBUGGER(); \ + if (checkIfShouldThrow(at)) \ + throwException(); \ + } \ + return !failed; \ + } \ + } while (false) #define DOCTEST_ASSERT_IN_TESTS(decomp) \ - ResultBuilder rb(at, file, line, expr); \ - rb.m_failed = failed; \ - if(rb.m_failed || getContextOptions()->success) \ - rb.m_decomp = decomp; \ - if(rb.log()) \ - DOCTEST_BREAK_INTO_DEBUGGER(); \ - if(rb.m_failed && checkIfShouldThrow(at)) \ - throwException() + ResultBuilder rb(at, file, line, expr); \ + rb.m_failed = failed; \ + if (rb.m_failed || getContextOptions()->success) \ + rb.m_decomp = decomp; \ + if (rb.log()) \ + DOCTEST_BREAK_INTO_DEBUGGER(); \ + if (rb.m_failed && checkIfShouldThrow(at)) \ + throwException() template - DOCTEST_NOINLINE bool binary_assert(assertType::Enum at, const char* file, int line, - const char* expr, const DOCTEST_REF_WRAP(L) lhs, - const DOCTEST_REF_WRAP(R) rhs) { - bool failed = !RelationalComparator()(lhs, rhs); - - // ################################################################################### - // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT - // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED - // ################################################################################### - DOCTEST_ASSERT_OUT_OF_TESTS(stringifyBinaryExpr(lhs, ", ", rhs)); - DOCTEST_ASSERT_IN_TESTS(stringifyBinaryExpr(lhs, ", ", rhs)); - return !failed; + DOCTEST_NOINLINE bool binary_assert(assertType::Enum at, const char *file, int line, + const char *expr, const DOCTEST_REF_WRAP(L) lhs, + const DOCTEST_REF_WRAP(R) rhs) + { + bool failed = !RelationalComparator()(lhs, rhs); + + // ################################################################################### + // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT + // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED + // ################################################################################### + DOCTEST_ASSERT_OUT_OF_TESTS(stringifyBinaryExpr(lhs, ", ", rhs)); + DOCTEST_ASSERT_IN_TESTS(stringifyBinaryExpr(lhs, ", ", rhs)); + return !failed; } template - DOCTEST_NOINLINE bool unary_assert(assertType::Enum at, const char* file, int line, - const char* expr, const DOCTEST_REF_WRAP(L) val) { - bool failed = !val; - - if(at & assertType::is_false) //!OCLINT bitwise operator in conditional - failed = !failed; - - // ################################################################################### - // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT - // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED - // ################################################################################### - DOCTEST_ASSERT_OUT_OF_TESTS((DOCTEST_STRINGIFY(val))); - DOCTEST_ASSERT_IN_TESTS((DOCTEST_STRINGIFY(val))); - return !failed; + DOCTEST_NOINLINE bool unary_assert(assertType::Enum at, const char *file, int line, + const char *expr, const DOCTEST_REF_WRAP(L) val) + { + bool failed = !val; + + if (at & assertType::is_false) //! OCLINT bitwise operator in conditional + failed = !failed; + + // ################################################################################### + // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT + // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED + // ################################################################################### + DOCTEST_ASSERT_OUT_OF_TESTS((DOCTEST_STRINGIFY(val))); + DOCTEST_ASSERT_IN_TESTS((DOCTEST_STRINGIFY(val))); + return !failed; } struct DOCTEST_INTERFACE IExceptionTranslator { - DOCTEST_DECLARE_INTERFACE(IExceptionTranslator) - virtual bool translate(String&) const = 0; + DOCTEST_DECLARE_INTERFACE(IExceptionTranslator) + virtual bool translate(String &) const = 0; }; template - class ExceptionTranslator : public IExceptionTranslator //!OCLINT destructor of virtual class + class ExceptionTranslator : public IExceptionTranslator //! OCLINT destructor of virtual class { public: - explicit ExceptionTranslator(String (*translateFunction)(T)) - : m_translateFunction(translateFunction) {} + explicit ExceptionTranslator(String (*translateFunction)(T)) + : m_translateFunction(translateFunction) + { + } - bool translate(String& res) const override { + bool translate(String &res) const override + { #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS - try { - throw; // lgtm [cpp/rethrow-no-exception] - // cppcheck-suppress catchExceptionByValue - } catch(const T& ex) { - res = m_translateFunction(ex); //!OCLINT parameter reassignment - return true; - } catch(...) {} //!OCLINT - empty catch statement -#endif // DOCTEST_CONFIG_NO_EXCEPTIONS - static_cast(res); // to silence -Wunused-parameter - return false; + try { + throw; // lgtm [cpp/rethrow-no-exception] + // cppcheck-suppress catchExceptionByValue + } + catch (const T &ex) { + res = m_translateFunction(ex); //! OCLINT parameter reassignment + return true; } + catch (...) { + } //! OCLINT - empty catch statement +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS + static_cast(res); // to silence -Wunused-parameter + return false; + } private: - String (*m_translateFunction)(T); + String (*m_translateFunction)(T); }; - DOCTEST_INTERFACE void registerExceptionTranslatorImpl(const IExceptionTranslator* et); + DOCTEST_INTERFACE void registerExceptionTranslatorImpl(const IExceptionTranslator *et); // ContextScope base class used to allow implementing methods of ContextScope // that don't depend on the template parameter in doctest.cpp. - struct DOCTEST_INTERFACE ContextScopeBase : public IContextScope { - ContextScopeBase(const ContextScopeBase&) = delete; + struct DOCTEST_INTERFACE ContextScopeBase : public IContextScope + { + ContextScopeBase(const ContextScopeBase &) = delete; - ContextScopeBase& operator=(const ContextScopeBase&) = delete; - ContextScopeBase& operator=(ContextScopeBase&&) = delete; + ContextScopeBase &operator=(const ContextScopeBase &) = delete; + ContextScopeBase &operator=(ContextScopeBase &&) = delete; - ~ContextScopeBase() override = default; + ~ContextScopeBase() override = default; protected: - ContextScopeBase(); - ContextScopeBase(ContextScopeBase&& other) noexcept; + ContextScopeBase(); + ContextScopeBase(ContextScopeBase &&other) noexcept; - void destroy(); - bool need_to_destroy{true}; + void destroy(); + bool need_to_destroy{true}; }; template class ContextScope : public ContextScopeBase { - L lambda_; + L lambda_; public: - explicit ContextScope(const L &lambda) : lambda_(lambda) {} - explicit ContextScope(L&& lambda) : lambda_(static_cast(lambda)) { } + explicit ContextScope(const L &lambda) : lambda_(lambda) {} + explicit ContextScope(L &&lambda) : lambda_(static_cast(lambda)) {} - ContextScope(const ContextScope&) = delete; - ContextScope(ContextScope&&) noexcept = default; + ContextScope(const ContextScope &) = delete; + ContextScope(ContextScope &&) noexcept = default; - ContextScope& operator=(const ContextScope&) = delete; - ContextScope& operator=(ContextScope&&) = delete; + ContextScope &operator=(const ContextScope &) = delete; + ContextScope &operator=(ContextScope &&) = delete; - void stringify(std::ostream* s) const override { lambda_(s); } + void stringify(std::ostream *s) const override { lambda_(s); } - ~ContextScope() override { - if (need_to_destroy) { - destroy(); - } + ~ContextScope() override + { + if (need_to_destroy) { + destroy(); } + } }; struct DOCTEST_INTERFACE MessageBuilder : public MessageData { - std::ostream* m_stream; - bool logged = false; + std::ostream *m_stream; + bool logged = false; - MessageBuilder(const char* file, int line, assertType::Enum severity); + MessageBuilder(const char *file, int line, assertType::Enum severity); - MessageBuilder(const MessageBuilder&) = delete; - MessageBuilder(MessageBuilder&&) = delete; + MessageBuilder(const MessageBuilder &) = delete; + MessageBuilder(MessageBuilder &&) = delete; - MessageBuilder& operator=(const MessageBuilder&) = delete; - MessageBuilder& operator=(MessageBuilder&&) = delete; + MessageBuilder &operator=(const MessageBuilder &) = delete; + MessageBuilder &operator=(MessageBuilder &&) = delete; - ~MessageBuilder(); + ~MessageBuilder(); - // the preferred way of chaining parameters for stringification -DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4866) - template - MessageBuilder& operator,(const T& in) { - *m_stream << (DOCTEST_STRINGIFY(in)); - return *this; - } -DOCTEST_MSVC_SUPPRESS_WARNING_POP + // the preferred way of chaining parameters for stringification + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4866) + template MessageBuilder &operator,(const T &in) + { + *m_stream << (DOCTEST_STRINGIFY(in)); + return *this; + } + DOCTEST_MSVC_SUPPRESS_WARNING_POP - // kept here just for backwards-compatibility - the comma operator should be preferred now - template - MessageBuilder& operator<<(const T& in) { return this->operator,(in); } + // kept here just for backwards-compatibility - the comma operator should be preferred now + template MessageBuilder &operator<<(const T &in) { return this->operator,(in); } - // the `,` operator has the lowest operator precedence - if `<<` is used by the user then - // the `,` operator will be called last which is not what we want and thus the `*` operator - // is used first (has higher operator precedence compared to `<<`) so that we guarantee that - // an operator of the MessageBuilder class is called first before the rest of the parameters - template - MessageBuilder& operator*(const T& in) { return this->operator,(in); } + // the `,` operator has the lowest operator precedence - if `<<` is used by the user then + // the `,` operator will be called last which is not what we want and thus the `*` operator + // is used first (has higher operator precedence compared to `<<`) so that we guarantee that + // an operator of the MessageBuilder class is called first before the rest of the parameters + template MessageBuilder &operator*(const T &in) { return this->operator,(in); } - bool log(); - void react(); + bool log(); + void react(); }; - template - ContextScope MakeContextScope(const L &lambda) { - return ContextScope(lambda); + template ContextScope MakeContextScope(const L &lambda) + { + return ContextScope(lambda); } -} // namespace detail + } // namespace detail #define DOCTEST_DEFINE_DECORATOR(name, type, def) \ - struct name \ - { \ - type data; \ - name(type in = def) \ - : data(in) {} \ - void fill(detail::TestCase& state) const { state.DOCTEST_CAT(m_, name) = data; } \ - void fill(detail::TestSuite& state) const { state.DOCTEST_CAT(m_, name) = data; } \ - } - -DOCTEST_DEFINE_DECORATOR(test_suite, const char*, ""); -DOCTEST_DEFINE_DECORATOR(description, const char*, ""); -DOCTEST_DEFINE_DECORATOR(skip, bool, true); -DOCTEST_DEFINE_DECORATOR(no_breaks, bool, true); -DOCTEST_DEFINE_DECORATOR(no_output, bool, true); -DOCTEST_DEFINE_DECORATOR(timeout, double, 0); -DOCTEST_DEFINE_DECORATOR(may_fail, bool, true); -DOCTEST_DEFINE_DECORATOR(should_fail, bool, true); -DOCTEST_DEFINE_DECORATOR(expected_failures, int, 0); - -template -int registerExceptionTranslator(String (*translateFunction)(T)) { + struct name \ + { \ + type data; \ + name(type in = def) : data(in) {} \ + void fill(detail::TestCase &state) const { state.DOCTEST_CAT(m_, name) = data; } \ + void fill(detail::TestSuite &state) const { state.DOCTEST_CAT(m_, name) = data; } \ + } + + DOCTEST_DEFINE_DECORATOR(test_suite, const char *, ""); + DOCTEST_DEFINE_DECORATOR(description, const char *, ""); + DOCTEST_DEFINE_DECORATOR(skip, bool, true); + DOCTEST_DEFINE_DECORATOR(no_breaks, bool, true); + DOCTEST_DEFINE_DECORATOR(no_output, bool, true); + DOCTEST_DEFINE_DECORATOR(timeout, double, 0); + DOCTEST_DEFINE_DECORATOR(may_fail, bool, true); + DOCTEST_DEFINE_DECORATOR(should_fail, bool, true); + DOCTEST_DEFINE_DECORATOR(expected_failures, int, 0); + + template int registerExceptionTranslator(String (*translateFunction)(T)) + { DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wexit-time-destructors") static detail::ExceptionTranslator exceptionTranslator(translateFunction); DOCTEST_CLANG_SUPPRESS_WARNING_POP detail::registerExceptionTranslatorImpl(&exceptionTranslator); return 0; -} + } } // namespace doctest // in a separate namespace outside of doctest because the DOCTEST_TEST_SUITE macro // introduces an anonymous namespace in which getCurrentTestSuite gets overridden namespace doctest_detail_test_suite_ns { -DOCTEST_INTERFACE doctest::detail::TestSuite& getCurrentTestSuite(); + DOCTEST_INTERFACE doctest::detail::TestSuite &getCurrentTestSuite(); } // namespace doctest_detail_test_suite_ns namespace doctest { #else // DOCTEST_CONFIG_DISABLE -template -int registerExceptionTranslator(String (*)(T)) { - return 0; -} + template int registerExceptionTranslator(String (*)(T)) { return 0; } #endif // DOCTEST_CONFIG_DISABLE -namespace detail { - using assert_handler = void (*)(const AssertData&); + namespace detail { + using assert_handler = void (*)(const AssertData &); struct ContextState; -} // namespace detail + } // namespace detail -class DOCTEST_INTERFACE Context -{ - detail::ContextState* p; + class DOCTEST_INTERFACE Context + { + detail::ContextState *p; - void parseArgs(int argc, const char* const* argv, bool withDefaults = false); + void parseArgs(int argc, const char *const *argv, bool withDefaults = false); -public: - explicit Context(int argc = 0, const char* const* argv = nullptr); + public: + explicit Context(int argc = 0, const char *const *argv = nullptr); - Context(const Context&) = delete; - Context(Context&&) = delete; + Context(const Context &) = delete; + Context(Context &&) = delete; - Context& operator=(const Context&) = delete; - Context& operator=(Context&&) = delete; + Context &operator=(const Context &) = delete; + Context &operator=(Context &&) = delete; ~Context(); // NOLINT(performance-trivially-destructible) - void applyCommandLine(int argc, const char* const* argv); + void applyCommandLine(int argc, const char *const *argv); - void addFilter(const char* filter, const char* value); + void addFilter(const char *filter, const char *value); void clearFilters(); - void setOption(const char* option, bool value); - void setOption(const char* option, int value); - void setOption(const char* option, const char* value); + void setOption(const char *option, bool value); + void setOption(const char *option, int value); + void setOption(const char *option, const char *value); bool shouldExit(); @@ -1992,125 +2072,128 @@ class DOCTEST_INTERFACE Context void setAssertHandler(detail::assert_handler ah); - void setCout(std::ostream* out); + void setCout(std::ostream *out); int run(); -}; - -namespace TestCaseFailureReason { - enum Enum - { - None = 0, - AssertFailure = 1, // an assertion has failed in the test case - Exception = 2, // test case threw an exception - Crash = 4, // a crash... - TooManyFailedAsserts = 8, // the abort-after option - Timeout = 16, // see the timeout decorator - ShouldHaveFailedButDidnt = 32, // see the should_fail decorator - ShouldHaveFailedAndDid = 64, // see the should_fail decorator - DidntFailExactlyNumTimes = 128, // see the expected_failures decorator - FailedExactlyNumTimes = 256, // see the expected_failures decorator - CouldHaveFailedAndDid = 512 // see the may_fail decorator + }; + + namespace TestCaseFailureReason { + enum Enum { + None = 0, + AssertFailure = 1, // an assertion has failed in the test case + Exception = 2, // test case threw an exception + Crash = 4, // a crash... + TooManyFailedAsserts = 8, // the abort-after option + Timeout = 16, // see the timeout decorator + ShouldHaveFailedButDidnt = 32, // see the should_fail decorator + ShouldHaveFailedAndDid = 64, // see the should_fail decorator + DidntFailExactlyNumTimes = 128, // see the expected_failures decorator + FailedExactlyNumTimes = 256, // see the expected_failures decorator + CouldHaveFailedAndDid = 512 // see the may_fail decorator }; -} // namespace TestCaseFailureReason + } // namespace TestCaseFailureReason -struct DOCTEST_INTERFACE CurrentTestCaseStats -{ + struct DOCTEST_INTERFACE CurrentTestCaseStats + { int numAssertsCurrentTest; int numAssertsFailedCurrentTest; double seconds; int failure_flags; // use TestCaseFailureReason::Enum bool testCaseSuccess; -}; + }; -struct DOCTEST_INTERFACE TestCaseException -{ + struct DOCTEST_INTERFACE TestCaseException + { String error_string; bool is_crash; -}; + }; -struct DOCTEST_INTERFACE TestRunStats -{ + struct DOCTEST_INTERFACE TestRunStats + { unsigned numTestCases; unsigned numTestCasesPassingFilters; unsigned numTestSuitesPassingFilters; unsigned numTestCasesFailed; int numAsserts; int numAssertsFailed; -}; + }; -struct QueryData -{ - const TestRunStats* run_stats = nullptr; - const TestCaseData** data = nullptr; + struct QueryData + { + const TestRunStats *run_stats = nullptr; + const TestCaseData **data = nullptr; unsigned num_data = 0; -}; + }; -struct DOCTEST_INTERFACE IReporter -{ + struct DOCTEST_INTERFACE IReporter + { // The constructor has to accept "const ContextOptions&" as a single argument // which has most of the options for the run + a pointer to the stdout stream // Reporter(const ContextOptions& in) // called when a query should be reported (listing test cases, printing the version, etc.) - virtual void report_query(const QueryData&) = 0; + virtual void report_query(const QueryData &) = 0; // called when the whole test run starts virtual void test_run_start() = 0; // called when the whole test run ends (caching a pointer to the input doesn't make sense here) - virtual void test_run_end(const TestRunStats&) = 0; + virtual void test_run_end(const TestRunStats &) = 0; // called when a test case is started (safe to cache a pointer to the input) - virtual void test_case_start(const TestCaseData&) = 0; - // called when a test case is reentered because of unfinished subcases (safe to cache a pointer to the input) - virtual void test_case_reenter(const TestCaseData&) = 0; + virtual void test_case_start(const TestCaseData &) = 0; + // called when a test case is reentered because of unfinished subcases (safe to cache a pointer + // to the input) + virtual void test_case_reenter(const TestCaseData &) = 0; // called when a test case has ended - virtual void test_case_end(const CurrentTestCaseStats&) = 0; + virtual void test_case_end(const CurrentTestCaseStats &) = 0; // called when an exception is thrown from the test case (or it crashes) - virtual void test_case_exception(const TestCaseException&) = 0; + virtual void test_case_exception(const TestCaseException &) = 0; // called whenever a subcase is entered (don't cache pointers to the input) - virtual void subcase_start(const SubcaseSignature&) = 0; + virtual void subcase_start(const SubcaseSignature &) = 0; // called whenever a subcase is exited (don't cache pointers to the input) virtual void subcase_end() = 0; // called for each assert (don't cache pointers to the input) - virtual void log_assert(const AssertData&) = 0; + virtual void log_assert(const AssertData &) = 0; // called for each message (don't cache pointers to the input) - virtual void log_message(const MessageData&) = 0; + virtual void log_message(const MessageData &) = 0; - // called when a test case is skipped either because it doesn't pass the filters, has a skip decorator - // or isn't in the execution range (between first and last) (safe to cache a pointer to the input) - virtual void test_case_skipped(const TestCaseData&) = 0; + // called when a test case is skipped either because it doesn't pass the filters, has a skip + // decorator or isn't in the execution range (between first and last) (safe to cache a pointer + // to the input) + virtual void test_case_skipped(const TestCaseData &) = 0; DOCTEST_DECLARE_INTERFACE(IReporter) // can obtain all currently active contexts and stringify them if one wishes to do so static int get_num_active_contexts(); - static const IContextScope* const* get_active_contexts(); + static const IContextScope *const *get_active_contexts(); - // can iterate through contexts which have been stringified automatically in their destructors when an exception has been thrown + // can iterate through contexts which have been stringified automatically in their destructors + // when an exception has been thrown static int get_num_stringified_contexts(); - static const String* get_stringified_contexts(); -}; + static const String *get_stringified_contexts(); + }; -namespace detail { - using reporterCreatorFunc = IReporter* (*)(const ContextOptions&); + namespace detail { + using reporterCreatorFunc = IReporter *(*)(const ContextOptions &); - DOCTEST_INTERFACE void registerReporterImpl(const char* name, int prio, reporterCreatorFunc c, bool isReporter); + DOCTEST_INTERFACE void registerReporterImpl(const char *name, int prio, reporterCreatorFunc c, + bool isReporter); - template - IReporter* reporterCreator(const ContextOptions& o) { - return new Reporter(o); + template IReporter *reporterCreator(const ContextOptions &o) + { + return new Reporter(o); } -} // namespace detail + } // namespace detail -template -int registerReporter(const char* name, int priority, bool isReporter) { + template int registerReporter(const char *name, int priority, bool isReporter) + { detail::registerReporterImpl(name, priority, detail::reporterCreator, isReporter); return 0; -} + } } // namespace doctest #ifdef DOCTEST_CONFIG_ASSERTS_RETURN_VALUES @@ -2123,221 +2206,226 @@ int registerReporter(const char* name, int priority, bool isReporter) { #ifndef DOCTEST_CONFIG_DISABLE #ifdef DOCTEST_CONFIG_ASSERTS_RETURN_VALUES -#define DOCTEST_FUNC_SCOPE_BEGIN [&] -#define DOCTEST_FUNC_SCOPE_END () +#define DOCTEST_FUNC_SCOPE_BEGIN [&] +#define DOCTEST_FUNC_SCOPE_END () #define DOCTEST_FUNC_SCOPE_RET(v) return v #else -#define DOCTEST_FUNC_SCOPE_BEGIN do -#define DOCTEST_FUNC_SCOPE_END while(false) +#define DOCTEST_FUNC_SCOPE_BEGIN do +#define DOCTEST_FUNC_SCOPE_END while (false) #define DOCTEST_FUNC_SCOPE_RET(v) (void)0 #endif // common code in asserts - for convenience #define DOCTEST_ASSERT_LOG_REACT_RETURN(b) \ - if(b.log()) DOCTEST_BREAK_INTO_DEBUGGER(); \ - b.react(); \ - DOCTEST_FUNC_SCOPE_RET(!b.m_failed) + if (b.log()) \ + DOCTEST_BREAK_INTO_DEBUGGER(); \ + b.react(); \ + DOCTEST_FUNC_SCOPE_RET(!b.m_failed) #ifdef DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS #define DOCTEST_WRAP_IN_TRY(x) x; #else // DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS #define DOCTEST_WRAP_IN_TRY(x) \ - try { \ - x; \ - } catch(...) { DOCTEST_RB.translateException(); } + try { \ + x; \ + } \ + catch (...) { \ + DOCTEST_RB.translateException(); \ + } #endif // DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS #ifdef DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS #define DOCTEST_CAST_TO_VOID(...) \ - DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wuseless-cast") \ - static_cast(__VA_ARGS__); \ - DOCTEST_GCC_SUPPRESS_WARNING_POP + DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wuseless-cast") \ + static_cast(__VA_ARGS__); \ + DOCTEST_GCC_SUPPRESS_WARNING_POP #else // DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS #define DOCTEST_CAST_TO_VOID(...) __VA_ARGS__; #endif // DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS // registers the test by initializing a dummy var with a function #define DOCTEST_REGISTER_FUNCTION(global_prefix, f, decorators) \ - global_prefix DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), /* NOLINT */ \ - doctest::detail::regTest( \ - doctest::detail::TestCase( \ - f, __FILE__, __LINE__, \ - doctest_detail_test_suite_ns::getCurrentTestSuite()) * \ - decorators)) + global_prefix DOCTEST_GLOBAL_NO_WARNINGS( \ + DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), /* NOLINT */ \ + doctest::detail::regTest( \ + doctest::detail::TestCase(f, __FILE__, __LINE__, \ + doctest_detail_test_suite_ns::getCurrentTestSuite()) * \ + decorators)) #define DOCTEST_IMPLEMENT_FIXTURE(der, base, func, decorators) \ - namespace { /* NOLINT */ \ - struct der : public base \ - { \ - void f(); \ - }; \ - static DOCTEST_INLINE_NOINLINE void func() { \ - der v; \ - v.f(); \ - } \ - DOCTEST_REGISTER_FUNCTION(DOCTEST_EMPTY, func, decorators) \ + namespace { /* NOLINT */ \ + struct der : public base \ + { \ + void f(); \ + }; \ + static DOCTEST_INLINE_NOINLINE void func() \ + { \ + der v; \ + v.f(); \ } \ - DOCTEST_INLINE_NOINLINE void der::f() // NOLINT(misc-definitions-in-headers) + DOCTEST_REGISTER_FUNCTION(DOCTEST_EMPTY, func, decorators) \ + } \ + DOCTEST_INLINE_NOINLINE void der::f() // NOLINT(misc-definitions-in-headers) #define DOCTEST_CREATE_AND_REGISTER_FUNCTION(f, decorators) \ - static void f(); \ - DOCTEST_REGISTER_FUNCTION(DOCTEST_EMPTY, f, decorators) \ - static void f() + static void f(); \ + DOCTEST_REGISTER_FUNCTION(DOCTEST_EMPTY, f, decorators) \ + static void f() #define DOCTEST_CREATE_AND_REGISTER_FUNCTION_IN_CLASS(f, proxy, decorators) \ - static doctest::detail::funcType proxy() { return f; } \ - DOCTEST_REGISTER_FUNCTION(inline, proxy(), decorators) \ - static void f() + static doctest::detail::funcType proxy() { return f; } \ + DOCTEST_REGISTER_FUNCTION(inline, proxy(), decorators) \ + static void f() // for registering tests #define DOCTEST_TEST_CASE(decorators) \ - DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), decorators) + DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), decorators) // for registering tests in classes - requires C++17 for inline variables! #if DOCTEST_CPLUSPLUS >= 201703L #define DOCTEST_TEST_CASE_CLASS(decorators) \ - DOCTEST_CREATE_AND_REGISTER_FUNCTION_IN_CLASS(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), \ - DOCTEST_ANONYMOUS(DOCTEST_ANON_PROXY_), \ - decorators) + DOCTEST_CREATE_AND_REGISTER_FUNCTION_IN_CLASS( \ + DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), DOCTEST_ANONYMOUS(DOCTEST_ANON_PROXY_), decorators) #else // DOCTEST_TEST_CASE_CLASS #define DOCTEST_TEST_CASE_CLASS(...) \ - TEST_CASES_CAN_BE_REGISTERED_IN_CLASSES_ONLY_IN_CPP17_MODE_OR_WITH_VS_2017_OR_NEWER + TEST_CASES_CAN_BE_REGISTERED_IN_CLASSES_ONLY_IN_CPP17_MODE_OR_WITH_VS_2017_OR_NEWER #endif // DOCTEST_TEST_CASE_CLASS // for registering tests with a fixture #define DOCTEST_TEST_CASE_FIXTURE(c, decorators) \ - DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(DOCTEST_ANON_CLASS_), c, \ - DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), decorators) + DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(DOCTEST_ANON_CLASS_), c, \ + DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), decorators) // for converting types to strings without the header and demangling #define DOCTEST_TYPE_TO_STRING_AS(str, ...) \ - namespace doctest { \ - template <> \ - inline String toString<__VA_ARGS__>() { \ - return str; \ - } \ - } \ - static_assert(true, "") + namespace doctest { \ + template <> inline String toString<__VA_ARGS__>() { return str; } \ + } \ + static_assert(true, "") #define DOCTEST_TYPE_TO_STRING(...) DOCTEST_TYPE_TO_STRING_AS(#__VA_ARGS__, __VA_ARGS__) #define DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, iter, func) \ - template \ - static void func(); \ - namespace { /* NOLINT */ \ - template \ - struct iter; \ - template \ - struct iter> \ - { \ - iter(const char* file, unsigned line, int index) { \ - doctest::detail::regTest(doctest::detail::TestCase(func, file, line, \ - doctest_detail_test_suite_ns::getCurrentTestSuite(), \ - doctest::toString(), \ - int(line) * 1000 + index) \ - * dec); \ - iter>(file, line, index + 1); \ - } \ - }; \ - template <> \ - struct iter> \ - { \ - iter(const char*, unsigned, int) {} \ - }; \ - } \ - template \ - static void func() + template static void func(); \ + namespace { /* NOLINT */ \ + template struct iter; \ + template struct iter> \ + { \ + iter(const char *file, unsigned line, int index) \ + { \ + doctest::detail::regTest( \ + doctest::detail::TestCase(func, file, line, \ + doctest_detail_test_suite_ns::getCurrentTestSuite(), \ + doctest::toString(), int(line) * 1000 + index) * \ + dec); \ + iter>(file, line, index + 1); \ + } \ + }; \ + template <> struct iter> \ + { \ + iter(const char *, unsigned, int) {} \ + }; \ + } \ + template static void func() #define DOCTEST_TEST_CASE_TEMPLATE_DEFINE(dec, T, id) \ - DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, DOCTEST_CAT(id, ITERATOR), \ - DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_)) + DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, DOCTEST_CAT(id, ITERATOR), \ + DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_)) #define DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, anon, ...) \ - DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_CAT(anon, DUMMY), /* NOLINT(cert-err58-cpp, fuchsia-statically-constructed-objects) */ \ - doctest::detail::instantiationHelper( \ - DOCTEST_CAT(id, ITERATOR)<__VA_ARGS__>(__FILE__, __LINE__, 0))) + DOCTEST_GLOBAL_NO_WARNINGS( \ + DOCTEST_CAT(anon, \ + DUMMY), /* NOLINT(cert-err58-cpp, fuchsia-statically-constructed-objects) */ \ + doctest::detail::instantiationHelper(DOCTEST_CAT(id, ITERATOR) < __VA_ARGS__ > \ + (__FILE__, __LINE__, 0))) #define DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, ...) \ - DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), std::tuple<__VA_ARGS__>) \ - static_assert(true, "") + DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), \ + std::tuple<__VA_ARGS__>) \ + static_assert(true, "") #define DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, ...) \ - DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), __VA_ARGS__) \ - static_assert(true, "") + DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), \ + __VA_ARGS__) \ + static_assert(true, "") #define DOCTEST_TEST_CASE_TEMPLATE_IMPL(dec, T, anon, ...) \ - DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, DOCTEST_CAT(anon, ITERATOR), anon); \ - DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(anon, anon, std::tuple<__VA_ARGS__>) \ - template \ - static void anon() + DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, DOCTEST_CAT(anon, ITERATOR), anon); \ + DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(anon, anon, std::tuple<__VA_ARGS__>) \ + template static void anon() #define DOCTEST_TEST_CASE_TEMPLATE(dec, T, ...) \ - DOCTEST_TEST_CASE_TEMPLATE_IMPL(dec, T, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), __VA_ARGS__) + DOCTEST_TEST_CASE_TEMPLATE_IMPL(dec, T, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), __VA_ARGS__) // for subcases #define DOCTEST_SUBCASE(name) \ - if(const doctest::detail::Subcase & DOCTEST_ANONYMOUS(DOCTEST_ANON_SUBCASE_) DOCTEST_UNUSED = \ - doctest::detail::Subcase(name, __FILE__, __LINE__)) + if (const doctest::detail::Subcase & DOCTEST_ANONYMOUS(DOCTEST_ANON_SUBCASE_) DOCTEST_UNUSED = \ + doctest::detail::Subcase(name, __FILE__, __LINE__)) // for grouping tests in test suites by using code blocks #define DOCTEST_TEST_SUITE_IMPL(decorators, ns_name) \ - namespace ns_name { namespace doctest_detail_test_suite_ns { \ - static DOCTEST_NOINLINE doctest::detail::TestSuite& getCurrentTestSuite() noexcept { \ - DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4640) \ - DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wexit-time-destructors") \ - DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wmissing-field-initializers") \ - static doctest::detail::TestSuite data{}; \ - static bool inited = false; \ - DOCTEST_MSVC_SUPPRESS_WARNING_POP \ - DOCTEST_CLANG_SUPPRESS_WARNING_POP \ - DOCTEST_GCC_SUPPRESS_WARNING_POP \ - if(!inited) { \ - data* decorators; \ - inited = true; \ - } \ - return data; \ - } \ + namespace ns_name { \ + namespace doctest_detail_test_suite_ns { \ + static DOCTEST_NOINLINE doctest::detail::TestSuite &getCurrentTestSuite() noexcept \ + { \ + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4640) \ + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wexit-time-destructors") \ + DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wmissing-field-initializers") \ + static doctest::detail::TestSuite data{}; \ + static bool inited = false; \ + DOCTEST_MSVC_SUPPRESS_WARNING_POP \ + DOCTEST_CLANG_SUPPRESS_WARNING_POP \ + DOCTEST_GCC_SUPPRESS_WARNING_POP \ + if (!inited) { \ + data *decorators; \ + inited = true; \ } \ + return data; \ + } \ } \ - namespace ns_name + } \ + namespace ns_name #define DOCTEST_TEST_SUITE(decorators) \ - DOCTEST_TEST_SUITE_IMPL(decorators, DOCTEST_ANONYMOUS(DOCTEST_ANON_SUITE_)) + DOCTEST_TEST_SUITE_IMPL(decorators, DOCTEST_ANONYMOUS(DOCTEST_ANON_SUITE_)) // for starting a testsuite block #define DOCTEST_TEST_SUITE_BEGIN(decorators) \ - DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), /* NOLINT(cert-err58-cpp) */ \ - doctest::detail::setTestSuite(doctest::detail::TestSuite() * decorators)) \ - static_assert(true, "") + DOCTEST_GLOBAL_NO_WARNINGS( \ + DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), /* NOLINT(cert-err58-cpp) */ \ + doctest::detail::setTestSuite(doctest::detail::TestSuite() * decorators)) \ + static_assert(true, "") // for ending a testsuite block #define DOCTEST_TEST_SUITE_END \ - DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), /* NOLINT(cert-err58-cpp) */ \ - doctest::detail::setTestSuite(doctest::detail::TestSuite() * "")) \ - using DOCTEST_ANONYMOUS(DOCTEST_ANON_FOR_SEMICOLON_) = int + DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), /* NOLINT(cert-err58-cpp) */ \ + doctest::detail::setTestSuite(doctest::detail::TestSuite() * "")) \ + using DOCTEST_ANONYMOUS(DOCTEST_ANON_FOR_SEMICOLON_) = int // for registering exception translators #define DOCTEST_REGISTER_EXCEPTION_TRANSLATOR_IMPL(translatorName, signature) \ - inline doctest::String translatorName(signature); \ - DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_), /* NOLINT(cert-err58-cpp) */ \ - doctest::registerExceptionTranslator(translatorName)) \ - doctest::String translatorName(signature) + inline doctest::String translatorName(signature); \ + DOCTEST_GLOBAL_NO_WARNINGS( \ + DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_), /* NOLINT(cert-err58-cpp) */ \ + doctest::registerExceptionTranslator(translatorName)) \ + doctest::String translatorName(signature) #define DOCTEST_REGISTER_EXCEPTION_TRANSLATOR(signature) \ - DOCTEST_REGISTER_EXCEPTION_TRANSLATOR_IMPL(DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_), \ - signature) + DOCTEST_REGISTER_EXCEPTION_TRANSLATOR_IMPL(DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_), signature) // for registering reporters #define DOCTEST_REGISTER_REPORTER(name, priority, reporter) \ - DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_REPORTER_), /* NOLINT(cert-err58-cpp) */ \ - doctest::registerReporter(name, priority, true)) \ - static_assert(true, "") + DOCTEST_GLOBAL_NO_WARNINGS( \ + DOCTEST_ANONYMOUS(DOCTEST_ANON_REPORTER_), /* NOLINT(cert-err58-cpp) */ \ + doctest::registerReporter(name, priority, true)) \ + static_assert(true, "") // for registering listeners #define DOCTEST_REGISTER_LISTENER(name, priority, reporter) \ - DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_REPORTER_), /* NOLINT(cert-err58-cpp) */ \ - doctest::registerReporter(name, priority, false)) \ - static_assert(true, "") + DOCTEST_GLOBAL_NO_WARNINGS( \ + DOCTEST_ANONYMOUS(DOCTEST_ANON_REPORTER_), /* NOLINT(cert-err58-cpp) */ \ + doctest::registerReporter(name, priority, false)) \ + static_assert(true, "") // clang-format off // for logging - disabling formatting because it's important to have these on 2 separate lines - see PR #557 @@ -2347,24 +2435,26 @@ int registerReporter(const char* name, int priority, bool isReporter) { __VA_ARGS__) // clang-format on -#define DOCTEST_INFO_IMPL(mb_name, s_name, ...) \ - auto DOCTEST_ANONYMOUS(DOCTEST_CAPTURE_) = doctest::detail::MakeContextScope( \ - [&](std::ostream* s_name) { \ +#define DOCTEST_INFO_IMPL(mb_name, s_name, ...) \ + auto DOCTEST_ANONYMOUS(DOCTEST_CAPTURE_) = \ + doctest::detail::MakeContextScope([&](std::ostream *s_name) { \ doctest::detail::MessageBuilder mb_name(__FILE__, __LINE__, doctest::assertType::is_warn); \ mb_name.m_stream = s_name; \ - mb_name * __VA_ARGS__; \ - }) + mb_name *__VA_ARGS__; \ + }) #define DOCTEST_CAPTURE(x) DOCTEST_INFO(#x " := ", x) #define DOCTEST_ADD_AT_IMPL(type, file, line, mb, ...) \ - DOCTEST_FUNC_SCOPE_BEGIN { \ - doctest::detail::MessageBuilder mb(file, line, doctest::assertType::type); \ - mb * __VA_ARGS__; \ - if(mb.log()) \ - DOCTEST_BREAK_INTO_DEBUGGER(); \ - mb.react(); \ - } DOCTEST_FUNC_SCOPE_END + DOCTEST_FUNC_SCOPE_BEGIN \ + { \ + doctest::detail::MessageBuilder mb(file, line, doctest::assertType::type); \ + mb *__VA_ARGS__; \ + if (mb.log()) \ + DOCTEST_BREAK_INTO_DEBUGGER(); \ + mb.react(); \ + } \ + DOCTEST_FUNC_SCOPE_END // clang-format off #define DOCTEST_ADD_MESSAGE_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_warn, file, line, DOCTEST_ANONYMOUS(DOCTEST_MESSAGE_), __VA_ARGS__) @@ -2372,47 +2462,49 @@ int registerReporter(const char* name, int priority, bool isReporter) { #define DOCTEST_ADD_FAIL_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_require, file, line, DOCTEST_ANONYMOUS(DOCTEST_MESSAGE_), __VA_ARGS__) // clang-format on -#define DOCTEST_MESSAGE(...) DOCTEST_ADD_MESSAGE_AT(__FILE__, __LINE__, __VA_ARGS__) +#define DOCTEST_MESSAGE(...) DOCTEST_ADD_MESSAGE_AT(__FILE__, __LINE__, __VA_ARGS__) #define DOCTEST_FAIL_CHECK(...) DOCTEST_ADD_FAIL_CHECK_AT(__FILE__, __LINE__, __VA_ARGS__) -#define DOCTEST_FAIL(...) DOCTEST_ADD_FAIL_AT(__FILE__, __LINE__, __VA_ARGS__) +#define DOCTEST_FAIL(...) DOCTEST_ADD_FAIL_AT(__FILE__, __LINE__, __VA_ARGS__) #define DOCTEST_TO_LVALUE(...) __VA_ARGS__ // Not removed to keep backwards compatibility. #ifndef DOCTEST_CONFIG_SUPER_FAST_ASSERTS #define DOCTEST_ASSERT_IMPLEMENT_2(assert_type, ...) \ - DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Woverloaded-shift-op-parentheses") \ - /* NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) */ \ - doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ - __LINE__, #__VA_ARGS__); \ - DOCTEST_WRAP_IN_TRY(DOCTEST_RB.setResult( \ - doctest::detail::ExpressionDecomposer(doctest::assertType::assert_type) \ - << __VA_ARGS__)) /* NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) */ \ - DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB) \ - DOCTEST_CLANG_SUPPRESS_WARNING_POP + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Woverloaded-shift-op-parentheses") \ + /* NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) */ \ + doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, __LINE__, \ + #__VA_ARGS__); \ + DOCTEST_WRAP_IN_TRY(DOCTEST_RB.setResult( \ + doctest::detail::ExpressionDecomposer(doctest::assertType::assert_type) \ + << __VA_ARGS__)) /* NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) */ \ + DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB) \ + DOCTEST_CLANG_SUPPRESS_WARNING_POP #define DOCTEST_ASSERT_IMPLEMENT_1(assert_type, ...) \ - DOCTEST_FUNC_SCOPE_BEGIN { \ - DOCTEST_ASSERT_IMPLEMENT_2(assert_type, __VA_ARGS__); \ - } DOCTEST_FUNC_SCOPE_END // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks) + DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_ASSERT_IMPLEMENT_2(assert_type, __VA_ARGS__); } \ + DOCTEST_FUNC_SCOPE_END // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks) #define DOCTEST_BINARY_ASSERT(assert_type, comp, ...) \ - DOCTEST_FUNC_SCOPE_BEGIN { \ - doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ - __LINE__, #__VA_ARGS__); \ - DOCTEST_WRAP_IN_TRY( \ - DOCTEST_RB.binary_assert( \ - __VA_ARGS__)) \ - DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ - } DOCTEST_FUNC_SCOPE_END + DOCTEST_FUNC_SCOPE_BEGIN \ + { \ + doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ + __LINE__, #__VA_ARGS__); \ + DOCTEST_WRAP_IN_TRY( \ + DOCTEST_RB.binary_assert(__VA_ARGS__)) \ + DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ + } \ + DOCTEST_FUNC_SCOPE_END #define DOCTEST_UNARY_ASSERT(assert_type, ...) \ - DOCTEST_FUNC_SCOPE_BEGIN { \ - doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ - __LINE__, #__VA_ARGS__); \ - DOCTEST_WRAP_IN_TRY(DOCTEST_RB.unary_assert(__VA_ARGS__)) \ - DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ - } DOCTEST_FUNC_SCOPE_END + DOCTEST_FUNC_SCOPE_BEGIN \ + { \ + doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ + __LINE__, #__VA_ARGS__); \ + DOCTEST_WRAP_IN_TRY(DOCTEST_RB.unary_assert(__VA_ARGS__)) \ + DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ + } \ + DOCTEST_FUNC_SCOPE_END #else // DOCTEST_CONFIG_SUPER_FAST_ASSERTS @@ -2420,27 +2512,27 @@ int registerReporter(const char* name, int priority, bool isReporter) { #define DOCTEST_ASSERT_IMPLEMENT_2 DOCTEST_ASSERT_IMPLEMENT_1 #define DOCTEST_ASSERT_IMPLEMENT_1(assert_type, ...) \ - DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Woverloaded-shift-op-parentheses") \ - doctest::detail::decomp_assert( \ - doctest::assertType::assert_type, __FILE__, __LINE__, #__VA_ARGS__, \ - doctest::detail::ExpressionDecomposer(doctest::assertType::assert_type) \ - << __VA_ARGS__) DOCTEST_CLANG_SUPPRESS_WARNING_POP + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Woverloaded-shift-op-parentheses") \ + doctest::detail::decomp_assert( \ + doctest::assertType::assert_type, __FILE__, __LINE__, #__VA_ARGS__, \ + doctest::detail::ExpressionDecomposer(doctest::assertType::assert_type) << __VA_ARGS__) \ + DOCTEST_CLANG_SUPPRESS_WARNING_POP #define DOCTEST_BINARY_ASSERT(assert_type, comparison, ...) \ - doctest::detail::binary_assert( \ - doctest::assertType::assert_type, __FILE__, __LINE__, #__VA_ARGS__, __VA_ARGS__) + doctest::detail::binary_assert( \ + doctest::assertType::assert_type, __FILE__, __LINE__, #__VA_ARGS__, __VA_ARGS__) #define DOCTEST_UNARY_ASSERT(assert_type, ...) \ - doctest::detail::unary_assert(doctest::assertType::assert_type, __FILE__, __LINE__, \ - #__VA_ARGS__, __VA_ARGS__) + doctest::detail::unary_assert(doctest::assertType::assert_type, __FILE__, __LINE__, \ + #__VA_ARGS__, __VA_ARGS__) #endif // DOCTEST_CONFIG_SUPER_FAST_ASSERTS -#define DOCTEST_WARN(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_WARN, __VA_ARGS__) -#define DOCTEST_CHECK(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_CHECK, __VA_ARGS__) -#define DOCTEST_REQUIRE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_REQUIRE, __VA_ARGS__) -#define DOCTEST_WARN_FALSE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_WARN_FALSE, __VA_ARGS__) -#define DOCTEST_CHECK_FALSE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_CHECK_FALSE, __VA_ARGS__) +#define DOCTEST_WARN(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_WARN, __VA_ARGS__) +#define DOCTEST_CHECK(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_CHECK, __VA_ARGS__) +#define DOCTEST_REQUIRE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_REQUIRE, __VA_ARGS__) +#define DOCTEST_WARN_FALSE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_WARN_FALSE, __VA_ARGS__) +#define DOCTEST_CHECK_FALSE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_CHECK_FALSE, __VA_ARGS__) #define DOCTEST_REQUIRE_FALSE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_REQUIRE_FALSE, __VA_ARGS__) // clang-format off @@ -2452,75 +2544,93 @@ int registerReporter(const char* name, int priority, bool isReporter) { #define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_REQUIRE_FALSE, cond); } DOCTEST_FUNC_SCOPE_END // clang-format on -#define DOCTEST_WARN_EQ(...) DOCTEST_BINARY_ASSERT(DT_WARN_EQ, eq, __VA_ARGS__) -#define DOCTEST_CHECK_EQ(...) DOCTEST_BINARY_ASSERT(DT_CHECK_EQ, eq, __VA_ARGS__) +#define DOCTEST_WARN_EQ(...) DOCTEST_BINARY_ASSERT(DT_WARN_EQ, eq, __VA_ARGS__) +#define DOCTEST_CHECK_EQ(...) DOCTEST_BINARY_ASSERT(DT_CHECK_EQ, eq, __VA_ARGS__) #define DOCTEST_REQUIRE_EQ(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_EQ, eq, __VA_ARGS__) -#define DOCTEST_WARN_NE(...) DOCTEST_BINARY_ASSERT(DT_WARN_NE, ne, __VA_ARGS__) -#define DOCTEST_CHECK_NE(...) DOCTEST_BINARY_ASSERT(DT_CHECK_NE, ne, __VA_ARGS__) +#define DOCTEST_WARN_NE(...) DOCTEST_BINARY_ASSERT(DT_WARN_NE, ne, __VA_ARGS__) +#define DOCTEST_CHECK_NE(...) DOCTEST_BINARY_ASSERT(DT_CHECK_NE, ne, __VA_ARGS__) #define DOCTEST_REQUIRE_NE(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_NE, ne, __VA_ARGS__) -#define DOCTEST_WARN_GT(...) DOCTEST_BINARY_ASSERT(DT_WARN_GT, gt, __VA_ARGS__) -#define DOCTEST_CHECK_GT(...) DOCTEST_BINARY_ASSERT(DT_CHECK_GT, gt, __VA_ARGS__) +#define DOCTEST_WARN_GT(...) DOCTEST_BINARY_ASSERT(DT_WARN_GT, gt, __VA_ARGS__) +#define DOCTEST_CHECK_GT(...) DOCTEST_BINARY_ASSERT(DT_CHECK_GT, gt, __VA_ARGS__) #define DOCTEST_REQUIRE_GT(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_GT, gt, __VA_ARGS__) -#define DOCTEST_WARN_LT(...) DOCTEST_BINARY_ASSERT(DT_WARN_LT, lt, __VA_ARGS__) -#define DOCTEST_CHECK_LT(...) DOCTEST_BINARY_ASSERT(DT_CHECK_LT, lt, __VA_ARGS__) +#define DOCTEST_WARN_LT(...) DOCTEST_BINARY_ASSERT(DT_WARN_LT, lt, __VA_ARGS__) +#define DOCTEST_CHECK_LT(...) DOCTEST_BINARY_ASSERT(DT_CHECK_LT, lt, __VA_ARGS__) #define DOCTEST_REQUIRE_LT(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_LT, lt, __VA_ARGS__) -#define DOCTEST_WARN_GE(...) DOCTEST_BINARY_ASSERT(DT_WARN_GE, ge, __VA_ARGS__) -#define DOCTEST_CHECK_GE(...) DOCTEST_BINARY_ASSERT(DT_CHECK_GE, ge, __VA_ARGS__) +#define DOCTEST_WARN_GE(...) DOCTEST_BINARY_ASSERT(DT_WARN_GE, ge, __VA_ARGS__) +#define DOCTEST_CHECK_GE(...) DOCTEST_BINARY_ASSERT(DT_CHECK_GE, ge, __VA_ARGS__) #define DOCTEST_REQUIRE_GE(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_GE, ge, __VA_ARGS__) -#define DOCTEST_WARN_LE(...) DOCTEST_BINARY_ASSERT(DT_WARN_LE, le, __VA_ARGS__) -#define DOCTEST_CHECK_LE(...) DOCTEST_BINARY_ASSERT(DT_CHECK_LE, le, __VA_ARGS__) +#define DOCTEST_WARN_LE(...) DOCTEST_BINARY_ASSERT(DT_WARN_LE, le, __VA_ARGS__) +#define DOCTEST_CHECK_LE(...) DOCTEST_BINARY_ASSERT(DT_CHECK_LE, le, __VA_ARGS__) #define DOCTEST_REQUIRE_LE(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_LE, le, __VA_ARGS__) -#define DOCTEST_WARN_UNARY(...) DOCTEST_UNARY_ASSERT(DT_WARN_UNARY, __VA_ARGS__) -#define DOCTEST_CHECK_UNARY(...) DOCTEST_UNARY_ASSERT(DT_CHECK_UNARY, __VA_ARGS__) -#define DOCTEST_REQUIRE_UNARY(...) DOCTEST_UNARY_ASSERT(DT_REQUIRE_UNARY, __VA_ARGS__) -#define DOCTEST_WARN_UNARY_FALSE(...) DOCTEST_UNARY_ASSERT(DT_WARN_UNARY_FALSE, __VA_ARGS__) -#define DOCTEST_CHECK_UNARY_FALSE(...) DOCTEST_UNARY_ASSERT(DT_CHECK_UNARY_FALSE, __VA_ARGS__) +#define DOCTEST_WARN_UNARY(...) DOCTEST_UNARY_ASSERT(DT_WARN_UNARY, __VA_ARGS__) +#define DOCTEST_CHECK_UNARY(...) DOCTEST_UNARY_ASSERT(DT_CHECK_UNARY, __VA_ARGS__) +#define DOCTEST_REQUIRE_UNARY(...) DOCTEST_UNARY_ASSERT(DT_REQUIRE_UNARY, __VA_ARGS__) +#define DOCTEST_WARN_UNARY_FALSE(...) DOCTEST_UNARY_ASSERT(DT_WARN_UNARY_FALSE, __VA_ARGS__) +#define DOCTEST_CHECK_UNARY_FALSE(...) DOCTEST_UNARY_ASSERT(DT_CHECK_UNARY_FALSE, __VA_ARGS__) #define DOCTEST_REQUIRE_UNARY_FALSE(...) DOCTEST_UNARY_ASSERT(DT_REQUIRE_UNARY_FALSE, __VA_ARGS__) #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS #define DOCTEST_ASSERT_THROWS_AS(expr, assert_type, message, ...) \ - DOCTEST_FUNC_SCOPE_BEGIN { \ - if(!doctest::getContextOptions()->no_throw) { \ - doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ - __LINE__, #expr, #__VA_ARGS__, message); \ - try { \ - DOCTEST_CAST_TO_VOID(expr) \ - } catch(const typename doctest::detail::types::remove_const< \ - typename doctest::detail::types::remove_reference<__VA_ARGS__>::type>::type&) {\ - DOCTEST_RB.translateException(); \ - DOCTEST_RB.m_threw_as = true; \ - } catch(...) { DOCTEST_RB.translateException(); } \ - DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ - } else { /* NOLINT(*-else-after-return) */ \ - DOCTEST_FUNC_SCOPE_RET(false); \ - } \ - } DOCTEST_FUNC_SCOPE_END + DOCTEST_FUNC_SCOPE_BEGIN \ + { \ + if (!doctest::getContextOptions()->no_throw) { \ + doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ + __LINE__, #expr, #__VA_ARGS__, message); \ + try { \ + DOCTEST_CAST_TO_VOID(expr) \ + } \ + catch (const typename doctest::detail::types::remove_const< \ + typename doctest::detail::types::remove_reference<__VA_ARGS__>::type>::type &) { \ + DOCTEST_RB.translateException(); \ + DOCTEST_RB.m_threw_as = true; \ + } \ + catch (...) { \ + DOCTEST_RB.translateException(); \ + } \ + DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ + } \ + else { /* NOLINT(*-else-after-return) */ \ + DOCTEST_FUNC_SCOPE_RET(false); \ + } \ + } \ + DOCTEST_FUNC_SCOPE_END #define DOCTEST_ASSERT_THROWS_WITH(expr, expr_str, assert_type, ...) \ - DOCTEST_FUNC_SCOPE_BEGIN { \ - if(!doctest::getContextOptions()->no_throw) { \ - doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ - __LINE__, expr_str, "", __VA_ARGS__); \ - try { \ - DOCTEST_CAST_TO_VOID(expr) \ - } catch(...) { DOCTEST_RB.translateException(); } \ - DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ - } else { /* NOLINT(*-else-after-return) */ \ - DOCTEST_FUNC_SCOPE_RET(false); \ - } \ - } DOCTEST_FUNC_SCOPE_END + DOCTEST_FUNC_SCOPE_BEGIN \ + { \ + if (!doctest::getContextOptions()->no_throw) { \ + doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ + __LINE__, expr_str, "", __VA_ARGS__); \ + try { \ + DOCTEST_CAST_TO_VOID(expr) \ + } \ + catch (...) { \ + DOCTEST_RB.translateException(); \ + } \ + DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ + } \ + else { /* NOLINT(*-else-after-return) */ \ + DOCTEST_FUNC_SCOPE_RET(false); \ + } \ + } \ + DOCTEST_FUNC_SCOPE_END #define DOCTEST_ASSERT_NOTHROW(assert_type, ...) \ - DOCTEST_FUNC_SCOPE_BEGIN { \ - doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ - __LINE__, #__VA_ARGS__); \ - try { \ - DOCTEST_CAST_TO_VOID(__VA_ARGS__) \ - } catch(...) { DOCTEST_RB.translateException(); } \ - DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ - } DOCTEST_FUNC_SCOPE_END + DOCTEST_FUNC_SCOPE_BEGIN \ + { \ + doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ + __LINE__, #__VA_ARGS__); \ + try { \ + DOCTEST_CAST_TO_VOID(__VA_ARGS__) \ + } \ + catch (...) { \ + DOCTEST_RB.translateException(); \ + } \ + DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ + } \ + DOCTEST_FUNC_SCOPE_END // clang-format off #define DOCTEST_WARN_THROWS(...) DOCTEST_ASSERT_THROWS_WITH((__VA_ARGS__), #__VA_ARGS__, DT_WARN_THROWS, "") @@ -2569,97 +2679,98 @@ int registerReporter(const char* name, int priority, bool isReporter) { #else // DOCTEST_CONFIG_DISABLE #define DOCTEST_IMPLEMENT_FIXTURE(der, base, func, name) \ - namespace /* NOLINT */ { \ - template \ - struct der : public base \ - { void f(); }; \ - } \ - template \ - inline void der::f() + namespace /* NOLINT */ { \ + template struct der : public base \ + { \ + void f(); \ + }; \ + } \ + template \ + inline void der::f() #define DOCTEST_CREATE_AND_REGISTER_FUNCTION(f, name) \ - template \ - static inline void f() + template static inline void f() // for registering tests #define DOCTEST_TEST_CASE(name) \ - DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), name) + DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), name) // for registering tests in classes #define DOCTEST_TEST_CASE_CLASS(name) \ - DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), name) + DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), name) // for registering tests with a fixture #define DOCTEST_TEST_CASE_FIXTURE(x, name) \ - DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(DOCTEST_ANON_CLASS_), x, \ - DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), name) + DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(DOCTEST_ANON_CLASS_), x, \ + DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), name) // for converting types to strings without the header and demangling #define DOCTEST_TYPE_TO_STRING_AS(str, ...) static_assert(true, "") -#define DOCTEST_TYPE_TO_STRING(...) static_assert(true, "") +#define DOCTEST_TYPE_TO_STRING(...) static_assert(true, "") // for typed tests #define DOCTEST_TEST_CASE_TEMPLATE(name, type, ...) \ - template \ - inline void DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_)() + template inline void DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_)() #define DOCTEST_TEST_CASE_TEMPLATE_DEFINE(name, type, id) \ - template \ - inline void DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_)() + template inline void DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_)() #define DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, ...) static_assert(true, "") -#define DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, ...) static_assert(true, "") +#define DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, ...) static_assert(true, "") // for subcases #define DOCTEST_SUBCASE(name) // for a testsuite block -#define DOCTEST_TEST_SUITE(name) namespace // NOLINT +#define DOCTEST_TEST_SUITE(name) namespace // NOLINT // for starting a testsuite block #define DOCTEST_TEST_SUITE_BEGIN(name) static_assert(true, "") // for ending a testsuite block -#define DOCTEST_TEST_SUITE_END using DOCTEST_ANONYMOUS(DOCTEST_ANON_FOR_SEMICOLON_) = int +#define DOCTEST_TEST_SUITE_END using DOCTEST_ANONYMOUS(DOCTEST_ANON_FOR_SEMICOLON_) = int #define DOCTEST_REGISTER_EXCEPTION_TRANSLATOR(signature) \ - template \ - static inline doctest::String DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_)(signature) + template \ + static inline doctest::String DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_)(signature) #define DOCTEST_REGISTER_REPORTER(name, priority, reporter) #define DOCTEST_REGISTER_LISTENER(name, priority, reporter) -#define DOCTEST_INFO(...) (static_cast(0)) -#define DOCTEST_CAPTURE(x) (static_cast(0)) -#define DOCTEST_ADD_MESSAGE_AT(file, line, ...) (static_cast(0)) +#define DOCTEST_INFO(...) (static_cast(0)) +#define DOCTEST_CAPTURE(x) (static_cast(0)) +#define DOCTEST_ADD_MESSAGE_AT(file, line, ...) (static_cast(0)) #define DOCTEST_ADD_FAIL_CHECK_AT(file, line, ...) (static_cast(0)) -#define DOCTEST_ADD_FAIL_AT(file, line, ...) (static_cast(0)) -#define DOCTEST_MESSAGE(...) (static_cast(0)) -#define DOCTEST_FAIL_CHECK(...) (static_cast(0)) -#define DOCTEST_FAIL(...) (static_cast(0)) - -#if defined(DOCTEST_CONFIG_EVALUATE_ASSERTS_EVEN_WHEN_DISABLED) \ - && defined(DOCTEST_CONFIG_ASSERTS_RETURN_VALUES) - -#define DOCTEST_WARN(...) [&] { return __VA_ARGS__; }() -#define DOCTEST_CHECK(...) [&] { return __VA_ARGS__; }() -#define DOCTEST_REQUIRE(...) [&] { return __VA_ARGS__; }() -#define DOCTEST_WARN_FALSE(...) [&] { return !(__VA_ARGS__); }() -#define DOCTEST_CHECK_FALSE(...) [&] { return !(__VA_ARGS__); }() +#define DOCTEST_ADD_FAIL_AT(file, line, ...) (static_cast(0)) +#define DOCTEST_MESSAGE(...) (static_cast(0)) +#define DOCTEST_FAIL_CHECK(...) (static_cast(0)) +#define DOCTEST_FAIL(...) (static_cast(0)) + +#if defined(DOCTEST_CONFIG_EVALUATE_ASSERTS_EVEN_WHEN_DISABLED) && \ + defined(DOCTEST_CONFIG_ASSERTS_RETURN_VALUES) + +#define DOCTEST_WARN(...) [&] { return __VA_ARGS__; }() +#define DOCTEST_CHECK(...) [&] { return __VA_ARGS__; }() +#define DOCTEST_REQUIRE(...) [&] { return __VA_ARGS__; }() +#define DOCTEST_WARN_FALSE(...) [&] { return !(__VA_ARGS__); }() +#define DOCTEST_CHECK_FALSE(...) [&] { return !(__VA_ARGS__); }() #define DOCTEST_REQUIRE_FALSE(...) [&] { return !(__VA_ARGS__); }() -#define DOCTEST_WARN_MESSAGE(cond, ...) [&] { return cond; }() -#define DOCTEST_CHECK_MESSAGE(cond, ...) [&] { return cond; }() -#define DOCTEST_REQUIRE_MESSAGE(cond, ...) [&] { return cond; }() -#define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) [&] { return !(cond); }() -#define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) [&] { return !(cond); }() +#define DOCTEST_WARN_MESSAGE(cond, ...) [&] { return cond; }() +#define DOCTEST_CHECK_MESSAGE(cond, ...) [&] { return cond; }() +#define DOCTEST_REQUIRE_MESSAGE(cond, ...) [&] { return cond; }() +#define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) [&] { return !(cond); }() +#define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) [&] { return !(cond); }() #define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) [&] { return !(cond); }() namespace doctest { -namespace detail { + namespace detail { #define DOCTEST_RELATIONAL_OP(name, op) \ - template \ - bool name(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) { return lhs op rhs; } + template \ + bool name(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) \ + { \ + return lhs op rhs; \ + } DOCTEST_RELATIONAL_OP(eq, ==) DOCTEST_RELATIONAL_OP(ne, !=) @@ -2667,147 +2778,325 @@ namespace detail { DOCTEST_RELATIONAL_OP(gt, >) DOCTEST_RELATIONAL_OP(le, <=) DOCTEST_RELATIONAL_OP(ge, >=) -} // namespace detail + } // namespace detail } // namespace doctest -#define DOCTEST_WARN_EQ(...) [&] { return doctest::detail::eq(__VA_ARGS__); }() -#define DOCTEST_CHECK_EQ(...) [&] { return doctest::detail::eq(__VA_ARGS__); }() -#define DOCTEST_REQUIRE_EQ(...) [&] { return doctest::detail::eq(__VA_ARGS__); }() -#define DOCTEST_WARN_NE(...) [&] { return doctest::detail::ne(__VA_ARGS__); }() -#define DOCTEST_CHECK_NE(...) [&] { return doctest::detail::ne(__VA_ARGS__); }() -#define DOCTEST_REQUIRE_NE(...) [&] { return doctest::detail::ne(__VA_ARGS__); }() -#define DOCTEST_WARN_LT(...) [&] { return doctest::detail::lt(__VA_ARGS__); }() -#define DOCTEST_CHECK_LT(...) [&] { return doctest::detail::lt(__VA_ARGS__); }() -#define DOCTEST_REQUIRE_LT(...) [&] { return doctest::detail::lt(__VA_ARGS__); }() -#define DOCTEST_WARN_GT(...) [&] { return doctest::detail::gt(__VA_ARGS__); }() -#define DOCTEST_CHECK_GT(...) [&] { return doctest::detail::gt(__VA_ARGS__); }() -#define DOCTEST_REQUIRE_GT(...) [&] { return doctest::detail::gt(__VA_ARGS__); }() -#define DOCTEST_WARN_LE(...) [&] { return doctest::detail::le(__VA_ARGS__); }() -#define DOCTEST_CHECK_LE(...) [&] { return doctest::detail::le(__VA_ARGS__); }() -#define DOCTEST_REQUIRE_LE(...) [&] { return doctest::detail::le(__VA_ARGS__); }() -#define DOCTEST_WARN_GE(...) [&] { return doctest::detail::ge(__VA_ARGS__); }() -#define DOCTEST_CHECK_GE(...) [&] { return doctest::detail::ge(__VA_ARGS__); }() -#define DOCTEST_REQUIRE_GE(...) [&] { return doctest::detail::ge(__VA_ARGS__); }() -#define DOCTEST_WARN_UNARY(...) [&] { return __VA_ARGS__; }() -#define DOCTEST_CHECK_UNARY(...) [&] { return __VA_ARGS__; }() -#define DOCTEST_REQUIRE_UNARY(...) [&] { return __VA_ARGS__; }() -#define DOCTEST_WARN_UNARY_FALSE(...) [&] { return !(__VA_ARGS__); }() -#define DOCTEST_CHECK_UNARY_FALSE(...) [&] { return !(__VA_ARGS__); }() +#define DOCTEST_WARN_EQ(...) [&] { return doctest::detail::eq(__VA_ARGS__); }() +#define DOCTEST_CHECK_EQ(...) [&] { return doctest::detail::eq(__VA_ARGS__); }() +#define DOCTEST_REQUIRE_EQ(...) [&] { return doctest::detail::eq(__VA_ARGS__); }() +#define DOCTEST_WARN_NE(...) [&] { return doctest::detail::ne(__VA_ARGS__); }() +#define DOCTEST_CHECK_NE(...) [&] { return doctest::detail::ne(__VA_ARGS__); }() +#define DOCTEST_REQUIRE_NE(...) [&] { return doctest::detail::ne(__VA_ARGS__); }() +#define DOCTEST_WARN_LT(...) [&] { return doctest::detail::lt(__VA_ARGS__); }() +#define DOCTEST_CHECK_LT(...) [&] { return doctest::detail::lt(__VA_ARGS__); }() +#define DOCTEST_REQUIRE_LT(...) [&] { return doctest::detail::lt(__VA_ARGS__); }() +#define DOCTEST_WARN_GT(...) [&] { return doctest::detail::gt(__VA_ARGS__); }() +#define DOCTEST_CHECK_GT(...) [&] { return doctest::detail::gt(__VA_ARGS__); }() +#define DOCTEST_REQUIRE_GT(...) [&] { return doctest::detail::gt(__VA_ARGS__); }() +#define DOCTEST_WARN_LE(...) [&] { return doctest::detail::le(__VA_ARGS__); }() +#define DOCTEST_CHECK_LE(...) [&] { return doctest::detail::le(__VA_ARGS__); }() +#define DOCTEST_REQUIRE_LE(...) [&] { return doctest::detail::le(__VA_ARGS__); }() +#define DOCTEST_WARN_GE(...) [&] { return doctest::detail::ge(__VA_ARGS__); }() +#define DOCTEST_CHECK_GE(...) [&] { return doctest::detail::ge(__VA_ARGS__); }() +#define DOCTEST_REQUIRE_GE(...) [&] { return doctest::detail::ge(__VA_ARGS__); }() +#define DOCTEST_WARN_UNARY(...) [&] { return __VA_ARGS__; }() +#define DOCTEST_CHECK_UNARY(...) [&] { return __VA_ARGS__; }() +#define DOCTEST_REQUIRE_UNARY(...) [&] { return __VA_ARGS__; }() +#define DOCTEST_WARN_UNARY_FALSE(...) [&] { return !(__VA_ARGS__); }() +#define DOCTEST_CHECK_UNARY_FALSE(...) [&] { return !(__VA_ARGS__); }() #define DOCTEST_REQUIRE_UNARY_FALSE(...) [&] { return !(__VA_ARGS__); }() #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS -#define DOCTEST_WARN_THROWS_WITH(expr, with, ...) [] { static_assert(false, "Exception translation is not available when doctest is disabled."); return false; }() -#define DOCTEST_CHECK_THROWS_WITH(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,) -#define DOCTEST_REQUIRE_THROWS_WITH(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,) -#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,) -#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,) -#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,) - -#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,) -#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,) -#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,) -#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,) -#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,) -#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,) - -#define DOCTEST_WARN_THROWS(...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }() -#define DOCTEST_CHECK_THROWS(...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }() -#define DOCTEST_REQUIRE_THROWS(...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }() -#define DOCTEST_WARN_THROWS_AS(expr, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }() -#define DOCTEST_CHECK_THROWS_AS(expr, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }() -#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }() -#define DOCTEST_WARN_NOTHROW(...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }() -#define DOCTEST_CHECK_NOTHROW(...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }() -#define DOCTEST_REQUIRE_NOTHROW(...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }() - -#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }() -#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }() -#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }() -#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }() -#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }() -#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }() -#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }() -#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }() -#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }() +#define DOCTEST_WARN_THROWS_WITH(expr, with, ...) \ + [] { \ + static_assert(false, "Exception translation is not available when doctest is disabled."); \ + return false; \ + }() +#define DOCTEST_CHECK_THROWS_WITH(expr, with, ...) DOCTEST_WARN_THROWS_WITH(, , ) +#define DOCTEST_REQUIRE_THROWS_WITH(expr, with, ...) DOCTEST_WARN_THROWS_WITH(, , ) +#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(, , ) +#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(, , ) +#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(, , ) + +#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH(, , ) +#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH(, , ) +#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH(, , ) +#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(, , ) +#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(, , ) +#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(, , ) + +#define DOCTEST_WARN_THROWS(...) \ + [&] { \ + try { \ + __VA_ARGS__; \ + return false; \ + } \ + catch (...) { \ + return true; \ + } \ + }() +#define DOCTEST_CHECK_THROWS(...) \ + [&] { \ + try { \ + __VA_ARGS__; \ + return false; \ + } \ + catch (...) { \ + return true; \ + } \ + }() +#define DOCTEST_REQUIRE_THROWS(...) \ + [&] { \ + try { \ + __VA_ARGS__; \ + return false; \ + } \ + catch (...) { \ + return true; \ + } \ + }() +#define DOCTEST_WARN_THROWS_AS(expr, ...) \ + [&] { \ + try { \ + expr; \ + } \ + catch (__VA_ARGS__) { \ + return true; \ + } \ + catch (...) { \ + } \ + return false; \ + }() +#define DOCTEST_CHECK_THROWS_AS(expr, ...) \ + [&] { \ + try { \ + expr; \ + } \ + catch (__VA_ARGS__) { \ + return true; \ + } \ + catch (...) { \ + } \ + return false; \ + }() +#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) \ + [&] { \ + try { \ + expr; \ + } \ + catch (__VA_ARGS__) { \ + return true; \ + } \ + catch (...) { \ + } \ + return false; \ + }() +#define DOCTEST_WARN_NOTHROW(...) \ + [&] { \ + try { \ + __VA_ARGS__; \ + return true; \ + } \ + catch (...) { \ + return false; \ + } \ + }() +#define DOCTEST_CHECK_NOTHROW(...) \ + [&] { \ + try { \ + __VA_ARGS__; \ + return true; \ + } \ + catch (...) { \ + return false; \ + } \ + }() +#define DOCTEST_REQUIRE_NOTHROW(...) \ + [&] { \ + try { \ + __VA_ARGS__; \ + return true; \ + } \ + catch (...) { \ + return false; \ + } \ + }() + +#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) \ + [&] { \ + try { \ + __VA_ARGS__; \ + return false; \ + } \ + catch (...) { \ + return true; \ + } \ + }() +#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) \ + [&] { \ + try { \ + __VA_ARGS__; \ + return false; \ + } \ + catch (...) { \ + return true; \ + } \ + }() +#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) \ + [&] { \ + try { \ + __VA_ARGS__; \ + return false; \ + } \ + catch (...) { \ + return true; \ + } \ + }() +#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) \ + [&] { \ + try { \ + expr; \ + } \ + catch (__VA_ARGS__) { \ + return true; \ + } \ + catch (...) { \ + } \ + return false; \ + }() +#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) \ + [&] { \ + try { \ + expr; \ + } \ + catch (__VA_ARGS__) { \ + return true; \ + } \ + catch (...) { \ + } \ + return false; \ + }() +#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) \ + [&] { \ + try { \ + expr; \ + } \ + catch (__VA_ARGS__) { \ + return true; \ + } \ + catch (...) { \ + } \ + return false; \ + }() +#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) \ + [&] { \ + try { \ + __VA_ARGS__; \ + return true; \ + } \ + catch (...) { \ + return false; \ + } \ + }() +#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) \ + [&] { \ + try { \ + __VA_ARGS__; \ + return true; \ + } \ + catch (...) { \ + return false; \ + } \ + }() +#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) \ + [&] { \ + try { \ + __VA_ARGS__; \ + return true; \ + } \ + catch (...) { \ + return false; \ + } \ + }() #endif // DOCTEST_CONFIG_NO_EXCEPTIONS #else // DOCTEST_CONFIG_EVALUATE_ASSERTS_EVEN_WHEN_DISABLED -#define DOCTEST_WARN(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_FALSE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_FALSE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_FALSE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_FALSE(...) DOCTEST_FUNC_EMPTY #define DOCTEST_REQUIRE_FALSE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY #define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_EQ(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_EQ(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_EQ(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_EQ(...) DOCTEST_FUNC_EMPTY #define DOCTEST_REQUIRE_EQ(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_NE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_NE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_NE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_NE(...) DOCTEST_FUNC_EMPTY #define DOCTEST_REQUIRE_NE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_GT(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_GT(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_GT(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_GT(...) DOCTEST_FUNC_EMPTY #define DOCTEST_REQUIRE_GT(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_LT(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_LT(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_LT(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_LT(...) DOCTEST_FUNC_EMPTY #define DOCTEST_REQUIRE_LT(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_GE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_GE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_GE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_GE(...) DOCTEST_FUNC_EMPTY #define DOCTEST_REQUIRE_GE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_LE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_LE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_LE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_LE(...) DOCTEST_FUNC_EMPTY #define DOCTEST_REQUIRE_LE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_UNARY(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_UNARY(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_UNARY(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_UNARY_FALSE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_UNARY_FALSE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_UNARY(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_UNARY(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_UNARY(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_UNARY_FALSE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_UNARY_FALSE(...) DOCTEST_FUNC_EMPTY #define DOCTEST_REQUIRE_UNARY_FALSE(...) DOCTEST_FUNC_EMPTY #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS -#define DOCTEST_WARN_THROWS(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_THROWS(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_THROWS(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_THROWS_AS(expr, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_THROWS_AS(expr, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_THROWS_WITH(expr, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_THROWS_WITH(expr, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_THROWS(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_THROWS(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_THROWS(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_THROWS_AS(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_THROWS_AS(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_THROWS_WITH(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_THROWS_WITH(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ...) DOCTEST_FUNC_EMPTY #define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_NOTHROW(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_NOTHROW(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_NOTHROW(...) DOCTEST_FUNC_EMPTY - -#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_NOTHROW(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_NOTHROW(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_NOTHROW(...) DOCTEST_FUNC_EMPTY + +#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_EMPTY #define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY #endif // DOCTEST_CONFIG_NO_EXCEPTIONS @@ -2820,8 +3109,13 @@ namespace detail { #ifdef DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS #define DOCTEST_EXCEPTION_EMPTY_FUNC DOCTEST_FUNC_EMPTY #else // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS -#define DOCTEST_EXCEPTION_EMPTY_FUNC [] { static_assert(false, "Exceptions are disabled! " \ - "Use DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS if you want to compile with exceptions disabled."); return false; }() +#define DOCTEST_EXCEPTION_EMPTY_FUNC \ + [] { \ + static_assert(false, "Exceptions are disabled! " \ + "Use DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS if you want to " \ + "compile with exceptions disabled."); \ + return false; \ + }() #undef DOCTEST_REQUIRE #undef DOCTEST_REQUIRE_FALSE @@ -2836,52 +3130,52 @@ namespace detail { #undef DOCTEST_REQUIRE_UNARY #undef DOCTEST_REQUIRE_UNARY_FALSE -#define DOCTEST_REQUIRE DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_FALSE DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_MESSAGE DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_FALSE DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_MESSAGE DOCTEST_EXCEPTION_EMPTY_FUNC #define DOCTEST_REQUIRE_FALSE_MESSAGE DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_EQ DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_NE DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_GT DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_LT DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_GE DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_LE DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_UNARY DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_UNARY_FALSE DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_EQ DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_NE DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_GT DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_LT DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_GE DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_LE DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_UNARY DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_UNARY_FALSE DOCTEST_EXCEPTION_EMPTY_FUNC #endif // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS -#define DOCTEST_WARN_THROWS(...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_CHECK_THROWS(...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_THROWS(...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_WARN_THROWS_AS(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_CHECK_THROWS_AS(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_WARN_THROWS_WITH(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_CHECK_THROWS_WITH(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_WARN_THROWS(...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_THROWS(...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_THROWS(...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_WARN_THROWS_AS(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_THROWS_AS(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_WARN_THROWS_WITH(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_THROWS_WITH(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC #define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_WARN_NOTHROW(...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_CHECK_NOTHROW(...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_NOTHROW(...) DOCTEST_EXCEPTION_EMPTY_FUNC - -#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_WARN_NOTHROW(...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_NOTHROW(...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_NOTHROW(...) DOCTEST_EXCEPTION_EMPTY_FUNC + +#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC #define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC #endif // DOCTEST_CONFIG_NO_EXCEPTIONS @@ -2933,139 +3227,151 @@ namespace detail { // == SHORT VERSIONS OF THE MACROS #ifndef DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES -#define TEST_CASE(name) DOCTEST_TEST_CASE(name) -#define TEST_CASE_CLASS(name) DOCTEST_TEST_CASE_CLASS(name) -#define TEST_CASE_FIXTURE(x, name) DOCTEST_TEST_CASE_FIXTURE(x, name) -#define TYPE_TO_STRING_AS(str, ...) DOCTEST_TYPE_TO_STRING_AS(str, __VA_ARGS__) -#define TYPE_TO_STRING(...) DOCTEST_TYPE_TO_STRING(__VA_ARGS__) -#define TEST_CASE_TEMPLATE(name, T, ...) DOCTEST_TEST_CASE_TEMPLATE(name, T, __VA_ARGS__) -#define TEST_CASE_TEMPLATE_DEFINE(name, T, id) DOCTEST_TEST_CASE_TEMPLATE_DEFINE(name, T, id) -#define TEST_CASE_TEMPLATE_INVOKE(id, ...) DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, __VA_ARGS__) -#define TEST_CASE_TEMPLATE_APPLY(id, ...) DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, __VA_ARGS__) -#define SUBCASE(name) DOCTEST_SUBCASE(name) -#define TEST_SUITE(decorators) DOCTEST_TEST_SUITE(decorators) -#define TEST_SUITE_BEGIN(name) DOCTEST_TEST_SUITE_BEGIN(name) -#define TEST_SUITE_END DOCTEST_TEST_SUITE_END +#define TEST_CASE(name) DOCTEST_TEST_CASE(name) +#define TEST_CASE_CLASS(name) DOCTEST_TEST_CASE_CLASS(name) +#define TEST_CASE_FIXTURE(x, name) DOCTEST_TEST_CASE_FIXTURE(x, name) +#define TYPE_TO_STRING_AS(str, ...) DOCTEST_TYPE_TO_STRING_AS(str, __VA_ARGS__) +#define TYPE_TO_STRING(...) DOCTEST_TYPE_TO_STRING(__VA_ARGS__) +#define TEST_CASE_TEMPLATE(name, T, ...) DOCTEST_TEST_CASE_TEMPLATE(name, T, __VA_ARGS__) +#define TEST_CASE_TEMPLATE_DEFINE(name, T, id) DOCTEST_TEST_CASE_TEMPLATE_DEFINE(name, T, id) +#define TEST_CASE_TEMPLATE_INVOKE(id, ...) DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, __VA_ARGS__) +#define TEST_CASE_TEMPLATE_APPLY(id, ...) DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, __VA_ARGS__) +#define SUBCASE(name) DOCTEST_SUBCASE(name) +#define TEST_SUITE(decorators) DOCTEST_TEST_SUITE(decorators) +#define TEST_SUITE_BEGIN(name) DOCTEST_TEST_SUITE_BEGIN(name) +#define TEST_SUITE_END DOCTEST_TEST_SUITE_END #define REGISTER_EXCEPTION_TRANSLATOR(signature) DOCTEST_REGISTER_EXCEPTION_TRANSLATOR(signature) -#define REGISTER_REPORTER(name, priority, reporter) DOCTEST_REGISTER_REPORTER(name, priority, reporter) -#define REGISTER_LISTENER(name, priority, reporter) DOCTEST_REGISTER_LISTENER(name, priority, reporter) -#define INFO(...) DOCTEST_INFO(__VA_ARGS__) -#define CAPTURE(x) DOCTEST_CAPTURE(x) -#define ADD_MESSAGE_AT(file, line, ...) DOCTEST_ADD_MESSAGE_AT(file, line, __VA_ARGS__) +#define REGISTER_REPORTER(name, priority, reporter) \ + DOCTEST_REGISTER_REPORTER(name, priority, reporter) +#define REGISTER_LISTENER(name, priority, reporter) \ + DOCTEST_REGISTER_LISTENER(name, priority, reporter) +#define INFO(...) DOCTEST_INFO(__VA_ARGS__) +#define CAPTURE(x) DOCTEST_CAPTURE(x) +#define ADD_MESSAGE_AT(file, line, ...) DOCTEST_ADD_MESSAGE_AT(file, line, __VA_ARGS__) #define ADD_FAIL_CHECK_AT(file, line, ...) DOCTEST_ADD_FAIL_CHECK_AT(file, line, __VA_ARGS__) -#define ADD_FAIL_AT(file, line, ...) DOCTEST_ADD_FAIL_AT(file, line, __VA_ARGS__) -#define MESSAGE(...) DOCTEST_MESSAGE(__VA_ARGS__) -#define FAIL_CHECK(...) DOCTEST_FAIL_CHECK(__VA_ARGS__) -#define FAIL(...) DOCTEST_FAIL(__VA_ARGS__) -#define TO_LVALUE(...) DOCTEST_TO_LVALUE(__VA_ARGS__) - -#define WARN(...) DOCTEST_WARN(__VA_ARGS__) -#define WARN_FALSE(...) DOCTEST_WARN_FALSE(__VA_ARGS__) -#define WARN_THROWS(...) DOCTEST_WARN_THROWS(__VA_ARGS__) -#define WARN_THROWS_AS(expr, ...) DOCTEST_WARN_THROWS_AS(expr, __VA_ARGS__) -#define WARN_THROWS_WITH(expr, ...) DOCTEST_WARN_THROWS_WITH(expr, __VA_ARGS__) -#define WARN_THROWS_WITH_AS(expr, with, ...) DOCTEST_WARN_THROWS_WITH_AS(expr, with, __VA_ARGS__) -#define WARN_NOTHROW(...) DOCTEST_WARN_NOTHROW(__VA_ARGS__) -#define CHECK(...) DOCTEST_CHECK(__VA_ARGS__) -#define CHECK_FALSE(...) DOCTEST_CHECK_FALSE(__VA_ARGS__) -#define CHECK_THROWS(...) DOCTEST_CHECK_THROWS(__VA_ARGS__) -#define CHECK_THROWS_AS(expr, ...) DOCTEST_CHECK_THROWS_AS(expr, __VA_ARGS__) -#define CHECK_THROWS_WITH(expr, ...) DOCTEST_CHECK_THROWS_WITH(expr, __VA_ARGS__) +#define ADD_FAIL_AT(file, line, ...) DOCTEST_ADD_FAIL_AT(file, line, __VA_ARGS__) +#define MESSAGE(...) DOCTEST_MESSAGE(__VA_ARGS__) +#define FAIL_CHECK(...) DOCTEST_FAIL_CHECK(__VA_ARGS__) +#define FAIL(...) DOCTEST_FAIL(__VA_ARGS__) +#define TO_LVALUE(...) DOCTEST_TO_LVALUE(__VA_ARGS__) + +#define WARN(...) DOCTEST_WARN(__VA_ARGS__) +#define WARN_FALSE(...) DOCTEST_WARN_FALSE(__VA_ARGS__) +#define WARN_THROWS(...) DOCTEST_WARN_THROWS(__VA_ARGS__) +#define WARN_THROWS_AS(expr, ...) DOCTEST_WARN_THROWS_AS(expr, __VA_ARGS__) +#define WARN_THROWS_WITH(expr, ...) DOCTEST_WARN_THROWS_WITH(expr, __VA_ARGS__) +#define WARN_THROWS_WITH_AS(expr, with, ...) DOCTEST_WARN_THROWS_WITH_AS(expr, with, __VA_ARGS__) +#define WARN_NOTHROW(...) DOCTEST_WARN_NOTHROW(__VA_ARGS__) +#define CHECK(...) DOCTEST_CHECK(__VA_ARGS__) +#define CHECK_FALSE(...) DOCTEST_CHECK_FALSE(__VA_ARGS__) +#define CHECK_THROWS(...) DOCTEST_CHECK_THROWS(__VA_ARGS__) +#define CHECK_THROWS_AS(expr, ...) DOCTEST_CHECK_THROWS_AS(expr, __VA_ARGS__) +#define CHECK_THROWS_WITH(expr, ...) DOCTEST_CHECK_THROWS_WITH(expr, __VA_ARGS__) #define CHECK_THROWS_WITH_AS(expr, with, ...) DOCTEST_CHECK_THROWS_WITH_AS(expr, with, __VA_ARGS__) -#define CHECK_NOTHROW(...) DOCTEST_CHECK_NOTHROW(__VA_ARGS__) -#define REQUIRE(...) DOCTEST_REQUIRE(__VA_ARGS__) -#define REQUIRE_FALSE(...) DOCTEST_REQUIRE_FALSE(__VA_ARGS__) -#define REQUIRE_THROWS(...) DOCTEST_REQUIRE_THROWS(__VA_ARGS__) -#define REQUIRE_THROWS_AS(expr, ...) DOCTEST_REQUIRE_THROWS_AS(expr, __VA_ARGS__) -#define REQUIRE_THROWS_WITH(expr, ...) DOCTEST_REQUIRE_THROWS_WITH(expr, __VA_ARGS__) -#define REQUIRE_THROWS_WITH_AS(expr, with, ...) DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, __VA_ARGS__) +#define CHECK_NOTHROW(...) DOCTEST_CHECK_NOTHROW(__VA_ARGS__) +#define REQUIRE(...) DOCTEST_REQUIRE(__VA_ARGS__) +#define REQUIRE_FALSE(...) DOCTEST_REQUIRE_FALSE(__VA_ARGS__) +#define REQUIRE_THROWS(...) DOCTEST_REQUIRE_THROWS(__VA_ARGS__) +#define REQUIRE_THROWS_AS(expr, ...) DOCTEST_REQUIRE_THROWS_AS(expr, __VA_ARGS__) +#define REQUIRE_THROWS_WITH(expr, ...) DOCTEST_REQUIRE_THROWS_WITH(expr, __VA_ARGS__) +#define REQUIRE_THROWS_WITH_AS(expr, with, ...) \ + DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, __VA_ARGS__) #define REQUIRE_NOTHROW(...) DOCTEST_REQUIRE_NOTHROW(__VA_ARGS__) -#define WARN_MESSAGE(cond, ...) DOCTEST_WARN_MESSAGE(cond, __VA_ARGS__) -#define WARN_FALSE_MESSAGE(cond, ...) DOCTEST_WARN_FALSE_MESSAGE(cond, __VA_ARGS__) -#define WARN_THROWS_MESSAGE(expr, ...) DOCTEST_WARN_THROWS_MESSAGE(expr, __VA_ARGS__) +#define WARN_MESSAGE(cond, ...) DOCTEST_WARN_MESSAGE(cond, __VA_ARGS__) +#define WARN_FALSE_MESSAGE(cond, ...) DOCTEST_WARN_FALSE_MESSAGE(cond, __VA_ARGS__) +#define WARN_THROWS_MESSAGE(expr, ...) DOCTEST_WARN_THROWS_MESSAGE(expr, __VA_ARGS__) #define WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__) -#define WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__) -#define WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__) +#define WARN_THROWS_WITH_MESSAGE(expr, with, ...) \ + DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__) +#define WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) \ + DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__) #define WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_WARN_NOTHROW_MESSAGE(expr, __VA_ARGS__) -#define CHECK_MESSAGE(cond, ...) DOCTEST_CHECK_MESSAGE(cond, __VA_ARGS__) -#define CHECK_FALSE_MESSAGE(cond, ...) DOCTEST_CHECK_FALSE_MESSAGE(cond, __VA_ARGS__) +#define CHECK_MESSAGE(cond, ...) DOCTEST_CHECK_MESSAGE(cond, __VA_ARGS__) +#define CHECK_FALSE_MESSAGE(cond, ...) DOCTEST_CHECK_FALSE_MESSAGE(cond, __VA_ARGS__) #define CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_CHECK_THROWS_MESSAGE(expr, __VA_ARGS__) -#define CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__) -#define CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__) -#define CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__) -#define CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_CHECK_NOTHROW_MESSAGE(expr, __VA_ARGS__) -#define REQUIRE_MESSAGE(cond, ...) DOCTEST_REQUIRE_MESSAGE(cond, __VA_ARGS__) -#define REQUIRE_FALSE_MESSAGE(cond, ...) DOCTEST_REQUIRE_FALSE_MESSAGE(cond, __VA_ARGS__) +#define CHECK_THROWS_AS_MESSAGE(expr, ex, ...) \ + DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__) +#define CHECK_THROWS_WITH_MESSAGE(expr, with, ...) \ + DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__) +#define CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) \ + DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__) +#define CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_CHECK_NOTHROW_MESSAGE(expr, __VA_ARGS__) +#define REQUIRE_MESSAGE(cond, ...) DOCTEST_REQUIRE_MESSAGE(cond, __VA_ARGS__) +#define REQUIRE_FALSE_MESSAGE(cond, ...) DOCTEST_REQUIRE_FALSE_MESSAGE(cond, __VA_ARGS__) #define REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_REQUIRE_THROWS_MESSAGE(expr, __VA_ARGS__) -#define REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__) -#define REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__) -#define REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__) +#define REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) \ + DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__) +#define REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) \ + DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__) +#define REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) \ + DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__) #define REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, __VA_ARGS__) -#define SCENARIO(name) DOCTEST_SCENARIO(name) -#define SCENARIO_CLASS(name) DOCTEST_SCENARIO_CLASS(name) -#define SCENARIO_TEMPLATE(name, T, ...) DOCTEST_SCENARIO_TEMPLATE(name, T, __VA_ARGS__) +#define SCENARIO(name) DOCTEST_SCENARIO(name) +#define SCENARIO_CLASS(name) DOCTEST_SCENARIO_CLASS(name) +#define SCENARIO_TEMPLATE(name, T, ...) DOCTEST_SCENARIO_TEMPLATE(name, T, __VA_ARGS__) #define SCENARIO_TEMPLATE_DEFINE(name, T, id) DOCTEST_SCENARIO_TEMPLATE_DEFINE(name, T, id) -#define GIVEN(name) DOCTEST_GIVEN(name) -#define WHEN(name) DOCTEST_WHEN(name) -#define AND_WHEN(name) DOCTEST_AND_WHEN(name) -#define THEN(name) DOCTEST_THEN(name) -#define AND_THEN(name) DOCTEST_AND_THEN(name) - -#define WARN_EQ(...) DOCTEST_WARN_EQ(__VA_ARGS__) -#define CHECK_EQ(...) DOCTEST_CHECK_EQ(__VA_ARGS__) -#define REQUIRE_EQ(...) DOCTEST_REQUIRE_EQ(__VA_ARGS__) -#define WARN_NE(...) DOCTEST_WARN_NE(__VA_ARGS__) -#define CHECK_NE(...) DOCTEST_CHECK_NE(__VA_ARGS__) -#define REQUIRE_NE(...) DOCTEST_REQUIRE_NE(__VA_ARGS__) -#define WARN_GT(...) DOCTEST_WARN_GT(__VA_ARGS__) -#define CHECK_GT(...) DOCTEST_CHECK_GT(__VA_ARGS__) -#define REQUIRE_GT(...) DOCTEST_REQUIRE_GT(__VA_ARGS__) -#define WARN_LT(...) DOCTEST_WARN_LT(__VA_ARGS__) -#define CHECK_LT(...) DOCTEST_CHECK_LT(__VA_ARGS__) -#define REQUIRE_LT(...) DOCTEST_REQUIRE_LT(__VA_ARGS__) -#define WARN_GE(...) DOCTEST_WARN_GE(__VA_ARGS__) -#define CHECK_GE(...) DOCTEST_CHECK_GE(__VA_ARGS__) -#define REQUIRE_GE(...) DOCTEST_REQUIRE_GE(__VA_ARGS__) -#define WARN_LE(...) DOCTEST_WARN_LE(__VA_ARGS__) -#define CHECK_LE(...) DOCTEST_CHECK_LE(__VA_ARGS__) -#define REQUIRE_LE(...) DOCTEST_REQUIRE_LE(__VA_ARGS__) -#define WARN_UNARY(...) DOCTEST_WARN_UNARY(__VA_ARGS__) -#define CHECK_UNARY(...) DOCTEST_CHECK_UNARY(__VA_ARGS__) -#define REQUIRE_UNARY(...) DOCTEST_REQUIRE_UNARY(__VA_ARGS__) -#define WARN_UNARY_FALSE(...) DOCTEST_WARN_UNARY_FALSE(__VA_ARGS__) -#define CHECK_UNARY_FALSE(...) DOCTEST_CHECK_UNARY_FALSE(__VA_ARGS__) +#define GIVEN(name) DOCTEST_GIVEN(name) +#define WHEN(name) DOCTEST_WHEN(name) +#define AND_WHEN(name) DOCTEST_AND_WHEN(name) +#define THEN(name) DOCTEST_THEN(name) +#define AND_THEN(name) DOCTEST_AND_THEN(name) + +#define WARN_EQ(...) DOCTEST_WARN_EQ(__VA_ARGS__) +#define CHECK_EQ(...) DOCTEST_CHECK_EQ(__VA_ARGS__) +#define REQUIRE_EQ(...) DOCTEST_REQUIRE_EQ(__VA_ARGS__) +#define WARN_NE(...) DOCTEST_WARN_NE(__VA_ARGS__) +#define CHECK_NE(...) DOCTEST_CHECK_NE(__VA_ARGS__) +#define REQUIRE_NE(...) DOCTEST_REQUIRE_NE(__VA_ARGS__) +#define WARN_GT(...) DOCTEST_WARN_GT(__VA_ARGS__) +#define CHECK_GT(...) DOCTEST_CHECK_GT(__VA_ARGS__) +#define REQUIRE_GT(...) DOCTEST_REQUIRE_GT(__VA_ARGS__) +#define WARN_LT(...) DOCTEST_WARN_LT(__VA_ARGS__) +#define CHECK_LT(...) DOCTEST_CHECK_LT(__VA_ARGS__) +#define REQUIRE_LT(...) DOCTEST_REQUIRE_LT(__VA_ARGS__) +#define WARN_GE(...) DOCTEST_WARN_GE(__VA_ARGS__) +#define CHECK_GE(...) DOCTEST_CHECK_GE(__VA_ARGS__) +#define REQUIRE_GE(...) DOCTEST_REQUIRE_GE(__VA_ARGS__) +#define WARN_LE(...) DOCTEST_WARN_LE(__VA_ARGS__) +#define CHECK_LE(...) DOCTEST_CHECK_LE(__VA_ARGS__) +#define REQUIRE_LE(...) DOCTEST_REQUIRE_LE(__VA_ARGS__) +#define WARN_UNARY(...) DOCTEST_WARN_UNARY(__VA_ARGS__) +#define CHECK_UNARY(...) DOCTEST_CHECK_UNARY(__VA_ARGS__) +#define REQUIRE_UNARY(...) DOCTEST_REQUIRE_UNARY(__VA_ARGS__) +#define WARN_UNARY_FALSE(...) DOCTEST_WARN_UNARY_FALSE(__VA_ARGS__) +#define CHECK_UNARY_FALSE(...) DOCTEST_CHECK_UNARY_FALSE(__VA_ARGS__) #define REQUIRE_UNARY_FALSE(...) DOCTEST_REQUIRE_UNARY_FALSE(__VA_ARGS__) // KEPT FOR BACKWARDS COMPATIBILITY -#define FAST_WARN_EQ(...) DOCTEST_FAST_WARN_EQ(__VA_ARGS__) -#define FAST_CHECK_EQ(...) DOCTEST_FAST_CHECK_EQ(__VA_ARGS__) +#define FAST_WARN_EQ(...) DOCTEST_FAST_WARN_EQ(__VA_ARGS__) +#define FAST_CHECK_EQ(...) DOCTEST_FAST_CHECK_EQ(__VA_ARGS__) #define FAST_REQUIRE_EQ(...) DOCTEST_FAST_REQUIRE_EQ(__VA_ARGS__) -#define FAST_WARN_NE(...) DOCTEST_FAST_WARN_NE(__VA_ARGS__) -#define FAST_CHECK_NE(...) DOCTEST_FAST_CHECK_NE(__VA_ARGS__) +#define FAST_WARN_NE(...) DOCTEST_FAST_WARN_NE(__VA_ARGS__) +#define FAST_CHECK_NE(...) DOCTEST_FAST_CHECK_NE(__VA_ARGS__) #define FAST_REQUIRE_NE(...) DOCTEST_FAST_REQUIRE_NE(__VA_ARGS__) -#define FAST_WARN_GT(...) DOCTEST_FAST_WARN_GT(__VA_ARGS__) -#define FAST_CHECK_GT(...) DOCTEST_FAST_CHECK_GT(__VA_ARGS__) +#define FAST_WARN_GT(...) DOCTEST_FAST_WARN_GT(__VA_ARGS__) +#define FAST_CHECK_GT(...) DOCTEST_FAST_CHECK_GT(__VA_ARGS__) #define FAST_REQUIRE_GT(...) DOCTEST_FAST_REQUIRE_GT(__VA_ARGS__) -#define FAST_WARN_LT(...) DOCTEST_FAST_WARN_LT(__VA_ARGS__) -#define FAST_CHECK_LT(...) DOCTEST_FAST_CHECK_LT(__VA_ARGS__) +#define FAST_WARN_LT(...) DOCTEST_FAST_WARN_LT(__VA_ARGS__) +#define FAST_CHECK_LT(...) DOCTEST_FAST_CHECK_LT(__VA_ARGS__) #define FAST_REQUIRE_LT(...) DOCTEST_FAST_REQUIRE_LT(__VA_ARGS__) -#define FAST_WARN_GE(...) DOCTEST_FAST_WARN_GE(__VA_ARGS__) -#define FAST_CHECK_GE(...) DOCTEST_FAST_CHECK_GE(__VA_ARGS__) +#define FAST_WARN_GE(...) DOCTEST_FAST_WARN_GE(__VA_ARGS__) +#define FAST_CHECK_GE(...) DOCTEST_FAST_CHECK_GE(__VA_ARGS__) #define FAST_REQUIRE_GE(...) DOCTEST_FAST_REQUIRE_GE(__VA_ARGS__) -#define FAST_WARN_LE(...) DOCTEST_FAST_WARN_LE(__VA_ARGS__) -#define FAST_CHECK_LE(...) DOCTEST_FAST_CHECK_LE(__VA_ARGS__) +#define FAST_WARN_LE(...) DOCTEST_FAST_WARN_LE(__VA_ARGS__) +#define FAST_CHECK_LE(...) DOCTEST_FAST_CHECK_LE(__VA_ARGS__) #define FAST_REQUIRE_LE(...) DOCTEST_FAST_REQUIRE_LE(__VA_ARGS__) -#define FAST_WARN_UNARY(...) DOCTEST_FAST_WARN_UNARY(__VA_ARGS__) -#define FAST_CHECK_UNARY(...) DOCTEST_FAST_CHECK_UNARY(__VA_ARGS__) -#define FAST_REQUIRE_UNARY(...) DOCTEST_FAST_REQUIRE_UNARY(__VA_ARGS__) -#define FAST_WARN_UNARY_FALSE(...) DOCTEST_FAST_WARN_UNARY_FALSE(__VA_ARGS__) -#define FAST_CHECK_UNARY_FALSE(...) DOCTEST_FAST_CHECK_UNARY_FALSE(__VA_ARGS__) +#define FAST_WARN_UNARY(...) DOCTEST_FAST_WARN_UNARY(__VA_ARGS__) +#define FAST_CHECK_UNARY(...) DOCTEST_FAST_CHECK_UNARY(__VA_ARGS__) +#define FAST_REQUIRE_UNARY(...) DOCTEST_FAST_REQUIRE_UNARY(__VA_ARGS__) +#define FAST_WARN_UNARY_FALSE(...) DOCTEST_FAST_WARN_UNARY_FALSE(__VA_ARGS__) +#define FAST_CHECK_UNARY_FALSE(...) DOCTEST_FAST_CHECK_UNARY_FALSE(__VA_ARGS__) #define FAST_REQUIRE_UNARY_FALSE(...) DOCTEST_FAST_REQUIRE_UNARY_FALSE(__VA_ARGS__) -#define TEST_CASE_TEMPLATE_INSTANTIATE(id, ...) DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE(id, __VA_ARGS__) +#define TEST_CASE_TEMPLATE_INSTANTIATE(id, ...) \ + DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE(id, __VA_ARGS__) #endif // DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES @@ -3146,21 +3452,22 @@ DOCTEST_MSVC_SUPPRESS_WARNING(5245) // unreferenced function with internal linka DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN // required includes - will go only in one translation unit! -#include -#include #include -// borland (Embarcadero) compiler requires math.h and not cmath - https://github.com/doctest/doctest/pull/37 +#include +#include +// borland (Embarcadero) compiler requires math.h and not cmath - +// https://github.com/doctest/doctest/pull/37 #ifdef __BORLANDC__ #include #endif // __BORLANDC__ -#include #include #include #include -#include -#include #include +#include +#include #include +#include #ifndef DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM #include #endif // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM @@ -3170,29 +3477,30 @@ DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN #ifndef DOCTEST_CONFIG_NO_MULTITHREADING #include #include -#define DOCTEST_DECLARE_MUTEX(name) std::mutex name; +#define DOCTEST_DECLARE_MUTEX(name) std::mutex name; #define DOCTEST_DECLARE_STATIC_MUTEX(name) static DOCTEST_DECLARE_MUTEX(name) -#define DOCTEST_LOCK_MUTEX(name) std::lock_guard DOCTEST_ANONYMOUS(DOCTEST_ANON_LOCK_)(name); +#define DOCTEST_LOCK_MUTEX(name) \ + std::lock_guard DOCTEST_ANONYMOUS(DOCTEST_ANON_LOCK_)(name); #else // DOCTEST_CONFIG_NO_MULTITHREADING #define DOCTEST_DECLARE_MUTEX(name) #define DOCTEST_DECLARE_STATIC_MUTEX(name) #define DOCTEST_LOCK_MUTEX(name) #endif // DOCTEST_CONFIG_NO_MULTITHREADING -#include -#include -#include -#include -#include -#include -#include #include +#include +#include #include +#include +#include +#include +#include #include +#include #ifdef DOCTEST_PLATFORM_MAC +#include #include #include -#include #endif // DOCTEST_PLATFORM_MAC #ifdef DOCTEST_PLATFORM_WINDOWS @@ -3244,7 +3552,8 @@ DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END #endif #ifndef DOCTEST_THREAD_LOCAL -#if defined(DOCTEST_CONFIG_NO_MULTITHREADING) || DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0)) +#if defined(DOCTEST_CONFIG_NO_MULTITHREADING) || \ + DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0)) #define DOCTEST_THREAD_LOCAL #else // DOCTEST_MSVC #define DOCTEST_THREAD_LOCAL thread_local @@ -3275,156 +3584,154 @@ DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END namespace doctest { -bool is_running_in_test = false; + bool is_running_in_test = false; -namespace { + namespace { using namespace detail; - template - DOCTEST_NORETURN void throw_exception(Ex const& e) { + template DOCTEST_NORETURN void throw_exception(Ex const &e) + { #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS - throw e; -#else // DOCTEST_CONFIG_NO_EXCEPTIONS + throw e; +#else // DOCTEST_CONFIG_NO_EXCEPTIONS #ifdef DOCTEST_CONFIG_HANDLE_EXCEPTION - DOCTEST_CONFIG_HANDLE_EXCEPTION(e); + DOCTEST_CONFIG_HANDLE_EXCEPTION(e); #else // DOCTEST_CONFIG_HANDLE_EXCEPTION #ifndef DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM - std::cerr << "doctest will terminate because it needed to throw an exception.\n" - << "The message was: " << e.what() << '\n'; + std::cerr << "doctest will terminate because it needed to throw an exception.\n" + << "The message was: " << e.what() << '\n'; #endif // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM #endif // DOCTEST_CONFIG_HANDLE_EXCEPTION - std::terminate(); + std::terminate(); #endif // DOCTEST_CONFIG_NO_EXCEPTIONS } #ifndef DOCTEST_INTERNAL_ERROR #define DOCTEST_INTERNAL_ERROR(msg) \ - throw_exception(std::logic_error( \ - __FILE__ ":" DOCTEST_TOSTR(__LINE__) ": Internal doctest error: " msg)) + throw_exception( \ + std::logic_error(__FILE__ ":" DOCTEST_TOSTR(__LINE__) ": Internal doctest error: " msg)) #endif // DOCTEST_INTERNAL_ERROR // case insensitive strcmp - int stricmp(const char* a, const char* b) { - for(;; a++, b++) { - const int d = tolower(*a) - tolower(*b); - if(d != 0 || !*a) - return d; - } + int stricmp(const char *a, const char *b) + { + for (;; a++, b++) { + const int d = tolower(*a) - tolower(*b); + if (d != 0 || !*a) + return d; + } } struct Endianness { - enum Arch - { - Big, - Little - }; - - static Arch which() { - int x = 1; - // casting any data pointer to char* is allowed - auto ptr = reinterpret_cast(&x); - if(*ptr) - return Little; - return Big; - } + enum Arch { Big, Little }; + + static Arch which() + { + int x = 1; + // casting any data pointer to char* is allowed + auto ptr = reinterpret_cast(&x); + if (*ptr) + return Little; + return Big; + } }; -} // namespace + } // namespace -namespace detail { + namespace detail { DOCTEST_THREAD_LOCAL class { - std::vector stack; - std::stringstream ss; + std::vector stack; + std::stringstream ss; public: - std::ostream* push() { - stack.push_back(ss.tellp()); - return &ss; - } - - String pop() { - if (stack.empty()) - DOCTEST_INTERNAL_ERROR("TLSS was empty when trying to pop!"); - - std::streampos pos = stack.back(); - stack.pop_back(); - unsigned sz = static_cast(ss.tellp() - pos); - ss.rdbuf()->pubseekpos(pos, std::ios::in | std::ios::out); - return String(ss, sz); - } + std::ostream *push() + { + stack.push_back(ss.tellp()); + return &ss; + } + + String pop() + { + if (stack.empty()) + DOCTEST_INTERNAL_ERROR("TLSS was empty when trying to pop!"); + + std::streampos pos = stack.back(); + stack.pop_back(); + unsigned sz = static_cast(ss.tellp() - pos); + ss.rdbuf()->pubseekpos(pos, std::ios::in | std::ios::out); + return String(ss, sz); + } } g_oss; - std::ostream* tlssPush() { - return g_oss.push(); - } + std::ostream *tlssPush() { return g_oss.push(); } - String tlssPop() { - return g_oss.pop(); - } + String tlssPop() { return g_oss.pop(); } #ifndef DOCTEST_CONFIG_DISABLE -namespace timer_large_integer -{ + namespace timer_large_integer { #if defined(DOCTEST_PLATFORM_WINDOWS) - using type = ULONGLONG; -#else // DOCTEST_PLATFORM_WINDOWS - using type = std::uint64_t; + using type = ULONGLONG; +#else // DOCTEST_PLATFORM_WINDOWS + using type = std::uint64_t; #endif // DOCTEST_PLATFORM_WINDOWS -} + } // namespace timer_large_integer -using ticks_t = timer_large_integer::type; + using ticks_t = timer_large_integer::type; #ifdef DOCTEST_CONFIG_GETCURRENTTICKS ticks_t getCurrentTicks() { return DOCTEST_CONFIG_GETCURRENTTICKS(); } #elif defined(DOCTEST_PLATFORM_WINDOWS) - ticks_t getCurrentTicks() { - static LARGE_INTEGER hz = { {0} }, hzo = { {0} }; - if(!hz.QuadPart) { - QueryPerformanceFrequency(&hz); - QueryPerformanceCounter(&hzo); - } - LARGE_INTEGER t; - QueryPerformanceCounter(&t); - return ((t.QuadPart - hzo.QuadPart) * LONGLONG(1000000)) / hz.QuadPart; + ticks_t getCurrentTicks() + { + static LARGE_INTEGER hz = {{0}}, hzo = {{0}}; + if (!hz.QuadPart) { + QueryPerformanceFrequency(&hz); + QueryPerformanceCounter(&hzo); + } + LARGE_INTEGER t; + QueryPerformanceCounter(&t); + return ((t.QuadPart - hzo.QuadPart) * LONGLONG(1000000)) / hz.QuadPart; } #else // DOCTEST_PLATFORM_WINDOWS - ticks_t getCurrentTicks() { - timeval t; - gettimeofday(&t, nullptr); - return static_cast(t.tv_sec) * 1000000 + static_cast(t.tv_usec); + ticks_t getCurrentTicks() + { + timeval t; + gettimeofday(&t, nullptr); + return static_cast(t.tv_sec) * 1000000 + static_cast(t.tv_usec); } #endif // DOCTEST_PLATFORM_WINDOWS struct Timer { - void start() { m_ticks = getCurrentTicks(); } - unsigned int getElapsedMicroseconds() const { - return static_cast(getCurrentTicks() - m_ticks); - } - //unsigned int getElapsedMilliseconds() const { - // return static_cast(getElapsedMicroseconds() / 1000); - //} - double getElapsedSeconds() const { return static_cast(getCurrentTicks() - m_ticks) / 1000000.0; } + void start() { m_ticks = getCurrentTicks(); } + unsigned int getElapsedMicroseconds() const + { + return static_cast(getCurrentTicks() - m_ticks); + } + // unsigned int getElapsedMilliseconds() const { + // return static_cast(getElapsedMicroseconds() / 1000); + // } + double getElapsedSeconds() const + { + return static_cast(getCurrentTicks() - m_ticks) / 1000000.0; + } private: - ticks_t m_ticks = 0; + ticks_t m_ticks = 0; }; #ifdef DOCTEST_CONFIG_NO_MULTITHREADING - template - using Atomic = T; -#else // DOCTEST_CONFIG_NO_MULTITHREADING - template - using Atomic = std::atomic; + template using Atomic = T; +#else // DOCTEST_CONFIG_NO_MULTITHREADING + template using Atomic = std::atomic; #endif // DOCTEST_CONFIG_NO_MULTITHREADING #if defined(DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS) || defined(DOCTEST_CONFIG_NO_MULTITHREADING) - template - using MultiLaneAtomic = Atomic; -#else // DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS + template using MultiLaneAtomic = Atomic; +#else // DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS // Provides a multilane implementation of an atomic variable that supports add, sub, load, // store. Instead of using a single atomic variable, this splits up into multiple ones, // each sitting on a separate cache line. The goal is to provide a speedup when most @@ -3435,157 +3742,168 @@ using ticks_t = timer_large_integer::type; // // The disadvantage is that there is a small overhead due to the use of TLS, and load/store // is slower because all atomics have to be accessed. - template - class MultiLaneAtomic + template class MultiLaneAtomic { - struct CacheLineAlignedAtomic - { - Atomic atomic{}; - char padding[DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE - sizeof(Atomic)]; - }; - CacheLineAlignedAtomic m_atomics[DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES]; + struct CacheLineAlignedAtomic + { + Atomic atomic{}; + char padding[DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE - sizeof(Atomic)]; + }; + CacheLineAlignedAtomic m_atomics[DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES]; - static_assert(sizeof(CacheLineAlignedAtomic) == DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE, - "guarantee one atomic takes exactly one cache line"); + static_assert(sizeof(CacheLineAlignedAtomic) == DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE, + "guarantee one atomic takes exactly one cache line"); public: - T operator++() DOCTEST_NOEXCEPT { return fetch_add(1) + 1; } + T operator++() DOCTEST_NOEXCEPT { return fetch_add(1) + 1; } - T operator++(int) DOCTEST_NOEXCEPT { return fetch_add(1); } + T operator++(int) DOCTEST_NOEXCEPT { return fetch_add(1); } - T fetch_add(T arg, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT { - return myAtomic().fetch_add(arg, order); - } + T fetch_add(T arg, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT + { + return myAtomic().fetch_add(arg, order); + } - T fetch_sub(T arg, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT { - return myAtomic().fetch_sub(arg, order); - } + T fetch_sub(T arg, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT + { + return myAtomic().fetch_sub(arg, order); + } - operator T() const DOCTEST_NOEXCEPT { return load(); } + operator T() const DOCTEST_NOEXCEPT { return load(); } - T load(std::memory_order order = std::memory_order_seq_cst) const DOCTEST_NOEXCEPT { - auto result = T(); - for(auto const& c : m_atomics) { - result += c.atomic.load(order); - } - return result; + T load(std::memory_order order = std::memory_order_seq_cst) const DOCTEST_NOEXCEPT + { + auto result = T(); + for (auto const &c : m_atomics) { + result += c.atomic.load(order); } + return result; + } - T operator=(T desired) DOCTEST_NOEXCEPT { // lgtm [cpp/assignment-does-not-return-this] - store(desired); - return desired; - } + T operator=(T desired) DOCTEST_NOEXCEPT + { // lgtm [cpp/assignment-does-not-return-this] + store(desired); + return desired; + } - void store(T desired, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT { - // first value becomes desired", all others become 0. - for(auto& c : m_atomics) { - c.atomic.store(desired, order); - desired = {}; - } + void store(T desired, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT + { + // first value becomes desired", all others become 0. + for (auto &c : m_atomics) { + c.atomic.store(desired, order); + desired = {}; } + } private: - // Each thread has a different atomic that it operates on. If more than NumLanes threads - // use this, some will use the same atomic. So performance will degrade a bit, but still - // everything will work. - // - // The logic here is a bit tricky. The call should be as fast as possible, so that there - // is minimal to no overhead in determining the correct atomic for the current thread. - // - // 1. A global static counter laneCounter counts continuously up. - // 2. Each successive thread will use modulo operation of that counter so it gets an atomic - // assigned in a round-robin fashion. - // 3. This tlsLaneIdx is stored in the thread local data, so it is directly available with - // little overhead. - Atomic& myAtomic() DOCTEST_NOEXCEPT { - static Atomic laneCounter; - DOCTEST_THREAD_LOCAL size_t tlsLaneIdx = - laneCounter++ % DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES; - - return m_atomics[tlsLaneIdx].atomic; - } + // Each thread has a different atomic that it operates on. If more than NumLanes threads + // use this, some will use the same atomic. So performance will degrade a bit, but still + // everything will work. + // + // The logic here is a bit tricky. The call should be as fast as possible, so that there + // is minimal to no overhead in determining the correct atomic for the current thread. + // + // 1. A global static counter laneCounter counts continuously up. + // 2. Each successive thread will use modulo operation of that counter so it gets an atomic + // assigned in a round-robin fashion. + // 3. This tlsLaneIdx is stored in the thread local data, so it is directly available with + // little overhead. + Atomic &myAtomic() DOCTEST_NOEXCEPT + { + static Atomic laneCounter; + DOCTEST_THREAD_LOCAL size_t tlsLaneIdx = + laneCounter++ % DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES; + + return m_atomics[tlsLaneIdx].atomic; + } }; #endif // DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS // this holds both parameters from the command line and runtime data for tests struct ContextState : ContextOptions, TestRunStats, CurrentTestCaseStats { - MultiLaneAtomic numAssertsCurrentTest_atomic; - MultiLaneAtomic numAssertsFailedCurrentTest_atomic; - - std::vector> filters = decltype(filters)(9); // 9 different filters - - std::vector reporters_currently_used; - - assert_handler ah = nullptr; - - Timer timer; - - std::vector stringifiedContexts; // logging from INFO() due to an exception - - // stuff for subcases - bool reachedLeaf; - std::vector subcaseStack; - std::vector nextSubcaseStack; - std::unordered_set fullyTraversedSubcases; - size_t currentSubcaseDepth; - Atomic shouldLogCurrentException; - - void resetRunData() { - numTestCases = 0; - numTestCasesPassingFilters = 0; - numTestSuitesPassingFilters = 0; - numTestCasesFailed = 0; - numAsserts = 0; - numAssertsFailed = 0; - numAssertsCurrentTest = 0; - numAssertsFailedCurrentTest = 0; - } - - void finalizeTestCaseData() { - seconds = timer.getElapsedSeconds(); - - // update the non-atomic counters - numAsserts += numAssertsCurrentTest_atomic; - numAssertsFailed += numAssertsFailedCurrentTest_atomic; - numAssertsCurrentTest = numAssertsCurrentTest_atomic; - numAssertsFailedCurrentTest = numAssertsFailedCurrentTest_atomic; - - if(numAssertsFailedCurrentTest) - failure_flags |= TestCaseFailureReason::AssertFailure; - - if(Approx(currentTest->m_timeout).epsilon(DBL_EPSILON) != 0 && - Approx(seconds).epsilon(DBL_EPSILON) > currentTest->m_timeout) - failure_flags |= TestCaseFailureReason::Timeout; - - if(currentTest->m_should_fail) { - if(failure_flags) { - failure_flags |= TestCaseFailureReason::ShouldHaveFailedAndDid; - } else { - failure_flags |= TestCaseFailureReason::ShouldHaveFailedButDidnt; - } - } else if(failure_flags && currentTest->m_may_fail) { - failure_flags |= TestCaseFailureReason::CouldHaveFailedAndDid; - } else if(currentTest->m_expected_failures > 0) { - if(numAssertsFailedCurrentTest == currentTest->m_expected_failures) { - failure_flags |= TestCaseFailureReason::FailedExactlyNumTimes; - } else { - failure_flags |= TestCaseFailureReason::DidntFailExactlyNumTimes; - } - } - - bool ok_to_fail = (TestCaseFailureReason::ShouldHaveFailedAndDid & failure_flags) || - (TestCaseFailureReason::CouldHaveFailedAndDid & failure_flags) || - (TestCaseFailureReason::FailedExactlyNumTimes & failure_flags); - - // if any subcase has failed - the whole test case has failed - testCaseSuccess = !(failure_flags && !ok_to_fail); - if(!testCaseSuccess) - numTestCasesFailed++; - } + MultiLaneAtomic numAssertsCurrentTest_atomic; + MultiLaneAtomic numAssertsFailedCurrentTest_atomic; + + std::vector> filters = decltype(filters)(9); // 9 different filters + + std::vector reporters_currently_used; + + assert_handler ah = nullptr; + + Timer timer; + + std::vector stringifiedContexts; // logging from INFO() due to an exception + + // stuff for subcases + bool reachedLeaf; + std::vector subcaseStack; + std::vector nextSubcaseStack; + std::unordered_set fullyTraversedSubcases; + size_t currentSubcaseDepth; + Atomic shouldLogCurrentException; + + void resetRunData() + { + numTestCases = 0; + numTestCasesPassingFilters = 0; + numTestSuitesPassingFilters = 0; + numTestCasesFailed = 0; + numAsserts = 0; + numAssertsFailed = 0; + numAssertsCurrentTest = 0; + numAssertsFailedCurrentTest = 0; + } + + void finalizeTestCaseData() + { + seconds = timer.getElapsedSeconds(); + + // update the non-atomic counters + numAsserts += numAssertsCurrentTest_atomic; + numAssertsFailed += numAssertsFailedCurrentTest_atomic; + numAssertsCurrentTest = numAssertsCurrentTest_atomic; + numAssertsFailedCurrentTest = numAssertsFailedCurrentTest_atomic; + + if (numAssertsFailedCurrentTest) + failure_flags |= TestCaseFailureReason::AssertFailure; + + if (Approx(currentTest->m_timeout).epsilon(DBL_EPSILON) != 0 && + Approx(seconds).epsilon(DBL_EPSILON) > currentTest->m_timeout) + failure_flags |= TestCaseFailureReason::Timeout; + + if (currentTest->m_should_fail) { + if (failure_flags) { + failure_flags |= TestCaseFailureReason::ShouldHaveFailedAndDid; + } + else { + failure_flags |= TestCaseFailureReason::ShouldHaveFailedButDidnt; + } + } + else if (failure_flags && currentTest->m_may_fail) { + failure_flags |= TestCaseFailureReason::CouldHaveFailedAndDid; + } + else if (currentTest->m_expected_failures > 0) { + if (numAssertsFailedCurrentTest == currentTest->m_expected_failures) { + failure_flags |= TestCaseFailureReason::FailedExactlyNumTimes; + } + else { + failure_flags |= TestCaseFailureReason::DidntFailExactlyNumTimes; + } + } + + bool ok_to_fail = (TestCaseFailureReason::ShouldHaveFailedAndDid & failure_flags) || + (TestCaseFailureReason::CouldHaveFailedAndDid & failure_flags) || + (TestCaseFailureReason::FailedExactlyNumTimes & failure_flags); + + // if any subcase has failed - the whole test case has failed + testCaseSuccess = !(failure_flags && !ok_to_fail); + if (!testCaseSuccess) + numTestCasesFailed++; + } }; - ContextState* g_cs = nullptr; + ContextState *g_cs = nullptr; // used to avoid locks for the debug output // TODO: figure out if this is indeed necessary/correct - seems like either there still @@ -3593,241 +3911,279 @@ using ticks_t = timer_large_integer::type; DOCTEST_THREAD_LOCAL bool g_no_colors; #endif // DOCTEST_CONFIG_DISABLE -} // namespace detail + } // namespace detail -char* String::allocate(size_type sz) { + char *String::allocate(size_type sz) + { if (sz <= last) { - buf[sz] = '\0'; - setLast(last - sz); - return buf; - } else { - setOnHeap(); - data.size = sz; - data.capacity = data.size + 1; - data.ptr = new char[data.capacity]; - data.ptr[sz] = '\0'; - return data.ptr; + buf[sz] = '\0'; + setLast(last - sz); + return buf; } -} - -void String::setOnHeap() noexcept { *reinterpret_cast(&buf[last]) = 128; } -void String::setLast(size_type in) noexcept { buf[last] = char(in); } -void String::setSize(size_type sz) noexcept { - if (isOnStack()) { buf[sz] = '\0'; setLast(last - sz); } - else { data.ptr[sz] = '\0'; data.size = sz; } -} + else { + setOnHeap(); + data.size = sz; + data.capacity = data.size + 1; + data.ptr = new char[data.capacity]; + data.ptr[sz] = '\0'; + return data.ptr; + } + } + + void String::setOnHeap() noexcept { *reinterpret_cast(&buf[last]) = 128; } + void String::setLast(size_type in) noexcept { buf[last] = char(in); } + void String::setSize(size_type sz) noexcept + { + if (isOnStack()) { + buf[sz] = '\0'; + setLast(last - sz); + } + else { + data.ptr[sz] = '\0'; + data.size = sz; + } + } -void String::copy(const String& other) { - if(other.isOnStack()) { - memcpy(buf, other.buf, len); - } else { - memcpy(allocate(other.data.size), other.data.ptr, other.data.size); + void String::copy(const String &other) + { + if (other.isOnStack()) { + memcpy(buf, other.buf, len); } -} + else { + memcpy(allocate(other.data.size), other.data.ptr, other.data.size); + } + } -String::String() noexcept { + String::String() noexcept + { buf[0] = '\0'; setLast(); -} + } -String::~String() { - if(!isOnStack()) - delete[] data.ptr; -} // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks) + String::~String() + { + if (!isOnStack()) + delete[] data.ptr; + } // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks) -String::String(const char* in) - : String(in, strlen(in)) {} + String::String(const char *in) : String(in, strlen(in)) {} -String::String(const char* in, size_type in_size) { - memcpy(allocate(in_size), in, in_size); -} + String::String(const char *in, size_type in_size) { memcpy(allocate(in_size), in, in_size); } -String::String(std::istream& in, size_type in_size) { - in.read(allocate(in_size), in_size); -} + String::String(std::istream &in, size_type in_size) { in.read(allocate(in_size), in_size); } -String::String(const String& other) { copy(other); } + String::String(const String &other) { copy(other); } -String& String::operator=(const String& other) { - if(this != &other) { - if(!isOnStack()) - delete[] data.ptr; + String &String::operator=(const String &other) + { + if (this != &other) { + if (!isOnStack()) + delete[] data.ptr; - copy(other); + copy(other); } return *this; -} + } -String& String::operator+=(const String& other) { + String &String::operator+=(const String &other) + { const size_type my_old_size = size(); const size_type other_size = other.size(); const size_type total_size = my_old_size + other_size; - if(isOnStack()) { - if(total_size < len) { - // append to the current stack space - memcpy(buf + my_old_size, other.c_str(), other_size + 1); - // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) - setLast(last - total_size); - } else { - // alloc new chunk - char* temp = new char[total_size + 1]; - // copy current data to new location before writing in the union - memcpy(temp, buf, my_old_size); // skip the +1 ('\0') for speed - // update data in union - setOnHeap(); - data.size = total_size; - data.capacity = data.size + 1; - data.ptr = temp; - // transfer the rest of the data - memcpy(data.ptr + my_old_size, other.c_str(), other_size + 1); - } - } else { - if(data.capacity > total_size) { - // append to the current heap block - data.size = total_size; - memcpy(data.ptr + my_old_size, other.c_str(), other_size + 1); - } else { - // resize - data.capacity *= 2; - if(data.capacity <= total_size) - data.capacity = total_size + 1; - // alloc new chunk - char* temp = new char[data.capacity]; - // copy current data to new location before releasing it - memcpy(temp, data.ptr, my_old_size); // skip the +1 ('\0') for speed - // release old chunk - delete[] data.ptr; - // update the rest of the union members - data.size = total_size; - data.ptr = temp; - // transfer the rest of the data - memcpy(data.ptr + my_old_size, other.c_str(), other_size + 1); - } + if (isOnStack()) { + if (total_size < len) { + // append to the current stack space + memcpy(buf + my_old_size, other.c_str(), other_size + 1); + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) + setLast(last - total_size); + } + else { + // alloc new chunk + char *temp = new char[total_size + 1]; + // copy current data to new location before writing in the union + memcpy(temp, buf, my_old_size); // skip the +1 ('\0') for speed + // update data in union + setOnHeap(); + data.size = total_size; + data.capacity = data.size + 1; + data.ptr = temp; + // transfer the rest of the data + memcpy(data.ptr + my_old_size, other.c_str(), other_size + 1); + } + } + else { + if (data.capacity > total_size) { + // append to the current heap block + data.size = total_size; + memcpy(data.ptr + my_old_size, other.c_str(), other_size + 1); + } + else { + // resize + data.capacity *= 2; + if (data.capacity <= total_size) + data.capacity = total_size + 1; + // alloc new chunk + char *temp = new char[data.capacity]; + // copy current data to new location before releasing it + memcpy(temp, data.ptr, my_old_size); // skip the +1 ('\0') for speed + // release old chunk + delete[] data.ptr; + // update the rest of the union members + data.size = total_size; + data.ptr = temp; + // transfer the rest of the data + memcpy(data.ptr + my_old_size, other.c_str(), other_size + 1); + } } return *this; -} + } -String::String(String&& other) noexcept { + String::String(String &&other) noexcept + { memcpy(buf, other.buf, len); other.buf[0] = '\0'; other.setLast(); -} + } -String& String::operator=(String&& other) noexcept { - if(this != &other) { - if(!isOnStack()) - delete[] data.ptr; - memcpy(buf, other.buf, len); - other.buf[0] = '\0'; - other.setLast(); + String &String::operator=(String &&other) noexcept + { + if (this != &other) { + if (!isOnStack()) + delete[] data.ptr; + memcpy(buf, other.buf, len); + other.buf[0] = '\0'; + other.setLast(); } return *this; -} + } -char String::operator[](size_type i) const { - return const_cast(this)->operator[](i); -} + char String::operator[](size_type i) const { return const_cast(this)->operator[](i); } -char& String::operator[](size_type i) { - if(isOnStack()) - return reinterpret_cast(buf)[i]; + char &String::operator[](size_type i) + { + if (isOnStack()) + return reinterpret_cast(buf)[i]; return data.ptr[i]; -} + } -DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wmaybe-uninitialized") -String::size_type String::size() const { - if(isOnStack()) - return last - (size_type(buf[last]) & 31); // using "last" would work only if "len" is 32 + DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wmaybe-uninitialized") + String::size_type String::size() const + { + if (isOnStack()) + return last - (size_type(buf[last]) & 31); // using "last" would work only if "len" is 32 return data.size; -} -DOCTEST_GCC_SUPPRESS_WARNING_POP + } + DOCTEST_GCC_SUPPRESS_WARNING_POP -String::size_type String::capacity() const { - if(isOnStack()) - return len; + String::size_type String::capacity() const + { + if (isOnStack()) + return len; return data.capacity; -} + } -String String::substr(size_type pos, size_type cnt) && { - cnt = std::min(cnt, size() - 1 - pos); - char* cptr = c_str(); + String String::substr(size_type pos, size_type cnt) && + { + cnt = std::min(cnt, size() - 1 - pos); + char *cptr = c_str(); memmove(cptr, cptr + pos, cnt); setSize(cnt); return std::move(*this); -} + } -String String::substr(size_type pos, size_type cnt) const & { + String String::substr(size_type pos, size_type cnt) const & + { cnt = std::min(cnt, size() - 1 - pos); - return String{ c_str() + pos, cnt }; -} - -String::size_type String::find(char ch, size_type pos) const { - const char* begin = c_str(); - const char* end = begin + size(); - const char* it = begin + pos; - for (; it < end && *it != ch; it++); - if (it < end) { return static_cast(it - begin); } - else { return npos; } -} - -String::size_type String::rfind(char ch, size_type pos) const { - const char* begin = c_str(); - const char* it = begin + std::min(pos, size() - 1); - for (; it >= begin && *it != ch; it--); - if (it >= begin) { return static_cast(it - begin); } - else { return npos; } -} + return String{c_str() + pos, cnt}; + } + + String::size_type String::find(char ch, size_type pos) const + { + const char *begin = c_str(); + const char *end = begin + size(); + const char *it = begin + pos; + for (; it < end && *it != ch; it++) + ; + if (it < end) { + return static_cast(it - begin); + } + else { + return npos; + } + } + + String::size_type String::rfind(char ch, size_type pos) const + { + const char *begin = c_str(); + const char *it = begin + std::min(pos, size() - 1); + for (; it >= begin && *it != ch; it--) + ; + if (it >= begin) { + return static_cast(it - begin); + } + else { + return npos; + } + } -int String::compare(const char* other, bool no_case) const { - if(no_case) - return doctest::stricmp(c_str(), other); + int String::compare(const char *other, bool no_case) const + { + if (no_case) + return doctest::stricmp(c_str(), other); return std::strcmp(c_str(), other); -} + } -int String::compare(const String& other, bool no_case) const { + int String::compare(const String &other, bool no_case) const + { return compare(other.c_str(), no_case); -} + } -String operator+(const String& lhs, const String& rhs) { return String(lhs) += rhs; } + String operator+(const String &lhs, const String &rhs) { return String(lhs) += rhs; } -bool operator==(const String& lhs, const String& rhs) { return lhs.compare(rhs) == 0; } -bool operator!=(const String& lhs, const String& rhs) { return lhs.compare(rhs) != 0; } -bool operator< (const String& lhs, const String& rhs) { return lhs.compare(rhs) < 0; } -bool operator> (const String& lhs, const String& rhs) { return lhs.compare(rhs) > 0; } -bool operator<=(const String& lhs, const String& rhs) { return (lhs != rhs) ? lhs.compare(rhs) < 0 : true; } -bool operator>=(const String& lhs, const String& rhs) { return (lhs != rhs) ? lhs.compare(rhs) > 0 : true; } + bool operator==(const String &lhs, const String &rhs) { return lhs.compare(rhs) == 0; } + bool operator!=(const String &lhs, const String &rhs) { return lhs.compare(rhs) != 0; } + bool operator<(const String &lhs, const String &rhs) { return lhs.compare(rhs) < 0; } + bool operator>(const String &lhs, const String &rhs) { return lhs.compare(rhs) > 0; } + bool operator<=(const String &lhs, const String &rhs) + { + return (lhs != rhs) ? lhs.compare(rhs) < 0 : true; + } + bool operator>=(const String &lhs, const String &rhs) + { + return (lhs != rhs) ? lhs.compare(rhs) > 0 : true; + } -std::ostream& operator<<(std::ostream& s, const String& in) { return s << in.c_str(); } + std::ostream &operator<<(std::ostream &s, const String &in) { return s << in.c_str(); } -Contains::Contains(const String& str) : string(str) { } + Contains::Contains(const String &str) : string(str) {} -bool Contains::checkWith(const String& other) const { + bool Contains::checkWith(const String &other) const + { return strstr(other.c_str(), string.c_str()) != nullptr; -} + } -String toString(const Contains& in) { - return "Contains( " + in.string + " )"; -} + String toString(const Contains &in) { return "Contains( " + in.string + " )"; } -bool operator==(const String& lhs, const Contains& rhs) { return rhs.checkWith(lhs); } -bool operator==(const Contains& lhs, const String& rhs) { return lhs.checkWith(rhs); } -bool operator!=(const String& lhs, const Contains& rhs) { return !rhs.checkWith(lhs); } -bool operator!=(const Contains& lhs, const String& rhs) { return !lhs.checkWith(rhs); } + bool operator==(const String &lhs, const Contains &rhs) { return rhs.checkWith(lhs); } + bool operator==(const Contains &lhs, const String &rhs) { return lhs.checkWith(rhs); } + bool operator!=(const String &lhs, const Contains &rhs) { return !rhs.checkWith(lhs); } + bool operator!=(const Contains &lhs, const String &rhs) { return !lhs.checkWith(rhs); } -namespace { - void color_to_stream(std::ostream&, Color::Enum) DOCTEST_BRANCH_ON_DISABLED({}, ;) -} // namespace + namespace { + void color_to_stream(std::ostream &, Color::Enum) DOCTEST_BRANCH_ON_DISABLED({}, ;) + } // namespace -namespace Color { - std::ostream& operator<<(std::ostream& s, Color::Enum code) { - color_to_stream(s, code); - return s; + namespace Color { + std::ostream &operator<<(std::ostream &s, Color::Enum code) + { + color_to_stream(s, code); + return s; } -} // namespace Color + } // namespace Color -// clang-format off + // clang-format off const char* assertString(assertType::Enum at) { DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4061) // enum 'x' in switch of enum 'y' is not explicitly handled #define DOCTEST_GENERATE_ASSERT_TYPE_CASE(assert_type) case assertType::DT_ ## assert_type: return #assert_type @@ -3866,181 +4222,191 @@ const char* assertString(assertType::Enum at) { } DOCTEST_MSVC_SUPPRESS_WARNING_POP } -// clang-format on - -const char* failureString(assertType::Enum at) { - if(at & assertType::is_warn) //!OCLINT bitwise operator in conditional - return "WARNING"; - if(at & assertType::is_check) //!OCLINT bitwise operator in conditional - return "ERROR"; - if(at & assertType::is_require) //!OCLINT bitwise operator in conditional - return "FATAL ERROR"; + // clang-format on + + const char *failureString(assertType::Enum at) + { + if (at & assertType::is_warn) //! OCLINT bitwise operator in conditional + return "WARNING"; + if (at & assertType::is_check) //! OCLINT bitwise operator in conditional + return "ERROR"; + if (at & assertType::is_require) //! OCLINT bitwise operator in conditional + return "FATAL ERROR"; return ""; -} + } -DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wnull-dereference") -DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wnull-dereference") -// depending on the current options this will remove the path of filenames -const char* skipPathFromFilename(const char* file) { + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wnull-dereference") + DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wnull-dereference") + // depending on the current options this will remove the path of filenames + const char *skipPathFromFilename(const char *file) + { #ifndef DOCTEST_CONFIG_DISABLE - if(getContextOptions()->no_path_in_filenames) { - auto back = std::strrchr(file, '\\'); - auto forward = std::strrchr(file, '/'); - if(back || forward) { - if(back > forward) - forward = back; - return forward + 1; - } + if (getContextOptions()->no_path_in_filenames) { + auto back = std::strrchr(file, '\\'); + auto forward = std::strrchr(file, '/'); + if (back || forward) { + if (back > forward) + forward = back; + return forward + 1; + } } #endif // DOCTEST_CONFIG_DISABLE return file; -} -DOCTEST_CLANG_SUPPRESS_WARNING_POP -DOCTEST_GCC_SUPPRESS_WARNING_POP - -bool SubcaseSignature::operator==(const SubcaseSignature& other) const { - return m_line == other.m_line - && std::strcmp(m_file, other.m_file) == 0 - && m_name == other.m_name; -} - -bool SubcaseSignature::operator<(const SubcaseSignature& other) const { - if(m_line != other.m_line) - return m_line < other.m_line; - if(std::strcmp(m_file, other.m_file) != 0) - return std::strcmp(m_file, other.m_file) < 0; + } + DOCTEST_CLANG_SUPPRESS_WARNING_POP + DOCTEST_GCC_SUPPRESS_WARNING_POP + + bool SubcaseSignature::operator==(const SubcaseSignature &other) const + { + return m_line == other.m_line && std::strcmp(m_file, other.m_file) == 0 && + m_name == other.m_name; + } + + bool SubcaseSignature::operator<(const SubcaseSignature &other) const + { + if (m_line != other.m_line) + return m_line < other.m_line; + if (std::strcmp(m_file, other.m_file) != 0) + return std::strcmp(m_file, other.m_file) < 0; return m_name.compare(other.m_name) < 0; -} + } -DOCTEST_DEFINE_INTERFACE(IContextScope) + DOCTEST_DEFINE_INTERFACE(IContextScope) -namespace detail { - void filldata::fill(std::ostream* stream, const void* in) { - if (in) { *stream << in; } - else { *stream << "nullptr"; } + namespace detail { + void filldata::fill(std::ostream *stream, const void *in) + { + if (in) { + *stream << in; + } + else { + *stream << "nullptr"; + } } - template - String toStreamLit(T t) { - std::ostream* os = tlssPush(); - os->operator<<(t); - return tlssPop(); + template String toStreamLit(T t) + { + std::ostream *os = tlssPush(); + os->operator<<(t); + return tlssPop(); } -} + } // namespace detail #ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING -String toString(const char* in) { return String("\"") + (in ? in : "{null string}") + "\""; } + String toString(const char *in) { return String("\"") + (in ? in : "{null string}") + "\""; } #endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING #if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0) -// see this issue on why this is needed: https://github.com/doctest/doctest/issues/183 -String toString(const std::string& in) { return in.c_str(); } + // see this issue on why this is needed: https://github.com/doctest/doctest/issues/183 + String toString(const std::string &in) { return in.c_str(); } #endif // VS 2019 -String toString(String in) { return in; } + String toString(String in) { return in; } -String toString(std::nullptr_t) { return "nullptr"; } + String toString(std::nullptr_t) { return "nullptr"; } -String toString(bool in) { return in ? "true" : "false"; } + String toString(bool in) { return in ? "true" : "false"; } -String toString(float in) { return toStreamLit(in); } -String toString(double in) { return toStreamLit(in); } -String toString(double long in) { return toStreamLit(in); } + String toString(float in) { return toStreamLit(in); } + String toString(double in) { return toStreamLit(in); } + String toString(double long in) { return toStreamLit(in); } -String toString(char in) { return toStreamLit(static_cast(in)); } -String toString(char signed in) { return toStreamLit(static_cast(in)); } -String toString(char unsigned in) { return toStreamLit(static_cast(in)); } -String toString(short in) { return toStreamLit(in); } -String toString(short unsigned in) { return toStreamLit(in); } -String toString(signed in) { return toStreamLit(in); } -String toString(unsigned in) { return toStreamLit(in); } -String toString(long in) { return toStreamLit(in); } -String toString(long unsigned in) { return toStreamLit(in); } -String toString(long long in) { return toStreamLit(in); } -String toString(long long unsigned in) { return toStreamLit(in); } + String toString(char in) { return toStreamLit(static_cast(in)); } + String toString(char signed in) { return toStreamLit(static_cast(in)); } + String toString(char unsigned in) { return toStreamLit(static_cast(in)); } + String toString(short in) { return toStreamLit(in); } + String toString(short unsigned in) { return toStreamLit(in); } + String toString(signed in) { return toStreamLit(in); } + String toString(unsigned in) { return toStreamLit(in); } + String toString(long in) { return toStreamLit(in); } + String toString(long unsigned in) { return toStreamLit(in); } + String toString(long long in) { return toStreamLit(in); } + String toString(long long unsigned in) { return toStreamLit(in); } -Approx::Approx(double value) - : m_epsilon(static_cast(std::numeric_limits::epsilon()) * 100) - , m_scale(1.0) - , m_value(value) {} + Approx::Approx(double value) + : m_epsilon(static_cast(std::numeric_limits::epsilon()) * 100), m_scale(1.0), + m_value(value) + { + } -Approx Approx::operator()(double value) const { + Approx Approx::operator()(double value) const + { Approx approx(value); approx.epsilon(m_epsilon); approx.scale(m_scale); return approx; -} + } -Approx& Approx::epsilon(double newEpsilon) { + Approx &Approx::epsilon(double newEpsilon) + { m_epsilon = newEpsilon; return *this; -} -Approx& Approx::scale(double newScale) { + } + Approx &Approx::scale(double newScale) + { m_scale = newScale; return *this; -} + } -bool operator==(double lhs, const Approx& rhs) { + bool operator==(double lhs, const Approx &rhs) + { // Thanks to Richard Harris for his help refining this formula return std::fabs(lhs - rhs.m_value) < rhs.m_epsilon * (rhs.m_scale + std::max(std::fabs(lhs), std::fabs(rhs.m_value))); -} -bool operator==(const Approx& lhs, double rhs) { return operator==(rhs, lhs); } -bool operator!=(double lhs, const Approx& rhs) { return !operator==(lhs, rhs); } -bool operator!=(const Approx& lhs, double rhs) { return !operator==(rhs, lhs); } -bool operator<=(double lhs, const Approx& rhs) { return lhs < rhs.m_value || lhs == rhs; } -bool operator<=(const Approx& lhs, double rhs) { return lhs.m_value < rhs || lhs == rhs; } -bool operator>=(double lhs, const Approx& rhs) { return lhs > rhs.m_value || lhs == rhs; } -bool operator>=(const Approx& lhs, double rhs) { return lhs.m_value > rhs || lhs == rhs; } -bool operator<(double lhs, const Approx& rhs) { return lhs < rhs.m_value && lhs != rhs; } -bool operator<(const Approx& lhs, double rhs) { return lhs.m_value < rhs && lhs != rhs; } -bool operator>(double lhs, const Approx& rhs) { return lhs > rhs.m_value && lhs != rhs; } -bool operator>(const Approx& lhs, double rhs) { return lhs.m_value > rhs && lhs != rhs; } - -String toString(const Approx& in) { - return "Approx( " + doctest::toString(in.m_value) + " )"; -} -const ContextOptions* getContextOptions() { return DOCTEST_BRANCH_ON_DISABLED(nullptr, g_cs); } - -DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4738) -template -IsNaN::operator bool() const { - return std::isnan(value) ^ flipped; -} -DOCTEST_MSVC_SUPPRESS_WARNING_POP -template struct DOCTEST_INTERFACE_DEF IsNaN; -template struct DOCTEST_INTERFACE_DEF IsNaN; -template struct DOCTEST_INTERFACE_DEF IsNaN; -template -String toString(IsNaN in) { return String(in.flipped ? "! " : "") + "IsNaN( " + doctest::toString(in.value) + " )"; } -String toString(IsNaN in) { return toString(in); } -String toString(IsNaN in) { return toString(in); } -String toString(IsNaN in) { return toString(in); } + } + bool operator==(const Approx &lhs, double rhs) { return operator==(rhs, lhs); } + bool operator!=(double lhs, const Approx &rhs) { return !operator==(lhs, rhs); } + bool operator!=(const Approx &lhs, double rhs) { return !operator==(rhs, lhs); } + bool operator<=(double lhs, const Approx &rhs) { return lhs < rhs.m_value || lhs == rhs; } + bool operator<=(const Approx &lhs, double rhs) { return lhs.m_value < rhs || lhs == rhs; } + bool operator>=(double lhs, const Approx &rhs) { return lhs > rhs.m_value || lhs == rhs; } + bool operator>=(const Approx &lhs, double rhs) { return lhs.m_value > rhs || lhs == rhs; } + bool operator<(double lhs, const Approx &rhs) { return lhs < rhs.m_value && lhs != rhs; } + bool operator<(const Approx &lhs, double rhs) { return lhs.m_value < rhs && lhs != rhs; } + bool operator>(double lhs, const Approx &rhs) { return lhs > rhs.m_value && lhs != rhs; } + bool operator>(const Approx &lhs, double rhs) { return lhs.m_value > rhs && lhs != rhs; } + + String toString(const Approx &in) { return "Approx( " + doctest::toString(in.m_value) + " )"; } + const ContextOptions *getContextOptions() { return DOCTEST_BRANCH_ON_DISABLED(nullptr, g_cs); } + + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4738) + template IsNaN::operator bool() const { return std::isnan(value) ^ flipped; } + DOCTEST_MSVC_SUPPRESS_WARNING_POP + template struct DOCTEST_INTERFACE_DEF IsNaN; + template struct DOCTEST_INTERFACE_DEF IsNaN; + template struct DOCTEST_INTERFACE_DEF IsNaN; + template String toString(IsNaN in) + { + return String(in.flipped ? "! " : "") + "IsNaN( " + doctest::toString(in.value) + " )"; + } + String toString(IsNaN in) { return toString(in); } + String toString(IsNaN in) { return toString(in); } + String toString(IsNaN in) { return toString(in); } } // namespace doctest #ifdef DOCTEST_CONFIG_DISABLE namespace doctest { -Context::Context(int, const char* const*) {} -Context::~Context() = default; -void Context::applyCommandLine(int, const char* const*) {} -void Context::addFilter(const char*, const char*) {} -void Context::clearFilters() {} -void Context::setOption(const char*, bool) {} -void Context::setOption(const char*, int) {} -void Context::setOption(const char*, const char*) {} -bool Context::shouldExit() { return false; } -void Context::setAsDefaultForAssertsOutOfTestCases() {} -void Context::setAssertHandler(detail::assert_handler) {} -void Context::setCout(std::ostream*) {} -int Context::run() { return 0; } - -int IReporter::get_num_active_contexts() { return 0; } -const IContextScope* const* IReporter::get_active_contexts() { return nullptr; } -int IReporter::get_num_stringified_contexts() { return 0; } -const String* IReporter::get_stringified_contexts() { return nullptr; } - -int registerReporter(const char*, int, IReporter*) { return 0; } + Context::Context(int, const char *const *) {} + Context::~Context() = default; + void Context::applyCommandLine(int, const char *const *) {} + void Context::addFilter(const char *, const char *) {} + void Context::clearFilters() {} + void Context::setOption(const char *, bool) {} + void Context::setOption(const char *, int) {} + void Context::setOption(const char *, const char *) {} + bool Context::shouldExit() { return false; } + void Context::setAsDefaultForAssertsOutOfTestCases() {} + void Context::setAssertHandler(detail::assert_handler) {} + void Context::setCout(std::ostream *) {} + int Context::run() { return 0; } + + int IReporter::get_num_active_contexts() { return 0; } + const IContextScope *const *IReporter::get_active_contexts() { return nullptr; } + int IReporter::get_num_stringified_contexts() { return 0; } + const String *IReporter::get_stringified_contexts() { return nullptr; } + + int registerReporter(const char *, int, IReporter *) { return 0; } } // namespace doctest #else // DOCTEST_CONFIG_DISABLE @@ -4056,220 +4422,244 @@ int registerReporter(const char*, int, IReporter*) { return 0; } #endif // DOCTEST_CONFIG_COLORS_NONE namespace doctest_detail_test_suite_ns { -// holds the current test suite -doctest::detail::TestSuite& getCurrentTestSuite() { + // holds the current test suite + doctest::detail::TestSuite &getCurrentTestSuite() + { static doctest::detail::TestSuite data{}; return data; -} + } } // namespace doctest_detail_test_suite_ns namespace doctest { -namespace { + namespace { // the int (priority) is part of the key for automatic sorting - sadly one can register a - // reporter with a duplicate name and a different priority but hopefully that won't happen often :| + // reporter with a duplicate name and a different priority but hopefully that won't happen often + // :| using reporterMap = std::map, reporterCreatorFunc>; - reporterMap& getReporters() { - static reporterMap data; - return data; + reporterMap &getReporters() + { + static reporterMap data; + return data; } - reporterMap& getListeners() { - static reporterMap data; - return data; + reporterMap &getListeners() + { + static reporterMap data; + return data; } -} // namespace -namespace detail { + } // namespace + namespace detail { #define DOCTEST_ITERATE_THROUGH_REPORTERS(function, ...) \ - for(auto& curr_rep : g_cs->reporters_currently_used) \ - curr_rep->function(__VA_ARGS__) + for (auto &curr_rep : g_cs->reporters_currently_used) \ + curr_rep->function(__VA_ARGS__) - bool checkIfShouldThrow(assertType::Enum at) { - if(at & assertType::is_require) //!OCLINT bitwise operator in conditional - return true; + bool checkIfShouldThrow(assertType::Enum at) + { + if (at & assertType::is_require) //! OCLINT bitwise operator in conditional + return true; - if((at & assertType::is_check) //!OCLINT bitwise operator in conditional - && getContextOptions()->abort_after > 0 && - (g_cs->numAssertsFailed + g_cs->numAssertsFailedCurrentTest_atomic) >= - getContextOptions()->abort_after) - return true; + if ((at & assertType::is_check) //! OCLINT bitwise operator in conditional + && getContextOptions()->abort_after > 0 && + (g_cs->numAssertsFailed + g_cs->numAssertsFailedCurrentTest_atomic) >= + getContextOptions()->abort_after) + return true; - return false; + return false; } #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS - DOCTEST_NORETURN void throwException() { - g_cs->shouldLogCurrentException = false; - throw TestFailureException(); // NOLINT(hicpp-exception-baseclass) + DOCTEST_NORETURN void throwException() + { + g_cs->shouldLogCurrentException = false; + throw TestFailureException(); // NOLINT(hicpp-exception-baseclass) } -#else // DOCTEST_CONFIG_NO_EXCEPTIONS +#else // DOCTEST_CONFIG_NO_EXCEPTIONS void throwException() {} #endif // DOCTEST_CONFIG_NO_EXCEPTIONS -} // namespace detail + } // namespace detail -namespace { + namespace { using namespace detail; // matching of a string against a wildcard mask (case sensitivity configurable) taken from // https://www.codeproject.com/Articles/1088/Wildcard-string-compare-globbing - int wildcmp(const char* str, const char* wild, bool caseSensitive) { - const char* cp = str; - const char* mp = wild; - - while((*str) && (*wild != '*')) { - if((caseSensitive ? (*wild != *str) : (tolower(*wild) != tolower(*str))) && - (*wild != '?')) { - return 0; - } - wild++; - str++; + int wildcmp(const char *str, const char *wild, bool caseSensitive) + { + const char *cp = str; + const char *mp = wild; + + while ((*str) && (*wild != '*')) { + if ((caseSensitive ? (*wild != *str) : (tolower(*wild) != tolower(*str))) && + (*wild != '?')) { + return 0; + } + wild++; + str++; + } + + while (*str) { + if (*wild == '*') { + if (!*++wild) { + return 1; + } + mp = wild; + cp = str + 1; + } + else if ((caseSensitive ? (*wild == *str) : (tolower(*wild) == tolower(*str))) || + (*wild == '?')) { + wild++; + str++; } - - while(*str) { - if(*wild == '*') { - if(!*++wild) { - return 1; - } - mp = wild; - cp = str + 1; - } else if((caseSensitive ? (*wild == *str) : (tolower(*wild) == tolower(*str))) || - (*wild == '?')) { - wild++; - str++; - } else { - wild = mp; //!OCLINT parameter reassignment - str = cp++; //!OCLINT parameter reassignment - } + else { + wild = mp; //! OCLINT parameter reassignment + str = cp++; //! OCLINT parameter reassignment } + } - while(*wild == '*') { - wild++; - } - return !*wild; + while (*wild == '*') { + wild++; + } + return !*wild; } // checks if the name matches any of the filters (and can be configured what to do when empty) - bool matchesAny(const char* name, const std::vector& filters, bool matchEmpty, - bool caseSensitive) { - if (filters.empty() && matchEmpty) - return true; - for (auto& curr : filters) - if (wildcmp(name, curr.c_str(), caseSensitive)) - return true; - return false; + bool matchesAny(const char *name, const std::vector &filters, bool matchEmpty, + bool caseSensitive) + { + if (filters.empty() && matchEmpty) + return true; + for (auto &curr : filters) + if (wildcmp(name, curr.c_str(), caseSensitive)) + return true; + return false; } DOCTEST_NO_SANITIZE_INTEGER - unsigned long long hash(unsigned long long a, unsigned long long b) { - return (a << 5) + b; - } + unsigned long long hash(unsigned long long a, unsigned long long b) { return (a << 5) + b; } // C string hash function (djb2) - taken from http://www.cse.yorku.ca/~oz/hash.html DOCTEST_NO_SANITIZE_INTEGER - unsigned long long hash(const char* str) { - unsigned long long hash = 5381; - char c; - while ((c = *str++)) - hash = ((hash << 5) + hash) + c; // hash * 33 + c - return hash; + unsigned long long hash(const char *str) + { + unsigned long long hash = 5381; + char c; + while ((c = *str++)) + hash = ((hash << 5) + hash) + c; // hash * 33 + c + return hash; } - unsigned long long hash(const SubcaseSignature& sig) { - return hash(hash(hash(sig.m_file), hash(sig.m_name.c_str())), sig.m_line); + unsigned long long hash(const SubcaseSignature &sig) + { + return hash(hash(hash(sig.m_file), hash(sig.m_name.c_str())), sig.m_line); } - unsigned long long hash(const std::vector& sigs, size_t count) { - unsigned long long running = 0; - auto end = sigs.begin() + count; - for (auto it = sigs.begin(); it != end; it++) { - running = hash(running, hash(*it)); - } - return running; + unsigned long long hash(const std::vector &sigs, size_t count) + { + unsigned long long running = 0; + auto end = sigs.begin() + count; + for (auto it = sigs.begin(); it != end; it++) { + running = hash(running, hash(*it)); + } + return running; } - unsigned long long hash(const std::vector& sigs) { - unsigned long long running = 0; - for (const SubcaseSignature& sig : sigs) { - running = hash(running, hash(sig)); - } - return running; + unsigned long long hash(const std::vector &sigs) + { + unsigned long long running = 0; + for (const SubcaseSignature &sig : sigs) { + running = hash(running, hash(sig)); + } + return running; } -} // namespace -namespace detail { - bool Subcase::checkFilters() { - if (g_cs->subcaseStack.size() < size_t(g_cs->subcase_filter_levels)) { - if (!matchesAny(m_signature.m_name.c_str(), g_cs->filters[6], true, g_cs->case_sensitive)) - return true; - if (matchesAny(m_signature.m_name.c_str(), g_cs->filters[7], false, g_cs->case_sensitive)) - return true; - } - return false; + } // namespace + namespace detail { + bool Subcase::checkFilters() + { + if (g_cs->subcaseStack.size() < size_t(g_cs->subcase_filter_levels)) { + if (!matchesAny(m_signature.m_name.c_str(), g_cs->filters[6], true, g_cs->case_sensitive)) + return true; + if (matchesAny(m_signature.m_name.c_str(), g_cs->filters[7], false, g_cs->case_sensitive)) + return true; + } + return false; } - Subcase::Subcase(const String& name, const char* file, int line) - : m_signature({name, file, line}) { - if (!g_cs->reachedLeaf) { - if (g_cs->nextSubcaseStack.size() <= g_cs->subcaseStack.size() - || g_cs->nextSubcaseStack[g_cs->subcaseStack.size()] == m_signature) { - // Going down. - if (checkFilters()) { return; } - - g_cs->subcaseStack.push_back(m_signature); - g_cs->currentSubcaseDepth++; - m_entered = true; - DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_start, m_signature); - } - } else { - if (g_cs->subcaseStack[g_cs->currentSubcaseDepth] == m_signature) { - // This subcase is reentered via control flow. - g_cs->currentSubcaseDepth++; - m_entered = true; - DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_start, m_signature); - } else if (g_cs->nextSubcaseStack.size() <= g_cs->currentSubcaseDepth - && g_cs->fullyTraversedSubcases.find(hash(hash(g_cs->subcaseStack, g_cs->currentSubcaseDepth), hash(m_signature))) - == g_cs->fullyTraversedSubcases.end()) { - if (checkFilters()) { return; } - // This subcase is part of the one to be executed next. - g_cs->nextSubcaseStack.clear(); - g_cs->nextSubcaseStack.insert(g_cs->nextSubcaseStack.end(), - g_cs->subcaseStack.begin(), g_cs->subcaseStack.begin() + g_cs->currentSubcaseDepth); - g_cs->nextSubcaseStack.push_back(m_signature); - } - } + Subcase::Subcase(const String &name, const char *file, int line) + : m_signature({name, file, line}) + { + if (!g_cs->reachedLeaf) { + if (g_cs->nextSubcaseStack.size() <= g_cs->subcaseStack.size() || + g_cs->nextSubcaseStack[g_cs->subcaseStack.size()] == m_signature) { + // Going down. + if (checkFilters()) { + return; + } + + g_cs->subcaseStack.push_back(m_signature); + g_cs->currentSubcaseDepth++; + m_entered = true; + DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_start, m_signature); + } + } + else { + if (g_cs->subcaseStack[g_cs->currentSubcaseDepth] == m_signature) { + // This subcase is reentered via control flow. + g_cs->currentSubcaseDepth++; + m_entered = true; + DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_start, m_signature); + } + else if (g_cs->nextSubcaseStack.size() <= g_cs->currentSubcaseDepth && + g_cs->fullyTraversedSubcases.find(hash( + hash(g_cs->subcaseStack, g_cs->currentSubcaseDepth), hash(m_signature))) == + g_cs->fullyTraversedSubcases.end()) { + if (checkFilters()) { + return; + } + // This subcase is part of the one to be executed next. + g_cs->nextSubcaseStack.clear(); + g_cs->nextSubcaseStack.insert(g_cs->nextSubcaseStack.end(), g_cs->subcaseStack.begin(), + g_cs->subcaseStack.begin() + g_cs->currentSubcaseDepth); + g_cs->nextSubcaseStack.push_back(m_signature); + } + } } DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4996) // std::uncaught_exception is deprecated in C++17 DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") - Subcase::~Subcase() { - if (m_entered) { - g_cs->currentSubcaseDepth--; - - if (!g_cs->reachedLeaf) { - // Leaf. - g_cs->fullyTraversedSubcases.insert(hash(g_cs->subcaseStack)); - g_cs->nextSubcaseStack.clear(); - g_cs->reachedLeaf = true; - } else if (g_cs->nextSubcaseStack.empty()) { - // All children are finished. - g_cs->fullyTraversedSubcases.insert(hash(g_cs->subcaseStack)); - } + Subcase::~Subcase() + { + if (m_entered) { + g_cs->currentSubcaseDepth--; + + if (!g_cs->reachedLeaf) { + // Leaf. + g_cs->fullyTraversedSubcases.insert(hash(g_cs->subcaseStack)); + g_cs->nextSubcaseStack.clear(); + g_cs->reachedLeaf = true; + } + else if (g_cs->nextSubcaseStack.empty()) { + // All children are finished. + g_cs->fullyTraversedSubcases.insert(hash(g_cs->subcaseStack)); + } -#if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200) - if(std::uncaught_exceptions() > 0 +#if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L && \ + (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200) + if (std::uncaught_exceptions() > 0 #else - if(std::uncaught_exception() + if (std::uncaught_exception() #endif - && g_cs->shouldLogCurrentException) { - DOCTEST_ITERATE_THROUGH_REPORTERS( - test_case_exception, {"exception thrown in subcase - will translate later " - "when the whole test case has been exited (cannot " - "translate while there is an active exception)", - false}); - g_cs->shouldLogCurrentException = false; - } - - DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_end, DOCTEST_EMPTY); + && g_cs->shouldLogCurrentException) { + DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_exception, + {"exception thrown in subcase - will translate later " + "when the whole test case has been exited (cannot " + "translate while there is an active exception)", + false}); + g_cs->shouldLogCurrentException = false; } + + DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_end, DOCTEST_EMPTY); + } } DOCTEST_CLANG_SUPPRESS_WARNING_POP @@ -4278,128 +4668,135 @@ namespace detail { Subcase::operator bool() const { return m_entered; } - Result::Result(bool passed, const String& decomposition) - : m_passed(passed) - , m_decomp(decomposition) {} - - ExpressionDecomposer::ExpressionDecomposer(assertType::Enum at) - : m_at(at) {} - - TestSuite& TestSuite::operator*(const char* in) { - m_test_suite = in; - return *this; + Result::Result(bool passed, const String &decomposition) + : m_passed(passed), m_decomp(decomposition) + { } - TestCase::TestCase(funcType test, const char* file, unsigned line, const TestSuite& test_suite, - const String& type, int template_id) { - m_file = file; - m_line = line; - m_name = nullptr; // will be later overridden in operator* - m_test_suite = test_suite.m_test_suite; - m_description = test_suite.m_description; - m_skip = test_suite.m_skip; - m_no_breaks = test_suite.m_no_breaks; - m_no_output = test_suite.m_no_output; - m_may_fail = test_suite.m_may_fail; - m_should_fail = test_suite.m_should_fail; - m_expected_failures = test_suite.m_expected_failures; - m_timeout = test_suite.m_timeout; + ExpressionDecomposer::ExpressionDecomposer(assertType::Enum at) : m_at(at) {} - m_test = test; - m_type = type; - m_template_id = template_id; + TestSuite &TestSuite::operator*(const char *in) + { + m_test_suite = in; + return *this; } - TestCase::TestCase(const TestCase& other) - : TestCaseData() { - *this = other; + TestCase::TestCase(funcType test, const char *file, unsigned line, const TestSuite &test_suite, + const String &type, int template_id) + { + m_file = file; + m_line = line; + m_name = nullptr; // will be later overridden in operator* + m_test_suite = test_suite.m_test_suite; + m_description = test_suite.m_description; + m_skip = test_suite.m_skip; + m_no_breaks = test_suite.m_no_breaks; + m_no_output = test_suite.m_no_output; + m_may_fail = test_suite.m_may_fail; + m_should_fail = test_suite.m_should_fail; + m_expected_failures = test_suite.m_expected_failures; + m_timeout = test_suite.m_timeout; + + m_test = test; + m_type = type; + m_template_id = template_id; } + TestCase::TestCase(const TestCase &other) : TestCaseData() { *this = other; } + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(26434) // hides a non-virtual function - TestCase& TestCase::operator=(const TestCase& other) { - TestCaseData::operator=(other); - m_test = other.m_test; - m_type = other.m_type; - m_template_id = other.m_template_id; - m_full_name = other.m_full_name; - - if(m_template_id != -1) - m_name = m_full_name.c_str(); - return *this; + TestCase &TestCase::operator=(const TestCase &other) + { + TestCaseData::operator=(other); + m_test = other.m_test; + m_type = other.m_type; + m_template_id = other.m_template_id; + m_full_name = other.m_full_name; + + if (m_template_id != -1) + m_name = m_full_name.c_str(); + return *this; } DOCTEST_MSVC_SUPPRESS_WARNING_POP - TestCase& TestCase::operator*(const char* in) { - m_name = in; - // make a new name with an appended type for templated test case - if(m_template_id != -1) { - m_full_name = String(m_name) + "<" + m_type + ">"; - // redirect the name to point to the newly constructed full name - m_name = m_full_name.c_str(); - } - return *this; + TestCase &TestCase::operator*(const char *in) + { + m_name = in; + // make a new name with an appended type for templated test case + if (m_template_id != -1) { + m_full_name = String(m_name) + "<" + m_type + ">"; + // redirect the name to point to the newly constructed full name + m_name = m_full_name.c_str(); + } + return *this; } - bool TestCase::operator<(const TestCase& other) const { - // this will be used only to differentiate between test cases - not relevant for sorting - if(m_line != other.m_line) - return m_line < other.m_line; - const int name_cmp = strcmp(m_name, other.m_name); - if(name_cmp != 0) - return name_cmp < 0; - const int file_cmp = m_file.compare(other.m_file); - if(file_cmp != 0) - return file_cmp < 0; - return m_template_id < other.m_template_id; + bool TestCase::operator<(const TestCase &other) const + { + // this will be used only to differentiate between test cases - not relevant for sorting + if (m_line != other.m_line) + return m_line < other.m_line; + const int name_cmp = strcmp(m_name, other.m_name); + if (name_cmp != 0) + return name_cmp < 0; + const int file_cmp = m_file.compare(other.m_file); + if (file_cmp != 0) + return file_cmp < 0; + return m_template_id < other.m_template_id; } // all the registered tests - std::set& getRegisteredTests() { - static std::set data; - return data; + std::set &getRegisteredTests() + { + static std::set data; + return data; } -} // namespace detail -namespace { + } // namespace detail + namespace { using namespace detail; // for sorting tests by file/line - bool fileOrderComparator(const TestCase* lhs, const TestCase* rhs) { - // this is needed because MSVC gives different case for drive letters - // for __FILE__ when evaluated in a header and a source file - const int res = lhs->m_file.compare(rhs->m_file, bool(DOCTEST_MSVC)); - if(res != 0) - return res < 0; - if(lhs->m_line != rhs->m_line) - return lhs->m_line < rhs->m_line; - return lhs->m_template_id < rhs->m_template_id; + bool fileOrderComparator(const TestCase *lhs, const TestCase *rhs) + { + // this is needed because MSVC gives different case for drive letters + // for __FILE__ when evaluated in a header and a source file + const int res = lhs->m_file.compare(rhs->m_file, bool(DOCTEST_MSVC)); + if (res != 0) + return res < 0; + if (lhs->m_line != rhs->m_line) + return lhs->m_line < rhs->m_line; + return lhs->m_template_id < rhs->m_template_id; } // for sorting tests by suite/file/line - bool suiteOrderComparator(const TestCase* lhs, const TestCase* rhs) { - const int res = std::strcmp(lhs->m_test_suite, rhs->m_test_suite); - if(res != 0) - return res < 0; - return fileOrderComparator(lhs, rhs); + bool suiteOrderComparator(const TestCase *lhs, const TestCase *rhs) + { + const int res = std::strcmp(lhs->m_test_suite, rhs->m_test_suite); + if (res != 0) + return res < 0; + return fileOrderComparator(lhs, rhs); } // for sorting tests by name/suite/file/line - bool nameOrderComparator(const TestCase* lhs, const TestCase* rhs) { - const int res = std::strcmp(lhs->m_name, rhs->m_name); - if(res != 0) - return res < 0; - return suiteOrderComparator(lhs, rhs); + bool nameOrderComparator(const TestCase *lhs, const TestCase *rhs) + { + const int res = std::strcmp(lhs->m_name, rhs->m_name); + if (res != 0) + return res < 0; + return suiteOrderComparator(lhs, rhs); } DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") - void color_to_stream(std::ostream& s, Color::Enum code) { - static_cast(s); // for DOCTEST_CONFIG_COLORS_NONE or DOCTEST_CONFIG_COLORS_WINDOWS - static_cast(code); // for DOCTEST_CONFIG_COLORS_NONE + void color_to_stream(std::ostream &s, Color::Enum code) + { + static_cast(s); // for DOCTEST_CONFIG_COLORS_NONE or DOCTEST_CONFIG_COLORS_WINDOWS + static_cast(code); // for DOCTEST_CONFIG_COLORS_NONE #ifdef DOCTEST_CONFIG_COLORS_ANSI - if(g_no_colors || - (isatty(STDOUT_FILENO) == false && getContextOptions()->force_colors == false)) - return; + if (g_no_colors || + (isatty(STDOUT_FILENO) == false && getContextOptions()->force_colors == false)) + return; - auto col = ""; - // clang-format off + auto col = ""; + // clang-format off switch(code) { //!OCLINT missing break in switch statement / unnecessary default statement in covered switch statement case Color::Red: col = "[0;31m"; break; case Color::Green: col = "[0;32m"; break; @@ -4416,34 +4813,36 @@ namespace { case Color::White: default: col = "[0m"; } - // clang-format on - s << "\033" << col; + // clang-format on + s << "\033" << col; #endif // DOCTEST_CONFIG_COLORS_ANSI #ifdef DOCTEST_CONFIG_COLORS_WINDOWS - if(g_no_colors || - (_isatty(_fileno(stdout)) == false && getContextOptions()->force_colors == false)) - return; + if (g_no_colors || + (_isatty(_fileno(stdout)) == false && getContextOptions()->force_colors == false)) + return; - static struct ConsoleHelper { - HANDLE stdoutHandle; - WORD origFgAttrs; - WORD origBgAttrs; - - ConsoleHelper() { - stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE); - CONSOLE_SCREEN_BUFFER_INFO csbiInfo; - GetConsoleScreenBufferInfo(stdoutHandle, &csbiInfo); - origFgAttrs = csbiInfo.wAttributes & ~(BACKGROUND_GREEN | BACKGROUND_RED | - BACKGROUND_BLUE | BACKGROUND_INTENSITY); - origBgAttrs = csbiInfo.wAttributes & ~(FOREGROUND_GREEN | FOREGROUND_RED | - FOREGROUND_BLUE | FOREGROUND_INTENSITY); - } - } ch; + static struct ConsoleHelper + { + HANDLE stdoutHandle; + WORD origFgAttrs; + WORD origBgAttrs; + + ConsoleHelper() + { + stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE); + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + GetConsoleScreenBufferInfo(stdoutHandle, &csbiInfo); + origFgAttrs = csbiInfo.wAttributes & ~(BACKGROUND_GREEN | BACKGROUND_RED | + BACKGROUND_BLUE | BACKGROUND_INTENSITY); + origBgAttrs = csbiInfo.wAttributes & ~(FOREGROUND_GREEN | FOREGROUND_RED | + FOREGROUND_BLUE | FOREGROUND_INTENSITY); + } + } ch; #define DOCTEST_SET_ATTR(x) SetConsoleTextAttribute(ch.stdoutHandle, x | ch.origBgAttrs) - // clang-format off + // clang-format off switch (code) { case Color::White: DOCTEST_SET_ATTR(FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE); break; case Color::Red: DOCTEST_SET_ATTR(FOREGROUND_RED); break; @@ -4460,24 +4859,26 @@ namespace { case Color::Bright: // invalid default: DOCTEST_SET_ATTR(ch.origFgAttrs); } - // clang-format on + // clang-format on #endif // DOCTEST_CONFIG_COLORS_WINDOWS } DOCTEST_CLANG_SUPPRESS_WARNING_POP - std::vector& getExceptionTranslators() { - static std::vector data; - return data; + std::vector &getExceptionTranslators() + { + static std::vector data; + return data; } - String translateActiveException() { + String translateActiveException() + { #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS - String res; - auto& translators = getExceptionTranslators(); - for(auto& curr : translators) - if(curr->translate(res)) - return res; - // clang-format off + String res; + auto &translators = getExceptionTranslators(); + for (auto &curr : translators) + if (curr->translate(res)) + return res; + // clang-format off DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wcatch-value") try { throw; @@ -4493,74 +4894,80 @@ namespace { DOCTEST_GCC_SUPPRESS_WARNING_POP // clang-format on #else // DOCTEST_CONFIG_NO_EXCEPTIONS - return ""; + return ""; #endif // DOCTEST_CONFIG_NO_EXCEPTIONS } -} // namespace + } // namespace -namespace detail { + namespace detail { // used by the macros for registering tests - int regTest(const TestCase& tc) { - getRegisteredTests().insert(tc); - return 0; + int regTest(const TestCase &tc) + { + getRegisteredTests().insert(tc); + return 0; } // sets the current test suite - int setTestSuite(const TestSuite& ts) { - doctest_detail_test_suite_ns::getCurrentTestSuite() = ts; - return 0; + int setTestSuite(const TestSuite &ts) + { + doctest_detail_test_suite_ns::getCurrentTestSuite() = ts; + return 0; } #ifdef DOCTEST_IS_DEBUGGER_ACTIVE bool isDebuggerActive() { return DOCTEST_IS_DEBUGGER_ACTIVE(); } #else // DOCTEST_IS_DEBUGGER_ACTIVE #ifdef DOCTEST_PLATFORM_LINUX - class ErrnoGuard { + class ErrnoGuard + { public: - ErrnoGuard() : m_oldErrno(errno) {} - ~ErrnoGuard() { errno = m_oldErrno; } + ErrnoGuard() : m_oldErrno(errno) {} + ~ErrnoGuard() { errno = m_oldErrno; } + private: - int m_oldErrno; + int m_oldErrno; }; // See the comments in Catch2 for the reasoning behind this implementation: // https://github.com/catchorg/Catch2/blob/v2.13.1/include/internal/catch_debugger.cpp#L79-L102 - bool isDebuggerActive() { - ErrnoGuard guard; - std::ifstream in("/proc/self/status"); - for(std::string line; std::getline(in, line);) { - static const int PREFIX_LEN = 11; - if(line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0) { - return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0'; - } - } - return false; + bool isDebuggerActive() + { + ErrnoGuard guard; + std::ifstream in("/proc/self/status"); + for (std::string line; std::getline(in, line);) { + static const int PREFIX_LEN = 11; + if (line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0) { + return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0'; + } + } + return false; } #elif defined(DOCTEST_PLATFORM_MAC) // The following function is taken directly from the following technical note: // https://developer.apple.com/library/archive/qa/qa1361/_index.html // Returns true if the current process is being debugged (either // running under the debugger or has a debugger attached post facto). - bool isDebuggerActive() { - int mib[4]; - kinfo_proc info; - size_t size; - // Initialize the flags so that, if sysctl fails for some bizarre - // reason, we get a predictable result. - info.kp_proc.p_flag = 0; - // Initialize mib, which tells sysctl the info we want, in this case - // we're looking for information about a specific process ID. - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PID; - mib[3] = getpid(); - // Call sysctl. - size = sizeof(info); - if(sysctl(mib, DOCTEST_COUNTOF(mib), &info, &size, 0, 0) != 0) { - std::cerr << "\nCall to sysctl failed - unable to determine if debugger is active **\n"; - return false; - } - // We're being debugged if the P_TRACED flag is set. - return ((info.kp_proc.p_flag & P_TRACED) != 0); + bool isDebuggerActive() + { + int mib[4]; + kinfo_proc info; + size_t size; + // Initialize the flags so that, if sysctl fails for some bizarre + // reason, we get a predictable result. + info.kp_proc.p_flag = 0; + // Initialize mib, which tells sysctl the info we want, in this case + // we're looking for information about a specific process ID. + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PID; + mib[3] = getpid(); + // Call sysctl. + size = sizeof(info); + if (sysctl(mib, DOCTEST_COUNTOF(mib), &info, &size, 0, 0) != 0) { + std::cerr << "\nCall to sysctl failed - unable to determine if debugger is active **\n"; + return false; + } + // We're being debugged if the P_TRACED flag is set. + return ((info.kp_proc.p_flag & P_TRACED) != 0); } #elif DOCTEST_MSVC || defined(__MINGW32__) || defined(__MINGW64__) bool isDebuggerActive() { return ::IsDebuggerPresent() != 0; } @@ -4569,24 +4976,24 @@ namespace detail { #endif // Platform #endif // DOCTEST_IS_DEBUGGER_ACTIVE - void registerExceptionTranslatorImpl(const IExceptionTranslator* et) { - if(std::find(getExceptionTranslators().begin(), getExceptionTranslators().end(), et) == - getExceptionTranslators().end()) - getExceptionTranslators().push_back(et); + void registerExceptionTranslatorImpl(const IExceptionTranslator *et) + { + if (std::find(getExceptionTranslators().begin(), getExceptionTranslators().end(), et) == + getExceptionTranslators().end()) + getExceptionTranslators().push_back(et); } - DOCTEST_THREAD_LOCAL std::vector g_infoContexts; // for logging with INFO() + DOCTEST_THREAD_LOCAL std::vector g_infoContexts; // for logging with INFO() - ContextScopeBase::ContextScopeBase() { - g_infoContexts.push_back(this); - } + ContextScopeBase::ContextScopeBase() { g_infoContexts.push_back(this); } - ContextScopeBase::ContextScopeBase(ContextScopeBase&& other) noexcept { - if (other.need_to_destroy) { - other.destroy(); - } - other.need_to_destroy = false; - g_infoContexts.push_back(this); + ContextScopeBase::ContextScopeBase(ContextScopeBase &&other) noexcept + { + if (other.need_to_destroy) { + other.destroy(); + } + other.need_to_destroy = false; + g_infoContexts.push_back(this); } DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4996) // std::uncaught_exception is deprecated in C++17 @@ -4596,172 +5003,176 @@ namespace detail { // destroy cannot be inlined into the destructor because that would mean calling stringify after // ContextScope has been destroyed (base class destructors run after derived class destructors). // Instead, ContextScope calls this method directly from its destructor. - void ContextScopeBase::destroy() { -#if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200) - if(std::uncaught_exceptions() > 0) { + void ContextScopeBase::destroy() + { +#if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L && \ + (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200) + if (std::uncaught_exceptions() > 0) { #else - if(std::uncaught_exception()) { + if (std::uncaught_exception()) { #endif - std::ostringstream s; - this->stringify(&s); - g_cs->stringifiedContexts.push_back(s.str().c_str()); - } - g_infoContexts.pop_back(); + std::ostringstream s; + this->stringify(&s); + g_cs->stringifiedContexts.push_back(s.str().c_str()); + } + g_infoContexts.pop_back(); } DOCTEST_CLANG_SUPPRESS_WARNING_POP DOCTEST_GCC_SUPPRESS_WARNING_POP DOCTEST_MSVC_SUPPRESS_WARNING_POP -} // namespace detail -namespace { + } // namespace detail + namespace { using namespace detail; #if !defined(DOCTEST_CONFIG_POSIX_SIGNALS) && !defined(DOCTEST_CONFIG_WINDOWS_SEH) struct FatalConditionHandler { - static void reset() {} - static void allocateAltStackMem() {} - static void freeAltStackMem() {} + static void reset() {} + static void allocateAltStackMem() {} + static void freeAltStackMem() {} }; #else // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH - void reportFatal(const std::string&); + void reportFatal(const std::string &); #ifdef DOCTEST_PLATFORM_WINDOWS struct SignalDefs { - DWORD id; - const char* name; + DWORD id; + const char *name; }; // There is no 1-1 mapping between signals and windows exceptions. // Windows can easily distinguish between SO and SigSegV, // but SigInt, SigTerm, etc are handled differently. SignalDefs signalDefs[] = { - {static_cast(EXCEPTION_ILLEGAL_INSTRUCTION), - "SIGILL - Illegal instruction signal"}, - {static_cast(EXCEPTION_STACK_OVERFLOW), "SIGSEGV - Stack overflow"}, - {static_cast(EXCEPTION_ACCESS_VIOLATION), - "SIGSEGV - Segmentation violation signal"}, - {static_cast(EXCEPTION_INT_DIVIDE_BY_ZERO), "Divide by zero error"}, + {static_cast(EXCEPTION_ILLEGAL_INSTRUCTION), "SIGILL - Illegal instruction signal"}, + {static_cast(EXCEPTION_STACK_OVERFLOW), "SIGSEGV - Stack overflow"}, + {static_cast(EXCEPTION_ACCESS_VIOLATION), "SIGSEGV - Segmentation violation signal"}, + {static_cast(EXCEPTION_INT_DIVIDE_BY_ZERO), "Divide by zero error"}, }; struct FatalConditionHandler { - static LONG CALLBACK handleException(PEXCEPTION_POINTERS ExceptionInfo) { - // Multiple threads may enter this filter/handler at once. We want the error message to be printed on the - // console just once no matter how many threads have crashed. - DOCTEST_DECLARE_STATIC_MUTEX(mutex) - static bool execute = true; - { - DOCTEST_LOCK_MUTEX(mutex) - if(execute) { - bool reported = false; - for(size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) { - if(ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) { - reportFatal(signalDefs[i].name); - reported = true; - break; - } - } - if(reported == false) - reportFatal("Unhandled SEH exception caught"); - if(isDebuggerActive() && !g_cs->no_breaks) - DOCTEST_BREAK_INTO_DEBUGGER(); - } - execute = false; + static LONG CALLBACK handleException(PEXCEPTION_POINTERS ExceptionInfo) + { + // Multiple threads may enter this filter/handler at once. We want the error message to be + // printed on the console just once no matter how many threads have crashed. + DOCTEST_DECLARE_STATIC_MUTEX(mutex) + static bool execute = true; + { + DOCTEST_LOCK_MUTEX(mutex) + if (execute) { + bool reported = false; + for (size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) { + if (ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) { + reportFatal(signalDefs[i].name); + reported = true; + break; + } } + if (reported == false) + reportFatal("Unhandled SEH exception caught"); + if (isDebuggerActive() && !g_cs->no_breaks) + DOCTEST_BREAK_INTO_DEBUGGER(); + } + execute = false; + } + std::exit(EXIT_FAILURE); + } + + static void allocateAltStackMem() {} + static void freeAltStackMem() {} + + FatalConditionHandler() + { + isSet = true; + // 32k seems enough for doctest to handle stack overflow, + // but the value was found experimentally, so there is no strong guarantee + guaranteeSize = 32 * 1024; + // Register an unhandled exception filter + previousTop = SetUnhandledExceptionFilter(handleException); + // Pass in guarantee size to be filled + SetThreadStackGuarantee(&guaranteeSize); + + // On Windows uncaught exceptions from another thread, exceptions from + // destructors, or calls to std::terminate are not a SEH exception + + // The terminal handler gets called when: + // - std::terminate is called FROM THE TEST RUNNER THREAD + // - an exception is thrown from a destructor FROM THE TEST RUNNER THREAD + original_terminate_handler = std::get_terminate(); + std::set_terminate([]() DOCTEST_NOEXCEPT { + reportFatal("Terminate handler called"); + if (isDebuggerActive() && !g_cs->no_breaks) + DOCTEST_BREAK_INTO_DEBUGGER(); + std::exit(EXIT_FAILURE); // explicitly exit - otherwise the SIGABRT handler may be called + // as well + }); + + // SIGABRT is raised when: + // - std::terminate is called FROM A DIFFERENT THREAD + // - an exception is thrown from a destructor FROM A DIFFERENT THREAD + // - an uncaught exception is thrown FROM A DIFFERENT THREAD + prev_sigabrt_handler = std::signal(SIGABRT, [](int signal) DOCTEST_NOEXCEPT { + if (signal == SIGABRT) { + reportFatal("SIGABRT - Abort (abnormal termination) signal"); + if (isDebuggerActive() && !g_cs->no_breaks) + DOCTEST_BREAK_INTO_DEBUGGER(); std::exit(EXIT_FAILURE); - } - - static void allocateAltStackMem() {} - static void freeAltStackMem() {} - - FatalConditionHandler() { - isSet = true; - // 32k seems enough for doctest to handle stack overflow, - // but the value was found experimentally, so there is no strong guarantee - guaranteeSize = 32 * 1024; - // Register an unhandled exception filter - previousTop = SetUnhandledExceptionFilter(handleException); - // Pass in guarantee size to be filled - SetThreadStackGuarantee(&guaranteeSize); - - // On Windows uncaught exceptions from another thread, exceptions from - // destructors, or calls to std::terminate are not a SEH exception - - // The terminal handler gets called when: - // - std::terminate is called FROM THE TEST RUNNER THREAD - // - an exception is thrown from a destructor FROM THE TEST RUNNER THREAD - original_terminate_handler = std::get_terminate(); - std::set_terminate([]() DOCTEST_NOEXCEPT { - reportFatal("Terminate handler called"); - if(isDebuggerActive() && !g_cs->no_breaks) - DOCTEST_BREAK_INTO_DEBUGGER(); - std::exit(EXIT_FAILURE); // explicitly exit - otherwise the SIGABRT handler may be called as well - }); - - // SIGABRT is raised when: - // - std::terminate is called FROM A DIFFERENT THREAD - // - an exception is thrown from a destructor FROM A DIFFERENT THREAD - // - an uncaught exception is thrown FROM A DIFFERENT THREAD - prev_sigabrt_handler = std::signal(SIGABRT, [](int signal) DOCTEST_NOEXCEPT { - if(signal == SIGABRT) { - reportFatal("SIGABRT - Abort (abnormal termination) signal"); - if(isDebuggerActive() && !g_cs->no_breaks) - DOCTEST_BREAK_INTO_DEBUGGER(); - std::exit(EXIT_FAILURE); - } - }); - - // The following settings are taken from google test, and more - // specifically from UnitTest::Run() inside of gtest.cc - - // the user does not want to see pop-up dialogs about crashes - prev_error_mode_1 = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT | - SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX); - // This forces the abort message to go to stderr in all circumstances. - prev_error_mode_2 = _set_error_mode(_OUT_TO_STDERR); - // In the debug version, Visual Studio pops up a separate dialog - // offering a choice to debug the aborted program - we want to disable that. - prev_abort_behavior = _set_abort_behavior(0x0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); - // In debug mode, the Windows CRT can crash with an assertion over invalid - // input (e.g. passing an invalid file descriptor). The default handling - // for these assertions is to pop up a dialog and wait for user input. - // Instead ask the CRT to dump such assertions to stderr non-interactively. - prev_report_mode = _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); - prev_report_file = _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); - } - - static void reset() { - if(isSet) { - // Unregister handler and restore the old guarantee - SetUnhandledExceptionFilter(previousTop); - SetThreadStackGuarantee(&guaranteeSize); - std::set_terminate(original_terminate_handler); - std::signal(SIGABRT, prev_sigabrt_handler); - SetErrorMode(prev_error_mode_1); - _set_error_mode(prev_error_mode_2); - _set_abort_behavior(prev_abort_behavior, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); - static_cast(_CrtSetReportMode(_CRT_ASSERT, prev_report_mode)); - static_cast(_CrtSetReportFile(_CRT_ASSERT, prev_report_file)); - isSet = false; - } - } - - ~FatalConditionHandler() { reset(); } + } + }); + + // The following settings are taken from google test, and more + // specifically from UnitTest::Run() inside of gtest.cc + + // the user does not want to see pop-up dialogs about crashes + prev_error_mode_1 = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT | + SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX); + // This forces the abort message to go to stderr in all circumstances. + prev_error_mode_2 = _set_error_mode(_OUT_TO_STDERR); + // In the debug version, Visual Studio pops up a separate dialog + // offering a choice to debug the aborted program - we want to disable that. + prev_abort_behavior = _set_abort_behavior(0x0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); + // In debug mode, the Windows CRT can crash with an assertion over invalid + // input (e.g. passing an invalid file descriptor). The default handling + // for these assertions is to pop up a dialog and wait for user input. + // Instead ask the CRT to dump such assertions to stderr non-interactively. + prev_report_mode = _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); + prev_report_file = _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); + } + + static void reset() + { + if (isSet) { + // Unregister handler and restore the old guarantee + SetUnhandledExceptionFilter(previousTop); + SetThreadStackGuarantee(&guaranteeSize); + std::set_terminate(original_terminate_handler); + std::signal(SIGABRT, prev_sigabrt_handler); + SetErrorMode(prev_error_mode_1); + _set_error_mode(prev_error_mode_2); + _set_abort_behavior(prev_abort_behavior, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); + static_cast(_CrtSetReportMode(_CRT_ASSERT, prev_report_mode)); + static_cast(_CrtSetReportFile(_CRT_ASSERT, prev_report_file)); + isSet = false; + } + } + + ~FatalConditionHandler() { reset(); } private: - static UINT prev_error_mode_1; - static int prev_error_mode_2; - static unsigned int prev_abort_behavior; - static int prev_report_mode; - static _HFILE prev_report_file; - static void (DOCTEST_CDECL *prev_sigabrt_handler)(int); - static std::terminate_handler original_terminate_handler; - static bool isSet; - static ULONG guaranteeSize; - static LPTOP_LEVEL_EXCEPTION_FILTER previousTop; + static UINT prev_error_mode_1; + static int prev_error_mode_2; + static unsigned int prev_abort_behavior; + static int prev_report_mode; + static _HFILE prev_report_file; + static void(DOCTEST_CDECL *prev_sigabrt_handler)(int); + static std::terminate_handler original_terminate_handler; + static bool isSet; + static ULONG guaranteeSize; + static LPTOP_LEVEL_EXCEPTION_FILTER previousTop; }; UINT FatalConditionHandler::prev_error_mode_1; @@ -4769,18 +5180,18 @@ namespace { unsigned int FatalConditionHandler::prev_abort_behavior; int FatalConditionHandler::prev_report_mode; _HFILE FatalConditionHandler::prev_report_file; - void (DOCTEST_CDECL *FatalConditionHandler::prev_sigabrt_handler)(int); - std::terminate_handler FatalConditionHandler::original_terminate_handler; - bool FatalConditionHandler::isSet = false; - ULONG FatalConditionHandler::guaranteeSize = 0; - LPTOP_LEVEL_EXCEPTION_FILTER FatalConditionHandler::previousTop = nullptr; + void(DOCTEST_CDECL *FatalConditionHandler::prev_sigabrt_handler)(int); + std::terminate_handler FatalConditionHandler::original_terminate_handler; + bool FatalConditionHandler::isSet = false; + ULONG FatalConditionHandler::guaranteeSize = 0; + LPTOP_LEVEL_EXCEPTION_FILTER FatalConditionHandler::previousTop = nullptr; #else // DOCTEST_PLATFORM_WINDOWS struct SignalDefs { - int id; - const char* name; + int id; + const char *name; }; SignalDefs signalDefs[] = {{SIGINT, "SIGINT - Terminal interrupt signal"}, {SIGILL, "SIGILL - Illegal instruction signal"}, @@ -4791,75 +5202,74 @@ namespace { struct FatalConditionHandler { - static bool isSet; - static struct sigaction oldSigActions[DOCTEST_COUNTOF(signalDefs)]; - static stack_t oldSigStack; - static size_t altStackSize; - static char* altStackMem; - - static void handleSignal(int sig) { - const char* name = ""; - for(std::size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) { - SignalDefs& def = signalDefs[i]; - if(sig == def.id) { - name = def.name; - break; - } - } - reset(); - reportFatal(name); - raise(sig); - } - - static void allocateAltStackMem() { - altStackMem = new char[altStackSize]; - } + static bool isSet; + static struct sigaction oldSigActions[DOCTEST_COUNTOF(signalDefs)]; + static stack_t oldSigStack; + static size_t altStackSize; + static char *altStackMem; + + static void handleSignal(int sig) + { + const char *name = ""; + for (std::size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) { + SignalDefs &def = signalDefs[i]; + if (sig == def.id) { + name = def.name; + break; + } + } + reset(); + reportFatal(name); + raise(sig); + } + + static void allocateAltStackMem() { altStackMem = new char[altStackSize]; } + + static void freeAltStackMem() { delete[] altStackMem; } + + FatalConditionHandler() + { + isSet = true; + stack_t sigStack; + sigStack.ss_sp = altStackMem; + sigStack.ss_size = altStackSize; + sigStack.ss_flags = 0; + sigaltstack(&sigStack, &oldSigStack); + struct sigaction sa = {}; + sa.sa_handler = handleSignal; + sa.sa_flags = SA_ONSTACK; + for (std::size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) { + sigaction(signalDefs[i].id, &sa, &oldSigActions[i]); + } + } + + ~FatalConditionHandler() { reset(); } + static void reset() + { + if (isSet) { + // Set signals back to previous values -- hopefully nobody overwrote them in the meantime + for (std::size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) { + sigaction(signalDefs[i].id, &oldSigActions[i], nullptr); + } + // Return the old stack + sigaltstack(&oldSigStack, nullptr); + isSet = false; + } + } + }; - static void freeAltStackMem() { - delete[] altStackMem; - } - - FatalConditionHandler() { - isSet = true; - stack_t sigStack; - sigStack.ss_sp = altStackMem; - sigStack.ss_size = altStackSize; - sigStack.ss_flags = 0; - sigaltstack(&sigStack, &oldSigStack); - struct sigaction sa = {}; - sa.sa_handler = handleSignal; - sa.sa_flags = SA_ONSTACK; - for(std::size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) { - sigaction(signalDefs[i].id, &sa, &oldSigActions[i]); - } - } - - ~FatalConditionHandler() { reset(); } - static void reset() { - if(isSet) { - // Set signals back to previous values -- hopefully nobody overwrote them in the meantime - for(std::size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) { - sigaction(signalDefs[i].id, &oldSigActions[i], nullptr); - } - // Return the old stack - sigaltstack(&oldSigStack, nullptr); - isSet = false; - } - } - }; - - bool FatalConditionHandler::isSet = false; + bool FatalConditionHandler::isSet = false; struct sigaction FatalConditionHandler::oldSigActions[DOCTEST_COUNTOF(signalDefs)] = {}; - stack_t FatalConditionHandler::oldSigStack = {}; + stack_t FatalConditionHandler::oldSigStack = {}; size_t FatalConditionHandler::altStackSize = 4 * SIGSTKSZ; - char* FatalConditionHandler::altStackMem = nullptr; + char *FatalConditionHandler::altStackMem = nullptr; #endif // DOCTEST_PLATFORM_WINDOWS #endif // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH -} // namespace + } // namespace -namespace { + namespace { using namespace detail; #ifdef DOCTEST_PLATFORM_WINDOWS @@ -4869,161 +5279,186 @@ namespace { #define DOCTEST_OUTPUT_DEBUG_STRING(text) #endif // Platform - void addAssert(assertType::Enum at) { - if((at & assertType::is_warn) == 0) //!OCLINT bitwise operator in conditional - g_cs->numAssertsCurrentTest_atomic++; + void addAssert(assertType::Enum at) + { + if ((at & assertType::is_warn) == 0) //! OCLINT bitwise operator in conditional + g_cs->numAssertsCurrentTest_atomic++; } - void addFailedAssert(assertType::Enum at) { - if((at & assertType::is_warn) == 0) //!OCLINT bitwise operator in conditional - g_cs->numAssertsFailedCurrentTest_atomic++; + void addFailedAssert(assertType::Enum at) + { + if ((at & assertType::is_warn) == 0) //! OCLINT bitwise operator in conditional + g_cs->numAssertsFailedCurrentTest_atomic++; } #if defined(DOCTEST_CONFIG_POSIX_SIGNALS) || defined(DOCTEST_CONFIG_WINDOWS_SEH) - void reportFatal(const std::string& message) { - g_cs->failure_flags |= TestCaseFailureReason::Crash; + void reportFatal(const std::string &message) + { + g_cs->failure_flags |= TestCaseFailureReason::Crash; - DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_exception, {message.c_str(), true}); + DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_exception, {message.c_str(), true}); - while (g_cs->subcaseStack.size()) { - g_cs->subcaseStack.pop_back(); - DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_end, DOCTEST_EMPTY); - } + while (g_cs->subcaseStack.size()) { + g_cs->subcaseStack.pop_back(); + DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_end, DOCTEST_EMPTY); + } - g_cs->finalizeTestCaseData(); + g_cs->finalizeTestCaseData(); - DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_end, *g_cs); + DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_end, *g_cs); - DOCTEST_ITERATE_THROUGH_REPORTERS(test_run_end, *g_cs); + DOCTEST_ITERATE_THROUGH_REPORTERS(test_run_end, *g_cs); } #endif // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH -} // namespace - -AssertData::AssertData(assertType::Enum at, const char* file, int line, const char* expr, - const char* exception_type, const StringContains& exception_string) - : m_test_case(g_cs->currentTest), m_at(at), m_file(file), m_line(line), m_expr(expr), - m_failed(true), m_threw(false), m_threw_as(false), m_exception_type(exception_type), - m_exception_string(exception_string) { + } // namespace + + AssertData::AssertData(assertType::Enum at, const char *file, int line, const char *expr, + const char *exception_type, const StringContains &exception_string) + : m_test_case(g_cs->currentTest), m_at(at), m_file(file), m_line(line), m_expr(expr), + m_failed(true), m_threw(false), m_threw_as(false), m_exception_type(exception_type), + m_exception_string(exception_string) + { #if DOCTEST_MSVC if (m_expr[0] == ' ') // this happens when variadic macros are disabled under MSVC - ++m_expr; + ++m_expr; #endif // MSVC -} - -namespace detail { - ResultBuilder::ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr, - const char* exception_type, const String& exception_string) - : AssertData(at, file, line, expr, exception_type, exception_string) { } + } - ResultBuilder::ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr, - const char* exception_type, const Contains& exception_string) - : AssertData(at, file, line, expr, exception_type, exception_string) { } - - void ResultBuilder::setResult(const Result& res) { - m_decomp = res.m_decomp; - m_failed = !res.m_passed; + namespace detail { + ResultBuilder::ResultBuilder(assertType::Enum at, const char *file, int line, const char *expr, + const char *exception_type, const String &exception_string) + : AssertData(at, file, line, expr, exception_type, exception_string) + { } - void ResultBuilder::translateException() { - m_threw = true; - m_exception = translateActiveException(); + ResultBuilder::ResultBuilder(assertType::Enum at, const char *file, int line, const char *expr, + const char *exception_type, const Contains &exception_string) + : AssertData(at, file, line, expr, exception_type, exception_string) + { } - bool ResultBuilder::log() { - if(m_at & assertType::is_throws) { //!OCLINT bitwise operator in conditional - m_failed = !m_threw; - } else if((m_at & assertType::is_throws_as) && (m_at & assertType::is_throws_with)) { //!OCLINT - m_failed = !m_threw_as || !m_exception_string.check(m_exception); - } else if(m_at & assertType::is_throws_as) { //!OCLINT bitwise operator in conditional - m_failed = !m_threw_as; - } else if(m_at & assertType::is_throws_with) { //!OCLINT bitwise operator in conditional - m_failed = !m_exception_string.check(m_exception); - } else if(m_at & assertType::is_nothrow) { //!OCLINT bitwise operator in conditional - m_failed = m_threw; - } - - if(m_exception.size()) - m_exception = "\"" + m_exception + "\""; - - if(is_running_in_test) { - addAssert(m_at); - DOCTEST_ITERATE_THROUGH_REPORTERS(log_assert, *this); - - if(m_failed) - addFailedAssert(m_at); - } else if(m_failed) { - failed_out_of_a_testing_context(*this); - } + void ResultBuilder::setResult(const Result &res) + { + m_decomp = res.m_decomp; + m_failed = !res.m_passed; + } - return m_failed && isDebuggerActive() && !getContextOptions()->no_breaks && - (g_cs->currentTest == nullptr || !g_cs->currentTest->m_no_breaks); // break into debugger + void ResultBuilder::translateException() + { + m_threw = true; + m_exception = translateActiveException(); } - void ResultBuilder::react() const { - if(m_failed && checkIfShouldThrow(m_at)) - throwException(); + bool ResultBuilder::log() + { + if (m_at & assertType::is_throws) { //! OCLINT bitwise operator in conditional + m_failed = !m_threw; + } + else if ((m_at & assertType::is_throws_as) && (m_at & assertType::is_throws_with)) { //! OCLINT + m_failed = !m_threw_as || !m_exception_string.check(m_exception); + } + else if (m_at & assertType::is_throws_as) { //! OCLINT bitwise operator in conditional + m_failed = !m_threw_as; + } + else if (m_at & assertType::is_throws_with) { //! OCLINT bitwise operator in conditional + m_failed = !m_exception_string.check(m_exception); + } + else if (m_at & assertType::is_nothrow) { //! OCLINT bitwise operator in conditional + m_failed = m_threw; + } + + if (m_exception.size()) + m_exception = "\"" + m_exception + "\""; + + if (is_running_in_test) { + addAssert(m_at); + DOCTEST_ITERATE_THROUGH_REPORTERS(log_assert, *this); + + if (m_failed) + addFailedAssert(m_at); + } + else if (m_failed) { + failed_out_of_a_testing_context(*this); + } + + return m_failed && isDebuggerActive() && !getContextOptions()->no_breaks && + (g_cs->currentTest == nullptr || + !g_cs->currentTest->m_no_breaks); // break into debugger } - void failed_out_of_a_testing_context(const AssertData& ad) { - if(g_cs->ah) - g_cs->ah(ad); - else - std::abort(); + void ResultBuilder::react() const + { + if (m_failed && checkIfShouldThrow(m_at)) + throwException(); } - bool decomp_assert(assertType::Enum at, const char* file, int line, const char* expr, - const Result& result) { - bool failed = !result.m_passed; + void failed_out_of_a_testing_context(const AssertData &ad) + { + if (g_cs->ah) + g_cs->ah(ad); + else + std::abort(); + } - // ################################################################################### - // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT - // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED - // ################################################################################### - DOCTEST_ASSERT_OUT_OF_TESTS(result.m_decomp); - DOCTEST_ASSERT_IN_TESTS(result.m_decomp); - return !failed; + bool decomp_assert(assertType::Enum at, const char *file, int line, const char *expr, + const Result &result) + { + bool failed = !result.m_passed; + + // ################################################################################### + // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT + // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED + // ################################################################################### + DOCTEST_ASSERT_OUT_OF_TESTS(result.m_decomp); + DOCTEST_ASSERT_IN_TESTS(result.m_decomp); + return !failed; } - MessageBuilder::MessageBuilder(const char* file, int line, assertType::Enum severity) { - m_stream = tlssPush(); - m_file = file; - m_line = line; - m_severity = severity; + MessageBuilder::MessageBuilder(const char *file, int line, assertType::Enum severity) + { + m_stream = tlssPush(); + m_file = file; + m_line = line; + m_severity = severity; } - MessageBuilder::~MessageBuilder() { - if (!logged) - tlssPop(); + MessageBuilder::~MessageBuilder() + { + if (!logged) + tlssPop(); } DOCTEST_DEFINE_INTERFACE(IExceptionTranslator) - bool MessageBuilder::log() { - if (!logged) { - m_string = tlssPop(); - logged = true; - } + bool MessageBuilder::log() + { + if (!logged) { + m_string = tlssPop(); + logged = true; + } - DOCTEST_ITERATE_THROUGH_REPORTERS(log_message, *this); + DOCTEST_ITERATE_THROUGH_REPORTERS(log_message, *this); - const bool isWarn = m_severity & assertType::is_warn; + const bool isWarn = m_severity & assertType::is_warn; - // warn is just a message in this context so we don't treat it as an assert - if(!isWarn) { - addAssert(m_severity); - addFailedAssert(m_severity); - } + // warn is just a message in this context so we don't treat it as an assert + if (!isWarn) { + addAssert(m_severity); + addFailedAssert(m_severity); + } - return isDebuggerActive() && !getContextOptions()->no_breaks && !isWarn && - (g_cs->currentTest == nullptr || !g_cs->currentTest->m_no_breaks); // break into debugger + return isDebuggerActive() && !getContextOptions()->no_breaks && !isWarn && + (g_cs->currentTest == nullptr || + !g_cs->currentTest->m_no_breaks); // break into debugger } - void MessageBuilder::react() { - if(m_severity & assertType::is_require) //!OCLINT bitwise operator in conditional - throwException(); + void MessageBuilder::react() + { + if (m_severity & assertType::is_require) //! OCLINT bitwise operator in conditional + throwException(); } -} // namespace detail -namespace { + } // namespace detail + namespace { using namespace detail; // clang-format off @@ -5414,291 +5849,303 @@ namespace { struct XmlReporter : public IReporter { - XmlWriter xml; - DOCTEST_DECLARE_MUTEX(mutex) - - // caching pointers/references to objects of these types - safe to do - const ContextOptions& opt; - const TestCaseData* tc = nullptr; - - XmlReporter(const ContextOptions& co) - : xml(*co.cout) - , opt(co) {} - - void log_contexts() { - int num_contexts = get_num_active_contexts(); - if(num_contexts) { - auto contexts = get_active_contexts(); - std::stringstream ss; - for(int i = 0; i < num_contexts; ++i) { - contexts[i]->stringify(&ss); - xml.scopedElement("Info").writeText(ss.str()); - ss.str(""); - } - } - } - - unsigned line(unsigned l) const { return opt.no_line_numbers ? 0 : l; } - - void test_case_start_impl(const TestCaseData& in) { - bool open_ts_tag = false; - if(tc != nullptr) { // we have already opened a test suite - if(std::strcmp(tc->m_test_suite, in.m_test_suite) != 0) { - xml.endElement(); - open_ts_tag = true; - } - } - else { - open_ts_tag = true; // first test case ==> first test suite - } - - if(open_ts_tag) { - xml.startElement("TestSuite"); - xml.writeAttribute("name", in.m_test_suite); - } - - tc = ∈ - xml.startElement("TestCase") - .writeAttribute("name", in.m_name) - .writeAttribute("filename", skipPathFromFilename(in.m_file.c_str())) - .writeAttribute("line", line(in.m_line)) - .writeAttribute("description", in.m_description); - - if(Approx(in.m_timeout) != 0) - xml.writeAttribute("timeout", in.m_timeout); - if(in.m_may_fail) - xml.writeAttribute("may_fail", true); - if(in.m_should_fail) - xml.writeAttribute("should_fail", true); - } - - // ========================================================================================= - // WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE - // ========================================================================================= - - void report_query(const QueryData& in) override { - test_run_start(); - if(opt.list_reporters) { - for(auto& curr : getListeners()) - xml.scopedElement("Listener") - .writeAttribute("priority", curr.first.first) - .writeAttribute("name", curr.first.second); - for(auto& curr : getReporters()) - xml.scopedElement("Reporter") - .writeAttribute("priority", curr.first.first) - .writeAttribute("name", curr.first.second); - } else if(opt.count || opt.list_test_cases) { - for(unsigned i = 0; i < in.num_data; ++i) { - xml.scopedElement("TestCase").writeAttribute("name", in.data[i]->m_name) - .writeAttribute("testsuite", in.data[i]->m_test_suite) - .writeAttribute("filename", skipPathFromFilename(in.data[i]->m_file.c_str())) - .writeAttribute("line", line(in.data[i]->m_line)) - .writeAttribute("skipped", in.data[i]->m_skip); - } - xml.scopedElement("OverallResultsTestCases") - .writeAttribute("unskipped", in.run_stats->numTestCasesPassingFilters); - } else if(opt.list_test_suites) { - for(unsigned i = 0; i < in.num_data; ++i) - xml.scopedElement("TestSuite").writeAttribute("name", in.data[i]->m_test_suite); - xml.scopedElement("OverallResultsTestCases") - .writeAttribute("unskipped", in.run_stats->numTestCasesPassingFilters); - xml.scopedElement("OverallResultsTestSuites") - .writeAttribute("unskipped", in.run_stats->numTestSuitesPassingFilters); - } + XmlWriter xml; + DOCTEST_DECLARE_MUTEX(mutex) + + // caching pointers/references to objects of these types - safe to do + const ContextOptions &opt; + const TestCaseData *tc = nullptr; + + XmlReporter(const ContextOptions &co) : xml(*co.cout), opt(co) {} + + void log_contexts() + { + int num_contexts = get_num_active_contexts(); + if (num_contexts) { + auto contexts = get_active_contexts(); + std::stringstream ss; + for (int i = 0; i < num_contexts; ++i) { + contexts[i]->stringify(&ss); + xml.scopedElement("Info").writeText(ss.str()); + ss.str(""); + } + } + } + + unsigned line(unsigned l) const { return opt.no_line_numbers ? 0 : l; } + + void test_case_start_impl(const TestCaseData &in) + { + bool open_ts_tag = false; + if (tc != nullptr) { // we have already opened a test suite + if (std::strcmp(tc->m_test_suite, in.m_test_suite) != 0) { xml.endElement(); + open_ts_tag = true; + } } - - void test_run_start() override { - xml.writeDeclaration(); - - // remove .exe extension - mainly to have the same output on UNIX and Windows - std::string binary_name = skipPathFromFilename(opt.binary_name.c_str()); + else { + open_ts_tag = true; // first test case ==> first test suite + } + + if (open_ts_tag) { + xml.startElement("TestSuite"); + xml.writeAttribute("name", in.m_test_suite); + } + + tc = ∈ + xml.startElement("TestCase") + .writeAttribute("name", in.m_name) + .writeAttribute("filename", skipPathFromFilename(in.m_file.c_str())) + .writeAttribute("line", line(in.m_line)) + .writeAttribute("description", in.m_description); + + if (Approx(in.m_timeout) != 0) + xml.writeAttribute("timeout", in.m_timeout); + if (in.m_may_fail) + xml.writeAttribute("may_fail", true); + if (in.m_should_fail) + xml.writeAttribute("should_fail", true); + } + + // ========================================================================================= + // WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE + // ========================================================================================= + + void report_query(const QueryData &in) override + { + test_run_start(); + if (opt.list_reporters) { + for (auto &curr : getListeners()) + xml.scopedElement("Listener") + .writeAttribute("priority", curr.first.first) + .writeAttribute("name", curr.first.second); + for (auto &curr : getReporters()) + xml.scopedElement("Reporter") + .writeAttribute("priority", curr.first.first) + .writeAttribute("name", curr.first.second); + } + else if (opt.count || opt.list_test_cases) { + for (unsigned i = 0; i < in.num_data; ++i) { + xml.scopedElement("TestCase") + .writeAttribute("name", in.data[i]->m_name) + .writeAttribute("testsuite", in.data[i]->m_test_suite) + .writeAttribute("filename", skipPathFromFilename(in.data[i]->m_file.c_str())) + .writeAttribute("line", line(in.data[i]->m_line)) + .writeAttribute("skipped", in.data[i]->m_skip); + } + xml.scopedElement("OverallResultsTestCases") + .writeAttribute("unskipped", in.run_stats->numTestCasesPassingFilters); + } + else if (opt.list_test_suites) { + for (unsigned i = 0; i < in.num_data; ++i) + xml.scopedElement("TestSuite").writeAttribute("name", in.data[i]->m_test_suite); + xml.scopedElement("OverallResultsTestCases") + .writeAttribute("unskipped", in.run_stats->numTestCasesPassingFilters); + xml.scopedElement("OverallResultsTestSuites") + .writeAttribute("unskipped", in.run_stats->numTestSuitesPassingFilters); + } + xml.endElement(); + } + + void test_run_start() override + { + xml.writeDeclaration(); + + // remove .exe extension - mainly to have the same output on UNIX and Windows + std::string binary_name = skipPathFromFilename(opt.binary_name.c_str()); #ifdef DOCTEST_PLATFORM_WINDOWS - if(binary_name.rfind(".exe") != std::string::npos) - binary_name = binary_name.substr(0, binary_name.length() - 4); + if (binary_name.rfind(".exe") != std::string::npos) + binary_name = binary_name.substr(0, binary_name.length() - 4); #endif // DOCTEST_PLATFORM_WINDOWS - xml.startElement("doctest").writeAttribute("binary", binary_name); - if(opt.no_version == false) - xml.writeAttribute("version", DOCTEST_VERSION_STR); - - // only the consequential ones (TODO: filters) - xml.scopedElement("Options") - .writeAttribute("order_by", opt.order_by.c_str()) - .writeAttribute("rand_seed", opt.rand_seed) - .writeAttribute("first", opt.first) - .writeAttribute("last", opt.last) - .writeAttribute("abort_after", opt.abort_after) - .writeAttribute("subcase_filter_levels", opt.subcase_filter_levels) - .writeAttribute("case_sensitive", opt.case_sensitive) - .writeAttribute("no_throw", opt.no_throw) - .writeAttribute("no_skip", opt.no_skip); - } - - void test_run_end(const TestRunStats& p) override { - if(tc) // the TestSuite tag - only if there has been at least 1 test case - xml.endElement(); - - xml.scopedElement("OverallResultsAsserts") - .writeAttribute("successes", p.numAsserts - p.numAssertsFailed) - .writeAttribute("failures", p.numAssertsFailed); - - xml.startElement("OverallResultsTestCases") - .writeAttribute("successes", - p.numTestCasesPassingFilters - p.numTestCasesFailed) - .writeAttribute("failures", p.numTestCasesFailed); - if(opt.no_skipped_summary == false) - xml.writeAttribute("skipped", p.numTestCases - p.numTestCasesPassingFilters); - xml.endElement(); - - xml.endElement(); - } - - void test_case_start(const TestCaseData& in) override { - test_case_start_impl(in); - xml.ensureTagClosed(); - } - - void test_case_reenter(const TestCaseData&) override {} - - void test_case_end(const CurrentTestCaseStats& st) override { - xml.startElement("OverallResultsAsserts") - .writeAttribute("successes", - st.numAssertsCurrentTest - st.numAssertsFailedCurrentTest) - .writeAttribute("failures", st.numAssertsFailedCurrentTest) - .writeAttribute("test_case_success", st.testCaseSuccess); - if(opt.duration) - xml.writeAttribute("duration", st.seconds); - if(tc->m_expected_failures) - xml.writeAttribute("expected_failures", tc->m_expected_failures); - xml.endElement(); - - xml.endElement(); - } - - void test_case_exception(const TestCaseException& e) override { - DOCTEST_LOCK_MUTEX(mutex) - - xml.scopedElement("Exception") - .writeAttribute("crash", e.is_crash) - .writeText(e.error_string.c_str()); - } - - void subcase_start(const SubcaseSignature& in) override { - xml.startElement("SubCase") - .writeAttribute("name", in.m_name) - .writeAttribute("filename", skipPathFromFilename(in.m_file)) - .writeAttribute("line", line(in.m_line)); - xml.ensureTagClosed(); - } - - void subcase_end() override { xml.endElement(); } - - void log_assert(const AssertData& rb) override { - if(!rb.m_failed && !opt.success) - return; - - DOCTEST_LOCK_MUTEX(mutex) - - xml.startElement("Expression") - .writeAttribute("success", !rb.m_failed) - .writeAttribute("type", assertString(rb.m_at)) - .writeAttribute("filename", skipPathFromFilename(rb.m_file)) - .writeAttribute("line", line(rb.m_line)); - - xml.scopedElement("Original").writeText(rb.m_expr); - - if(rb.m_threw) - xml.scopedElement("Exception").writeText(rb.m_exception.c_str()); - - if(rb.m_at & assertType::is_throws_as) - xml.scopedElement("ExpectedException").writeText(rb.m_exception_type); - if(rb.m_at & assertType::is_throws_with) - xml.scopedElement("ExpectedExceptionString").writeText(rb.m_exception_string.c_str()); - if((rb.m_at & assertType::is_normal) && !rb.m_threw) - xml.scopedElement("Expanded").writeText(rb.m_decomp.c_str()); - - log_contexts(); - - xml.endElement(); - } - - void log_message(const MessageData& mb) override { - DOCTEST_LOCK_MUTEX(mutex) - - xml.startElement("Message") - .writeAttribute("type", failureString(mb.m_severity)) - .writeAttribute("filename", skipPathFromFilename(mb.m_file)) - .writeAttribute("line", line(mb.m_line)); - - xml.scopedElement("Text").writeText(mb.m_string.c_str()); - - log_contexts(); - - xml.endElement(); - } - - void test_case_skipped(const TestCaseData& in) override { - if(opt.no_skipped_summary == false) { - test_case_start_impl(in); - xml.writeAttribute("skipped", "true"); - xml.endElement(); - } - } + xml.startElement("doctest").writeAttribute("binary", binary_name); + if (opt.no_version == false) + xml.writeAttribute("version", DOCTEST_VERSION_STR); + + // only the consequential ones (TODO: filters) + xml.scopedElement("Options") + .writeAttribute("order_by", opt.order_by.c_str()) + .writeAttribute("rand_seed", opt.rand_seed) + .writeAttribute("first", opt.first) + .writeAttribute("last", opt.last) + .writeAttribute("abort_after", opt.abort_after) + .writeAttribute("subcase_filter_levels", opt.subcase_filter_levels) + .writeAttribute("case_sensitive", opt.case_sensitive) + .writeAttribute("no_throw", opt.no_throw) + .writeAttribute("no_skip", opt.no_skip); + } + + void test_run_end(const TestRunStats &p) override + { + if (tc) // the TestSuite tag - only if there has been at least 1 test case + xml.endElement(); + + xml.scopedElement("OverallResultsAsserts") + .writeAttribute("successes", p.numAsserts - p.numAssertsFailed) + .writeAttribute("failures", p.numAssertsFailed); + + xml.startElement("OverallResultsTestCases") + .writeAttribute("successes", p.numTestCasesPassingFilters - p.numTestCasesFailed) + .writeAttribute("failures", p.numTestCasesFailed); + if (opt.no_skipped_summary == false) + xml.writeAttribute("skipped", p.numTestCases - p.numTestCasesPassingFilters); + xml.endElement(); + + xml.endElement(); + } + + void test_case_start(const TestCaseData &in) override + { + test_case_start_impl(in); + xml.ensureTagClosed(); + } + + void test_case_reenter(const TestCaseData &) override {} + + void test_case_end(const CurrentTestCaseStats &st) override + { + xml.startElement("OverallResultsAsserts") + .writeAttribute("successes", st.numAssertsCurrentTest - st.numAssertsFailedCurrentTest) + .writeAttribute("failures", st.numAssertsFailedCurrentTest) + .writeAttribute("test_case_success", st.testCaseSuccess); + if (opt.duration) + xml.writeAttribute("duration", st.seconds); + if (tc->m_expected_failures) + xml.writeAttribute("expected_failures", tc->m_expected_failures); + xml.endElement(); + + xml.endElement(); + } + + void test_case_exception(const TestCaseException &e) override + { + DOCTEST_LOCK_MUTEX(mutex) + + xml.scopedElement("Exception") + .writeAttribute("crash", e.is_crash) + .writeText(e.error_string.c_str()); + } + + void subcase_start(const SubcaseSignature &in) override + { + xml.startElement("SubCase") + .writeAttribute("name", in.m_name) + .writeAttribute("filename", skipPathFromFilename(in.m_file)) + .writeAttribute("line", line(in.m_line)); + xml.ensureTagClosed(); + } + + void subcase_end() override { xml.endElement(); } + + void log_assert(const AssertData &rb) override + { + if (!rb.m_failed && !opt.success) + return; + + DOCTEST_LOCK_MUTEX(mutex) + + xml.startElement("Expression") + .writeAttribute("success", !rb.m_failed) + .writeAttribute("type", assertString(rb.m_at)) + .writeAttribute("filename", skipPathFromFilename(rb.m_file)) + .writeAttribute("line", line(rb.m_line)); + + xml.scopedElement("Original").writeText(rb.m_expr); + + if (rb.m_threw) + xml.scopedElement("Exception").writeText(rb.m_exception.c_str()); + + if (rb.m_at & assertType::is_throws_as) + xml.scopedElement("ExpectedException").writeText(rb.m_exception_type); + if (rb.m_at & assertType::is_throws_with) + xml.scopedElement("ExpectedExceptionString").writeText(rb.m_exception_string.c_str()); + if ((rb.m_at & assertType::is_normal) && !rb.m_threw) + xml.scopedElement("Expanded").writeText(rb.m_decomp.c_str()); + + log_contexts(); + + xml.endElement(); + } + + void log_message(const MessageData &mb) override + { + DOCTEST_LOCK_MUTEX(mutex) + + xml.startElement("Message") + .writeAttribute("type", failureString(mb.m_severity)) + .writeAttribute("filename", skipPathFromFilename(mb.m_file)) + .writeAttribute("line", line(mb.m_line)); + + xml.scopedElement("Text").writeText(mb.m_string.c_str()); + + log_contexts(); + + xml.endElement(); + } + + void test_case_skipped(const TestCaseData &in) override + { + if (opt.no_skipped_summary == false) { + test_case_start_impl(in); + xml.writeAttribute("skipped", "true"); + xml.endElement(); + } + } }; DOCTEST_REGISTER_REPORTER("xml", 0, XmlReporter); - void fulltext_log_assert_to_stream(std::ostream& s, const AssertData& rb) { - if((rb.m_at & (assertType::is_throws_as | assertType::is_throws_with)) == - 0) //!OCLINT bitwise operator in conditional - s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << " ) " - << Color::None; - - if(rb.m_at & assertType::is_throws) { //!OCLINT bitwise operator in conditional - s << (rb.m_threw ? "threw as expected!" : "did NOT throw at all!") << "\n"; - } else if((rb.m_at & assertType::is_throws_as) && - (rb.m_at & assertType::is_throws_with)) { //!OCLINT - s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", \"" - << rb.m_exception_string.c_str() - << "\", " << rb.m_exception_type << " ) " << Color::None; - if(rb.m_threw) { - if(!rb.m_failed) { - s << "threw as expected!\n"; - } else { - s << "threw a DIFFERENT exception! (contents: " << rb.m_exception << ")\n"; - } - } else { - s << "did NOT throw at all!\n"; - } - } else if(rb.m_at & - assertType::is_throws_as) { //!OCLINT bitwise operator in conditional - s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", " - << rb.m_exception_type << " ) " << Color::None - << (rb.m_threw ? (rb.m_threw_as ? "threw as expected!" : - "threw a DIFFERENT exception: ") : - "did NOT throw at all!") - << Color::Cyan << rb.m_exception << "\n"; - } else if(rb.m_at & - assertType::is_throws_with) { //!OCLINT bitwise operator in conditional - s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", \"" - << rb.m_exception_string.c_str() - << "\" ) " << Color::None - << (rb.m_threw ? (!rb.m_failed ? "threw as expected!" : - "threw a DIFFERENT exception: ") : - "did NOT throw at all!") - << Color::Cyan << rb.m_exception << "\n"; - } else if(rb.m_at & assertType::is_nothrow) { //!OCLINT bitwise operator in conditional - s << (rb.m_threw ? "THREW exception: " : "didn't throw!") << Color::Cyan - << rb.m_exception << "\n"; - } else { - s << (rb.m_threw ? "THREW exception: " : - (!rb.m_failed ? "is correct!\n" : "is NOT correct!\n")); - if(rb.m_threw) - s << rb.m_exception << "\n"; - else - s << " values: " << assertString(rb.m_at) << "( " << rb.m_decomp << " )\n"; + void fulltext_log_assert_to_stream(std::ostream &s, const AssertData &rb) + { + if ((rb.m_at & (assertType::is_throws_as | assertType::is_throws_with)) == + 0) //! OCLINT bitwise operator in conditional + s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << " ) " << Color::None; + + if (rb.m_at & assertType::is_throws) { //! OCLINT bitwise operator in conditional + s << (rb.m_threw ? "threw as expected!" : "did NOT throw at all!") << "\n"; + } + else if ((rb.m_at & assertType::is_throws_as) && + (rb.m_at & assertType::is_throws_with)) { //! OCLINT + s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", \"" + << rb.m_exception_string.c_str() << "\", " << rb.m_exception_type << " ) " << Color::None; + if (rb.m_threw) { + if (!rb.m_failed) { + s << "threw as expected!\n"; + } + else { + s << "threw a DIFFERENT exception! (contents: " << rb.m_exception << ")\n"; + } } + else { + s << "did NOT throw at all!\n"; + } + } + else if (rb.m_at & assertType::is_throws_as) { //! OCLINT bitwise operator in conditional + s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", " + << rb.m_exception_type << " ) " << Color::None + << (rb.m_threw ? (rb.m_threw_as ? "threw as expected!" : "threw a DIFFERENT exception: ") + : "did NOT throw at all!") + << Color::Cyan << rb.m_exception << "\n"; + } + else if (rb.m_at & assertType::is_throws_with) { //! OCLINT bitwise operator in conditional + s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", \"" + << rb.m_exception_string.c_str() << "\" ) " << Color::None + << (rb.m_threw ? (!rb.m_failed ? "threw as expected!" : "threw a DIFFERENT exception: ") + : "did NOT throw at all!") + << Color::Cyan << rb.m_exception << "\n"; + } + else if (rb.m_at & assertType::is_nothrow) { //! OCLINT bitwise operator in conditional + s << (rb.m_threw ? "THREW exception: " : "didn't throw!") << Color::Cyan << rb.m_exception + << "\n"; + } + else { + s << (rb.m_threw ? "THREW exception: " + : (!rb.m_failed ? "is correct!\n" : "is NOT correct!\n")); + if (rb.m_threw) + s << rb.m_exception << "\n"; + else + s << " values: " << assertString(rb.m_at) << "( " << rb.m_decomp << " )\n"; + } } // TODO: @@ -5708,375 +6155,401 @@ namespace { // - more attributes in tags struct JUnitReporter : public IReporter { - XmlWriter xml; - DOCTEST_DECLARE_MUTEX(mutex) - Timer timer; - std::vector deepestSubcaseStackNames; - - struct JUnitTestCaseData + XmlWriter xml; + DOCTEST_DECLARE_MUTEX(mutex) + Timer timer; + std::vector deepestSubcaseStackNames; + + struct JUnitTestCaseData + { + static std::string getCurrentTimestamp() { - static std::string getCurrentTimestamp() { - // Beware, this is not reentrant because of backward compatibility issues - // Also, UTC only, again because of backward compatibility (%z is C++11) - time_t rawtime; - std::time(&rawtime); - auto const timeStampSize = sizeof("2017-01-16T17:06:45Z"); - - std::tm timeInfo; -#ifdef DOCTEST_PLATFORM_WINDOWS - gmtime_s(&timeInfo, &rawtime); -#else // DOCTEST_PLATFORM_WINDOWS - gmtime_r(&rawtime, &timeInfo); -#endif // DOCTEST_PLATFORM_WINDOWS - - char timeStamp[timeStampSize]; - const char* const fmt = "%Y-%m-%dT%H:%M:%SZ"; - - std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); - return std::string(timeStamp); - } - - struct JUnitTestMessage - { - JUnitTestMessage(const std::string& _message, const std::string& _type, const std::string& _details) - : message(_message), type(_type), details(_details) {} - - JUnitTestMessage(const std::string& _message, const std::string& _details) - : message(_message), type(), details(_details) {} - - std::string message, type, details; - }; - - struct JUnitTestCase - { - JUnitTestCase(const std::string& _classname, const std::string& _name) - : classname(_classname), name(_name), time(0), failures() {} - - std::string classname, name; - double time; - std::vector failures, errors; - }; - - void add(const std::string& classname, const std::string& name) { - testcases.emplace_back(classname, name); - } - - void appendSubcaseNamesToLastTestcase(std::vector nameStack) { - for(auto& curr: nameStack) - if(curr.size()) - testcases.back().name += std::string("/") + curr.c_str(); - } - - void addTime(double time) { - if(time < 1e-4) - time = 0; - testcases.back().time = time; - totalSeconds += time; - } + // Beware, this is not reentrant because of backward compatibility issues + // Also, UTC only, again because of backward compatibility (%z is C++11) + time_t rawtime; + std::time(&rawtime); + auto const timeStampSize = sizeof("2017-01-16T17:06:45Z"); - void addFailure(const std::string& message, const std::string& type, const std::string& details) { - testcases.back().failures.emplace_back(message, type, details); - ++totalFailures; - } - - void addError(const std::string& message, const std::string& details) { - testcases.back().errors.emplace_back(message, details); - ++totalErrors; - } - - std::vector testcases; - double totalSeconds = 0; - int totalErrors = 0, totalFailures = 0; - }; - - JUnitTestCaseData testCaseData; - - // caching pointers/references to objects of these types - safe to do - const ContextOptions& opt; - const TestCaseData* tc = nullptr; - - JUnitReporter(const ContextOptions& co) - : xml(*co.cout) - , opt(co) {} - - unsigned line(unsigned l) const { return opt.no_line_numbers ? 0 : l; } - - // ========================================================================================= - // WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE - // ========================================================================================= - - void report_query(const QueryData&) override { - xml.writeDeclaration(); - } - - void test_run_start() override { - xml.writeDeclaration(); - } - - void test_run_end(const TestRunStats& p) override { - // remove .exe extension - mainly to have the same output on UNIX and Windows - std::string binary_name = skipPathFromFilename(opt.binary_name.c_str()); + std::tm timeInfo; #ifdef DOCTEST_PLATFORM_WINDOWS - if(binary_name.rfind(".exe") != std::string::npos) - binary_name = binary_name.substr(0, binary_name.length() - 4); + gmtime_s(&timeInfo, &rawtime); +#else // DOCTEST_PLATFORM_WINDOWS + gmtime_r(&rawtime, &timeInfo); #endif // DOCTEST_PLATFORM_WINDOWS - xml.startElement("testsuites"); - xml.startElement("testsuite").writeAttribute("name", binary_name) - .writeAttribute("errors", testCaseData.totalErrors) - .writeAttribute("failures", testCaseData.totalFailures) - .writeAttribute("tests", p.numAsserts); - if(opt.no_time_in_output == false) { - xml.writeAttribute("time", testCaseData.totalSeconds); - xml.writeAttribute("timestamp", JUnitTestCaseData::getCurrentTimestamp()); - } - if(opt.no_version == false) - xml.writeAttribute("doctest_version", DOCTEST_VERSION_STR); - - for(const auto& testCase : testCaseData.testcases) { - xml.startElement("testcase") - .writeAttribute("classname", testCase.classname) - .writeAttribute("name", testCase.name); - if(opt.no_time_in_output == false) - xml.writeAttribute("time", testCase.time); - // This is not ideal, but it should be enough to mimic gtest's junit output. - xml.writeAttribute("status", "run"); - - for(const auto& failure : testCase.failures) { - xml.scopedElement("failure") - .writeAttribute("message", failure.message) - .writeAttribute("type", failure.type) - .writeText(failure.details, false); - } - for(const auto& error : testCase.errors) { - xml.scopedElement("error") - .writeAttribute("message", error.message) - .writeText(error.details); - } + char timeStamp[timeStampSize]; + const char *const fmt = "%Y-%m-%dT%H:%M:%SZ"; - xml.endElement(); - } - xml.endElement(); - xml.endElement(); + std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); + return std::string(timeStamp); } - void test_case_start(const TestCaseData& in) override { - testCaseData.add(skipPathFromFilename(in.m_file.c_str()), in.m_name); - timer.start(); - } + struct JUnitTestMessage + { + JUnitTestMessage(const std::string &_message, const std::string &_type, + const std::string &_details) + : message(_message), type(_type), details(_details) + { + } + + JUnitTestMessage(const std::string &_message, const std::string &_details) + : message(_message), type(), details(_details) + { + } + + std::string message, type, details; + }; - void test_case_reenter(const TestCaseData& in) override { - testCaseData.addTime(timer.getElapsedSeconds()); - testCaseData.appendSubcaseNamesToLastTestcase(deepestSubcaseStackNames); - deepestSubcaseStackNames.clear(); + struct JUnitTestCase + { + JUnitTestCase(const std::string &_classname, const std::string &_name) + : classname(_classname), name(_name), time(0), failures() + { + } + + std::string classname, name; + double time; + std::vector failures, errors; + }; - timer.start(); - testCaseData.add(skipPathFromFilename(in.m_file.c_str()), in.m_name); + void add(const std::string &classname, const std::string &name) + { + testcases.emplace_back(classname, name); } - void test_case_end(const CurrentTestCaseStats&) override { - testCaseData.addTime(timer.getElapsedSeconds()); - testCaseData.appendSubcaseNamesToLastTestcase(deepestSubcaseStackNames); - deepestSubcaseStackNames.clear(); + void appendSubcaseNamesToLastTestcase(std::vector nameStack) + { + for (auto &curr : nameStack) + if (curr.size()) + testcases.back().name += std::string("/") + curr.c_str(); } - void test_case_exception(const TestCaseException& e) override { - DOCTEST_LOCK_MUTEX(mutex) - testCaseData.addError("exception", e.error_string.c_str()); + void addTime(double time) + { + if (time < 1e-4) + time = 0; + testcases.back().time = time; + totalSeconds += time; } - void subcase_start(const SubcaseSignature& in) override { - deepestSubcaseStackNames.push_back(in.m_name); + void addFailure(const std::string &message, const std::string &type, + const std::string &details) + { + testcases.back().failures.emplace_back(message, type, details); + ++totalFailures; } - void subcase_end() override {} - - void log_assert(const AssertData& rb) override { - if(!rb.m_failed) // report only failures & ignore the `success` option - return; - - DOCTEST_LOCK_MUTEX(mutex) - - std::ostringstream os; - os << skipPathFromFilename(rb.m_file) << (opt.gnu_file_line ? ":" : "(") - << line(rb.m_line) << (opt.gnu_file_line ? ":" : "):") << std::endl; - - fulltext_log_assert_to_stream(os, rb); - log_contexts(os); - testCaseData.addFailure(rb.m_decomp.c_str(), assertString(rb.m_at), os.str()); + void addError(const std::string &message, const std::string &details) + { + testcases.back().errors.emplace_back(message, details); + ++totalErrors; } - void log_message(const MessageData& mb) override { - if(mb.m_severity & assertType::is_warn) // report only failures - return; + std::vector testcases; + double totalSeconds = 0; + int totalErrors = 0, totalFailures = 0; + }; - DOCTEST_LOCK_MUTEX(mutex) + JUnitTestCaseData testCaseData; - std::ostringstream os; - os << skipPathFromFilename(mb.m_file) << (opt.gnu_file_line ? ":" : "(") - << line(mb.m_line) << (opt.gnu_file_line ? ":" : "):") << std::endl; + // caching pointers/references to objects of these types - safe to do + const ContextOptions &opt; + const TestCaseData *tc = nullptr; - os << mb.m_string.c_str() << "\n"; - log_contexts(os); + JUnitReporter(const ContextOptions &co) : xml(*co.cout), opt(co) {} - testCaseData.addFailure(mb.m_string.c_str(), - mb.m_severity & assertType::is_check ? "FAIL_CHECK" : "FAIL", os.str()); - } + unsigned line(unsigned l) const { return opt.no_line_numbers ? 0 : l; } - void test_case_skipped(const TestCaseData&) override {} + // ========================================================================================= + // WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE + // ========================================================================================= - void log_contexts(std::ostringstream& s) { - int num_contexts = get_num_active_contexts(); - if(num_contexts) { - auto contexts = get_active_contexts(); + void report_query(const QueryData &) override { xml.writeDeclaration(); } - s << " logged: "; - for(int i = 0; i < num_contexts; ++i) { - s << (i == 0 ? "" : " "); - contexts[i]->stringify(&s); - s << std::endl; - } - } - } + void test_run_start() override { xml.writeDeclaration(); } + + void test_run_end(const TestRunStats &p) override + { + // remove .exe extension - mainly to have the same output on UNIX and Windows + std::string binary_name = skipPathFromFilename(opt.binary_name.c_str()); +#ifdef DOCTEST_PLATFORM_WINDOWS + if (binary_name.rfind(".exe") != std::string::npos) + binary_name = binary_name.substr(0, binary_name.length() - 4); +#endif // DOCTEST_PLATFORM_WINDOWS + xml.startElement("testsuites"); + xml.startElement("testsuite") + .writeAttribute("name", binary_name) + .writeAttribute("errors", testCaseData.totalErrors) + .writeAttribute("failures", testCaseData.totalFailures) + .writeAttribute("tests", p.numAsserts); + if (opt.no_time_in_output == false) { + xml.writeAttribute("time", testCaseData.totalSeconds); + xml.writeAttribute("timestamp", JUnitTestCaseData::getCurrentTimestamp()); + } + if (opt.no_version == false) + xml.writeAttribute("doctest_version", DOCTEST_VERSION_STR); + + for (const auto &testCase : testCaseData.testcases) { + xml.startElement("testcase") + .writeAttribute("classname", testCase.classname) + .writeAttribute("name", testCase.name); + if (opt.no_time_in_output == false) + xml.writeAttribute("time", testCase.time); + // This is not ideal, but it should be enough to mimic gtest's junit output. + xml.writeAttribute("status", "run"); + + for (const auto &failure : testCase.failures) { + xml.scopedElement("failure") + .writeAttribute("message", failure.message) + .writeAttribute("type", failure.type) + .writeText(failure.details, false); + } + + for (const auto &error : testCase.errors) { + xml.scopedElement("error") + .writeAttribute("message", error.message) + .writeText(error.details); + } + + xml.endElement(); + } + xml.endElement(); + xml.endElement(); + } + + void test_case_start(const TestCaseData &in) override + { + testCaseData.add(skipPathFromFilename(in.m_file.c_str()), in.m_name); + timer.start(); + } + + void test_case_reenter(const TestCaseData &in) override + { + testCaseData.addTime(timer.getElapsedSeconds()); + testCaseData.appendSubcaseNamesToLastTestcase(deepestSubcaseStackNames); + deepestSubcaseStackNames.clear(); + + timer.start(); + testCaseData.add(skipPathFromFilename(in.m_file.c_str()), in.m_name); + } + + void test_case_end(const CurrentTestCaseStats &) override + { + testCaseData.addTime(timer.getElapsedSeconds()); + testCaseData.appendSubcaseNamesToLastTestcase(deepestSubcaseStackNames); + deepestSubcaseStackNames.clear(); + } + + void test_case_exception(const TestCaseException &e) override + { + DOCTEST_LOCK_MUTEX(mutex) + testCaseData.addError("exception", e.error_string.c_str()); + } + + void subcase_start(const SubcaseSignature &in) override + { + deepestSubcaseStackNames.push_back(in.m_name); + } + + void subcase_end() override {} + + void log_assert(const AssertData &rb) override + { + if (!rb.m_failed) // report only failures & ignore the `success` option + return; + + DOCTEST_LOCK_MUTEX(mutex) + + std::ostringstream os; + os << skipPathFromFilename(rb.m_file) << (opt.gnu_file_line ? ":" : "(") << line(rb.m_line) + << (opt.gnu_file_line ? ":" : "):") << std::endl; + + fulltext_log_assert_to_stream(os, rb); + log_contexts(os); + testCaseData.addFailure(rb.m_decomp.c_str(), assertString(rb.m_at), os.str()); + } + + void log_message(const MessageData &mb) override + { + if (mb.m_severity & assertType::is_warn) // report only failures + return; + + DOCTEST_LOCK_MUTEX(mutex) + + std::ostringstream os; + os << skipPathFromFilename(mb.m_file) << (opt.gnu_file_line ? ":" : "(") << line(mb.m_line) + << (opt.gnu_file_line ? ":" : "):") << std::endl; + + os << mb.m_string.c_str() << "\n"; + log_contexts(os); + + testCaseData.addFailure(mb.m_string.c_str(), + mb.m_severity & assertType::is_check ? "FAIL_CHECK" : "FAIL", + os.str()); + } + + void test_case_skipped(const TestCaseData &) override {} + + void log_contexts(std::ostringstream &s) + { + int num_contexts = get_num_active_contexts(); + if (num_contexts) { + auto contexts = get_active_contexts(); + + s << " logged: "; + for (int i = 0; i < num_contexts; ++i) { + s << (i == 0 ? "" : " "); + contexts[i]->stringify(&s); + s << std::endl; + } + } + } }; DOCTEST_REGISTER_REPORTER("junit", 0, JUnitReporter); struct Whitespace { - int nrSpaces; - explicit Whitespace(int nr) - : nrSpaces(nr) {} + int nrSpaces; + explicit Whitespace(int nr) : nrSpaces(nr) {} }; - std::ostream& operator<<(std::ostream& out, const Whitespace& ws) { - if(ws.nrSpaces != 0) - out << std::setw(ws.nrSpaces) << ' '; - return out; + std::ostream &operator<<(std::ostream &out, const Whitespace &ws) + { + if (ws.nrSpaces != 0) + out << std::setw(ws.nrSpaces) << ' '; + return out; } struct ConsoleReporter : public IReporter { - std::ostream& s; - bool hasLoggedCurrentTestStart; - std::vector subcasesStack; - size_t currentSubcaseLevel; - DOCTEST_DECLARE_MUTEX(mutex) - - // caching pointers/references to objects of these types - safe to do - const ContextOptions& opt; - const TestCaseData* tc; - - ConsoleReporter(const ContextOptions& co) - : s(*co.cout) - , opt(co) {} - - ConsoleReporter(const ContextOptions& co, std::ostream& ostr) - : s(ostr) - , opt(co) {} - - // ========================================================================================= - // WHAT FOLLOWS ARE HELPERS USED BY THE OVERRIDES OF THE VIRTUAL METHODS OF THE INTERFACE - // ========================================================================================= - - void separator_to_stream() { - s << Color::Yellow - << "===============================================================================" - "\n"; - } - - const char* getSuccessOrFailString(bool success, assertType::Enum at, - const char* success_str) { - if(success) - return success_str; - return failureString(at); - } - - Color::Enum getSuccessOrFailColor(bool success, assertType::Enum at) { - return success ? Color::BrightGreen : - (at & assertType::is_warn) ? Color::Yellow : Color::Red; - } - - void successOrFailColoredStringToStream(bool success, assertType::Enum at, - const char* success_str = "SUCCESS") { - s << getSuccessOrFailColor(success, at) - << getSuccessOrFailString(success, at, success_str) << ": "; - } - - void log_contexts() { - int num_contexts = get_num_active_contexts(); - if(num_contexts) { - auto contexts = get_active_contexts(); - - s << Color::None << " logged: "; - for(int i = 0; i < num_contexts; ++i) { - s << (i == 0 ? "" : " "); - contexts[i]->stringify(&s); - s << "\n"; - } - } - - s << "\n"; - } - - // this was requested to be made virtual so users could override it - virtual void file_line_to_stream(const char* file, int line, - const char* tail = "") { - s << Color::LightGrey << skipPathFromFilename(file) << (opt.gnu_file_line ? ":" : "(") - << (opt.no_line_numbers ? 0 : line) // 0 or the real num depending on the option - << (opt.gnu_file_line ? ":" : "):") << tail; - } - - void logTestStart() { - if(hasLoggedCurrentTestStart) - return; - - separator_to_stream(); - file_line_to_stream(tc->m_file.c_str(), tc->m_line, "\n"); - if(tc->m_description) - s << Color::Yellow << "DESCRIPTION: " << Color::None << tc->m_description << "\n"; - if(tc->m_test_suite && tc->m_test_suite[0] != '\0') - s << Color::Yellow << "TEST SUITE: " << Color::None << tc->m_test_suite << "\n"; - if(strncmp(tc->m_name, " Scenario:", 11) != 0) - s << Color::Yellow << "TEST CASE: "; - s << Color::None << tc->m_name << "\n"; - - for(size_t i = 0; i < currentSubcaseLevel; ++i) { - if(subcasesStack[i].m_name[0] != '\0') - s << " " << subcasesStack[i].m_name << "\n"; - } - - if(currentSubcaseLevel != subcasesStack.size()) { - s << Color::Yellow << "\nDEEPEST SUBCASE STACK REACHED (DIFFERENT FROM THE CURRENT ONE):\n" << Color::None; - for(size_t i = 0; i < subcasesStack.size(); ++i) { - if(subcasesStack[i].m_name[0] != '\0') - s << " " << subcasesStack[i].m_name << "\n"; - } - } - + std::ostream &s; + bool hasLoggedCurrentTestStart; + std::vector subcasesStack; + size_t currentSubcaseLevel; + DOCTEST_DECLARE_MUTEX(mutex) + + // caching pointers/references to objects of these types - safe to do + const ContextOptions &opt; + const TestCaseData *tc; + + ConsoleReporter(const ContextOptions &co) : s(*co.cout), opt(co) {} + + ConsoleReporter(const ContextOptions &co, std::ostream &ostr) : s(ostr), opt(co) {} + + // ========================================================================================= + // WHAT FOLLOWS ARE HELPERS USED BY THE OVERRIDES OF THE VIRTUAL METHODS OF THE INTERFACE + // ========================================================================================= + + void separator_to_stream() + { + s << Color::Yellow + << "===============================================================================" + "\n"; + } + + const char *getSuccessOrFailString(bool success, assertType::Enum at, const char *success_str) + { + if (success) + return success_str; + return failureString(at); + } + + Color::Enum getSuccessOrFailColor(bool success, assertType::Enum at) + { + return success ? Color::BrightGreen + : (at & assertType::is_warn) ? Color::Yellow + : Color::Red; + } + + void successOrFailColoredStringToStream(bool success, assertType::Enum at, + const char *success_str = "SUCCESS") + { + s << getSuccessOrFailColor(success, at) << getSuccessOrFailString(success, at, success_str) + << ": "; + } + + void log_contexts() + { + int num_contexts = get_num_active_contexts(); + if (num_contexts) { + auto contexts = get_active_contexts(); + + s << Color::None << " logged: "; + for (int i = 0; i < num_contexts; ++i) { + s << (i == 0 ? "" : " "); + contexts[i]->stringify(&s); s << "\n"; - - hasLoggedCurrentTestStart = true; - } - - void printVersion() { - if(opt.no_version == false) - s << Color::Cyan << "[doctest] " << Color::None << "doctest version is \"" - << DOCTEST_VERSION_STR << "\"\n"; - } - - void printIntro() { - if(opt.no_intro == false) { - printVersion(); - s << Color::Cyan << "[doctest] " << Color::None - << "run with \"--" DOCTEST_OPTIONS_PREFIX_DISPLAY "help\" for options\n"; - } - } - - void printHelp() { - int sizePrefixDisplay = static_cast(strlen(DOCTEST_OPTIONS_PREFIX_DISPLAY)); - printVersion(); - // clang-format off + } + } + + s << "\n"; + } + + // this was requested to be made virtual so users could override it + virtual void file_line_to_stream(const char *file, int line, const char *tail = "") + { + s << Color::LightGrey << skipPathFromFilename(file) << (opt.gnu_file_line ? ":" : "(") + << (opt.no_line_numbers ? 0 : line) // 0 or the real num depending on the option + << (opt.gnu_file_line ? ":" : "):") << tail; + } + + void logTestStart() + { + if (hasLoggedCurrentTestStart) + return; + + separator_to_stream(); + file_line_to_stream(tc->m_file.c_str(), tc->m_line, "\n"); + if (tc->m_description) + s << Color::Yellow << "DESCRIPTION: " << Color::None << tc->m_description << "\n"; + if (tc->m_test_suite && tc->m_test_suite[0] != '\0') + s << Color::Yellow << "TEST SUITE: " << Color::None << tc->m_test_suite << "\n"; + if (strncmp(tc->m_name, " Scenario:", 11) != 0) + s << Color::Yellow << "TEST CASE: "; + s << Color::None << tc->m_name << "\n"; + + for (size_t i = 0; i < currentSubcaseLevel; ++i) { + if (subcasesStack[i].m_name[0] != '\0') + s << " " << subcasesStack[i].m_name << "\n"; + } + + if (currentSubcaseLevel != subcasesStack.size()) { + s << Color::Yellow + << "\nDEEPEST SUBCASE STACK REACHED (DIFFERENT FROM THE CURRENT ONE):\n" + << Color::None; + for (size_t i = 0; i < subcasesStack.size(); ++i) { + if (subcasesStack[i].m_name[0] != '\0') + s << " " << subcasesStack[i].m_name << "\n"; + } + } + + s << "\n"; + + hasLoggedCurrentTestStart = true; + } + + void printVersion() + { + if (opt.no_version == false) + s << Color::Cyan << "[doctest] " << Color::None << "doctest version is \"" + << DOCTEST_VERSION_STR << "\"\n"; + } + + void printIntro() + { + if (opt.no_intro == false) { + printVersion(); + s << Color::Cyan << "[doctest] " << Color::None + << "run with \"--" DOCTEST_OPTIONS_PREFIX_DISPLAY "help\" for options\n"; + } + } + + void printHelp() + { + int sizePrefixDisplay = static_cast(strlen(DOCTEST_OPTIONS_PREFIX_DISPLAY)); + printVersion(); + // clang-format off s << Color::Cyan << "[doctest]\n" << Color::None; s << Color::Cyan << "[doctest] " << Color::None; s << "boolean values: \"1/on/yes/true\" or \"0/off/no/false\"\n"; @@ -6184,228 +6657,255 @@ namespace { s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nln, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-line-numbers= " << Whitespace(sizePrefixDisplay*1) << "0 instead of real line numbers in output\n"; // ================================================================================== << 79 - // clang-format on - - s << Color::Cyan << "\n[doctest] " << Color::None; - s << "for more information visit the project documentation\n\n"; - } - - void printRegisteredReporters() { - printVersion(); - auto printReporters = [this] (const reporterMap& reporters, const char* type) { - if(reporters.size()) { - s << Color::Cyan << "[doctest] " << Color::None << "listing all registered " << type << "\n"; - for(auto& curr : reporters) - s << "priority: " << std::setw(5) << curr.first.first - << " name: " << curr.first.second << "\n"; - } - }; - printReporters(getListeners(), "listeners"); - printReporters(getReporters(), "reporters"); - } - - // ========================================================================================= - // WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE - // ========================================================================================= - - void report_query(const QueryData& in) override { - if(opt.version) { - printVersion(); - } else if(opt.help) { - printHelp(); - } else if(opt.list_reporters) { - printRegisteredReporters(); - } else if(opt.count || opt.list_test_cases) { - if(opt.list_test_cases) { - s << Color::Cyan << "[doctest] " << Color::None - << "listing all test case names\n"; - separator_to_stream(); - } - - for(unsigned i = 0; i < in.num_data; ++i) - s << Color::None << in.data[i]->m_name << "\n"; - - separator_to_stream(); - - s << Color::Cyan << "[doctest] " << Color::None - << "unskipped test cases passing the current filters: " - << g_cs->numTestCasesPassingFilters << "\n"; - - } else if(opt.list_test_suites) { - s << Color::Cyan << "[doctest] " << Color::None << "listing all test suites\n"; - separator_to_stream(); - - for(unsigned i = 0; i < in.num_data; ++i) - s << Color::None << in.data[i]->m_test_suite << "\n"; - - separator_to_stream(); - - s << Color::Cyan << "[doctest] " << Color::None - << "unskipped test cases passing the current filters: " - << g_cs->numTestCasesPassingFilters << "\n"; - s << Color::Cyan << "[doctest] " << Color::None - << "test suites with unskipped test cases passing the current filters: " - << g_cs->numTestSuitesPassingFilters << "\n"; - } - } - - void test_run_start() override { - if(!opt.minimal) - printIntro(); - } - - void test_run_end(const TestRunStats& p) override { - if(opt.minimal && p.numTestCasesFailed == 0) - return; - - separator_to_stream(); - s << std::dec; - - auto totwidth = int(std::ceil(log10(static_cast(std::max(p.numTestCasesPassingFilters, static_cast(p.numAsserts))) + 1))); - auto passwidth = int(std::ceil(log10(static_cast(std::max(p.numTestCasesPassingFilters - p.numTestCasesFailed, static_cast(p.numAsserts - p.numAssertsFailed))) + 1))); - auto failwidth = int(std::ceil(log10(static_cast(std::max(p.numTestCasesFailed, static_cast(p.numAssertsFailed))) + 1))); - const bool anythingFailed = p.numTestCasesFailed > 0 || p.numAssertsFailed > 0; - s << Color::Cyan << "[doctest] " << Color::None << "test cases: " << std::setw(totwidth) - << p.numTestCasesPassingFilters << " | " - << ((p.numTestCasesPassingFilters == 0 || anythingFailed) ? Color::None : - Color::Green) - << std::setw(passwidth) << p.numTestCasesPassingFilters - p.numTestCasesFailed << " passed" - << Color::None << " | " << (p.numTestCasesFailed > 0 ? Color::Red : Color::None) - << std::setw(failwidth) << p.numTestCasesFailed << " failed" << Color::None << " |"; - if(opt.no_skipped_summary == false) { - const int numSkipped = p.numTestCases - p.numTestCasesPassingFilters; - s << " " << (numSkipped == 0 ? Color::None : Color::Yellow) << numSkipped - << " skipped" << Color::None; - } - s << "\n"; - s << Color::Cyan << "[doctest] " << Color::None << "assertions: " << std::setw(totwidth) - << p.numAsserts << " | " - << ((p.numAsserts == 0 || anythingFailed) ? Color::None : Color::Green) - << std::setw(passwidth) << (p.numAsserts - p.numAssertsFailed) << " passed" << Color::None - << " | " << (p.numAssertsFailed > 0 ? Color::Red : Color::None) << std::setw(failwidth) - << p.numAssertsFailed << " failed" << Color::None << " |\n"; - s << Color::Cyan << "[doctest] " << Color::None - << "Status: " << (p.numTestCasesFailed > 0 ? Color::Red : Color::Green) - << ((p.numTestCasesFailed > 0) ? "FAILURE!" : "SUCCESS!") << Color::None << std::endl; - } - - void test_case_start(const TestCaseData& in) override { - hasLoggedCurrentTestStart = false; - tc = ∈ - subcasesStack.clear(); - currentSubcaseLevel = 0; - } - - void test_case_reenter(const TestCaseData&) override { - subcasesStack.clear(); - } + // clang-format on - void test_case_end(const CurrentTestCaseStats& st) override { - if(tc->m_no_output) - return; - - // log the preamble of the test case only if there is something - // else to print - something other than that an assert has failed - if(opt.duration || - (st.failure_flags && st.failure_flags != static_cast(TestCaseFailureReason::AssertFailure))) - logTestStart(); - - if(opt.duration) - s << Color::None << std::setprecision(6) << std::fixed << st.seconds - << " s: " << tc->m_name << "\n"; - - if(st.failure_flags & TestCaseFailureReason::Timeout) - s << Color::Red << "Test case exceeded time limit of " << std::setprecision(6) - << std::fixed << tc->m_timeout << "!\n"; - - if(st.failure_flags & TestCaseFailureReason::ShouldHaveFailedButDidnt) { - s << Color::Red << "Should have failed but didn't! Marking it as failed!\n"; - } else if(st.failure_flags & TestCaseFailureReason::ShouldHaveFailedAndDid) { - s << Color::Yellow << "Failed as expected so marking it as not failed\n"; - } else if(st.failure_flags & TestCaseFailureReason::CouldHaveFailedAndDid) { - s << Color::Yellow << "Allowed to fail so marking it as not failed\n"; - } else if(st.failure_flags & TestCaseFailureReason::DidntFailExactlyNumTimes) { - s << Color::Red << "Didn't fail exactly " << tc->m_expected_failures - << " times so marking it as failed!\n"; - } else if(st.failure_flags & TestCaseFailureReason::FailedExactlyNumTimes) { - s << Color::Yellow << "Failed exactly " << tc->m_expected_failures - << " times as expected so marking it as not failed!\n"; - } - if(st.failure_flags & TestCaseFailureReason::TooManyFailedAsserts) { - s << Color::Red << "Aborting - too many failed asserts!\n"; - } - s << Color::None; // lgtm [cpp/useless-expression] - } + s << Color::Cyan << "\n[doctest] " << Color::None; + s << "for more information visit the project documentation\n\n"; + } + + void printRegisteredReporters() + { + printVersion(); + auto printReporters = [this](const reporterMap &reporters, const char *type) { + if (reporters.size()) { + s << Color::Cyan << "[doctest] " << Color::None << "listing all registered " << type + << "\n"; + for (auto &curr : reporters) + s << "priority: " << std::setw(5) << curr.first.first + << " name: " << curr.first.second << "\n"; + } + }; + printReporters(getListeners(), "listeners"); + printReporters(getReporters(), "reporters"); + } - void test_case_exception(const TestCaseException& e) override { - DOCTEST_LOCK_MUTEX(mutex) - if(tc->m_no_output) - return; - - logTestStart(); - - file_line_to_stream(tc->m_file.c_str(), tc->m_line, " "); - successOrFailColoredStringToStream(false, e.is_crash ? assertType::is_require : - assertType::is_check); - s << Color::Red << (e.is_crash ? "test case CRASHED: " : "test case THREW exception: ") - << Color::Cyan << e.error_string << "\n"; - - int num_stringified_contexts = get_num_stringified_contexts(); - if(num_stringified_contexts) { - auto stringified_contexts = get_stringified_contexts(); - s << Color::None << " logged: "; - for(int i = num_stringified_contexts; i > 0; --i) { - s << (i == num_stringified_contexts ? "" : " ") - << stringified_contexts[i - 1] << "\n"; - } - } - s << "\n" << Color::None; - } + // ========================================================================================= + // WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE + // ========================================================================================= - void subcase_start(const SubcaseSignature& subc) override { - subcasesStack.push_back(subc); - ++currentSubcaseLevel; - hasLoggedCurrentTestStart = false; + void report_query(const QueryData &in) override + { + if (opt.version) { + printVersion(); } - - void subcase_end() override { - --currentSubcaseLevel; - hasLoggedCurrentTestStart = false; + else if (opt.help) { + printHelp(); } - - void log_assert(const AssertData& rb) override { - if((!rb.m_failed && !opt.success) || tc->m_no_output) - return; - - DOCTEST_LOCK_MUTEX(mutex) - - logTestStart(); - - file_line_to_stream(rb.m_file, rb.m_line, " "); - successOrFailColoredStringToStream(!rb.m_failed, rb.m_at); - - fulltext_log_assert_to_stream(s, rb); - - log_contexts(); + else if (opt.list_reporters) { + printRegisteredReporters(); } + else if (opt.count || opt.list_test_cases) { + if (opt.list_test_cases) { + s << Color::Cyan << "[doctest] " << Color::None << "listing all test case names\n"; + separator_to_stream(); + } + + for (unsigned i = 0; i < in.num_data; ++i) + s << Color::None << in.data[i]->m_name << "\n"; + + separator_to_stream(); + + s << Color::Cyan << "[doctest] " << Color::None + << "unskipped test cases passing the current filters: " + << g_cs->numTestCasesPassingFilters << "\n"; + } + else if (opt.list_test_suites) { + s << Color::Cyan << "[doctest] " << Color::None << "listing all test suites\n"; + separator_to_stream(); + + for (unsigned i = 0; i < in.num_data; ++i) + s << Color::None << in.data[i]->m_test_suite << "\n"; + + separator_to_stream(); + + s << Color::Cyan << "[doctest] " << Color::None + << "unskipped test cases passing the current filters: " + << g_cs->numTestCasesPassingFilters << "\n"; + s << Color::Cyan << "[doctest] " << Color::None + << "test suites with unskipped test cases passing the current filters: " + << g_cs->numTestSuitesPassingFilters << "\n"; + } + } + + void test_run_start() override + { + if (!opt.minimal) + printIntro(); + } + + void test_run_end(const TestRunStats &p) override + { + if (opt.minimal && p.numTestCasesFailed == 0) + return; + + separator_to_stream(); + s << std::dec; + + auto totwidth = + int(std::ceil(log10(static_cast(std::max(p.numTestCasesPassingFilters, + static_cast(p.numAsserts))) + + 1))); + auto passwidth = + int(std::ceil(log10(static_cast(std::max( + p.numTestCasesPassingFilters - p.numTestCasesFailed, + static_cast(p.numAsserts - p.numAssertsFailed))) + + 1))); + auto failwidth = int( + std::ceil(log10(static_cast(std::max( + p.numTestCasesFailed, static_cast(p.numAssertsFailed))) + + 1))); + const bool anythingFailed = p.numTestCasesFailed > 0 || p.numAssertsFailed > 0; + s << Color::Cyan << "[doctest] " << Color::None << "test cases: " << std::setw(totwidth) + << p.numTestCasesPassingFilters << " | " + << ((p.numTestCasesPassingFilters == 0 || anythingFailed) ? Color::None : Color::Green) + << std::setw(passwidth) << p.numTestCasesPassingFilters - p.numTestCasesFailed + << " passed" << Color::None << " | " + << (p.numTestCasesFailed > 0 ? Color::Red : Color::None) << std::setw(failwidth) + << p.numTestCasesFailed << " failed" << Color::None << " |"; + if (opt.no_skipped_summary == false) { + const int numSkipped = p.numTestCases - p.numTestCasesPassingFilters; + s << " " << (numSkipped == 0 ? Color::None : Color::Yellow) << numSkipped << " skipped" + << Color::None; + } + s << "\n"; + s << Color::Cyan << "[doctest] " << Color::None << "assertions: " << std::setw(totwidth) + << p.numAsserts << " | " + << ((p.numAsserts == 0 || anythingFailed) ? Color::None : Color::Green) + << std::setw(passwidth) << (p.numAsserts - p.numAssertsFailed) << " passed" << Color::None + << " | " << (p.numAssertsFailed > 0 ? Color::Red : Color::None) << std::setw(failwidth) + << p.numAssertsFailed << " failed" << Color::None << " |\n"; + s << Color::Cyan << "[doctest] " << Color::None + << "Status: " << (p.numTestCasesFailed > 0 ? Color::Red : Color::Green) + << ((p.numTestCasesFailed > 0) ? "FAILURE!" : "SUCCESS!") << Color::None << std::endl; + } + + void test_case_start(const TestCaseData &in) override + { + hasLoggedCurrentTestStart = false; + tc = ∈ + subcasesStack.clear(); + currentSubcaseLevel = 0; + } + + void test_case_reenter(const TestCaseData &) override { subcasesStack.clear(); } + + void test_case_end(const CurrentTestCaseStats &st) override + { + if (tc->m_no_output) + return; + + // log the preamble of the test case only if there is something + // else to print - something other than that an assert has failed + if (opt.duration || + (st.failure_flags && + st.failure_flags != static_cast(TestCaseFailureReason::AssertFailure))) + logTestStart(); + + if (opt.duration) + s << Color::None << std::setprecision(6) << std::fixed << st.seconds + << " s: " << tc->m_name << "\n"; + + if (st.failure_flags & TestCaseFailureReason::Timeout) + s << Color::Red << "Test case exceeded time limit of " << std::setprecision(6) + << std::fixed << tc->m_timeout << "!\n"; + + if (st.failure_flags & TestCaseFailureReason::ShouldHaveFailedButDidnt) { + s << Color::Red << "Should have failed but didn't! Marking it as failed!\n"; + } + else if (st.failure_flags & TestCaseFailureReason::ShouldHaveFailedAndDid) { + s << Color::Yellow << "Failed as expected so marking it as not failed\n"; + } + else if (st.failure_flags & TestCaseFailureReason::CouldHaveFailedAndDid) { + s << Color::Yellow << "Allowed to fail so marking it as not failed\n"; + } + else if (st.failure_flags & TestCaseFailureReason::DidntFailExactlyNumTimes) { + s << Color::Red << "Didn't fail exactly " << tc->m_expected_failures + << " times so marking it as failed!\n"; + } + else if (st.failure_flags & TestCaseFailureReason::FailedExactlyNumTimes) { + s << Color::Yellow << "Failed exactly " << tc->m_expected_failures + << " times as expected so marking it as not failed!\n"; + } + if (st.failure_flags & TestCaseFailureReason::TooManyFailedAsserts) { + s << Color::Red << "Aborting - too many failed asserts!\n"; + } + s << Color::None; // lgtm [cpp/useless-expression] + } + + void test_case_exception(const TestCaseException &e) override + { + DOCTEST_LOCK_MUTEX(mutex) + if (tc->m_no_output) + return; + + logTestStart(); + + file_line_to_stream(tc->m_file.c_str(), tc->m_line, " "); + successOrFailColoredStringToStream(false, e.is_crash ? assertType::is_require + : assertType::is_check); + s << Color::Red << (e.is_crash ? "test case CRASHED: " : "test case THREW exception: ") + << Color::Cyan << e.error_string << "\n"; + + int num_stringified_contexts = get_num_stringified_contexts(); + if (num_stringified_contexts) { + auto stringified_contexts = get_stringified_contexts(); + s << Color::None << " logged: "; + for (int i = num_stringified_contexts; i > 0; --i) { + s << (i == num_stringified_contexts ? "" : " ") << stringified_contexts[i - 1] + << "\n"; + } + } + s << "\n" << Color::None; + } + + void subcase_start(const SubcaseSignature &subc) override + { + subcasesStack.push_back(subc); + ++currentSubcaseLevel; + hasLoggedCurrentTestStart = false; + } + + void subcase_end() override + { + --currentSubcaseLevel; + hasLoggedCurrentTestStart = false; + } + + void log_assert(const AssertData &rb) override + { + if ((!rb.m_failed && !opt.success) || tc->m_no_output) + return; + + DOCTEST_LOCK_MUTEX(mutex) + + logTestStart(); + + file_line_to_stream(rb.m_file, rb.m_line, " "); + successOrFailColoredStringToStream(!rb.m_failed, rb.m_at); + + fulltext_log_assert_to_stream(s, rb); - void log_message(const MessageData& mb) override { - if(tc->m_no_output) - return; + log_contexts(); + } - DOCTEST_LOCK_MUTEX(mutex) + void log_message(const MessageData &mb) override + { + if (tc->m_no_output) + return; - logTestStart(); + DOCTEST_LOCK_MUTEX(mutex) + + logTestStart(); - file_line_to_stream(mb.m_file, mb.m_line, " "); - s << getSuccessOrFailColor(false, mb.m_severity) - << getSuccessOrFailString(mb.m_severity & assertType::is_warn, mb.m_severity, - "MESSAGE") << ": "; - s << Color::None << mb.m_string << "\n"; - log_contexts(); - } + file_line_to_stream(mb.m_file, mb.m_line, " "); + s << getSuccessOrFailColor(false, mb.m_severity) + << getSuccessOrFailString(mb.m_severity & assertType::is_warn, mb.m_severity, "MESSAGE") + << ": "; + s << Color::None << mb.m_string << "\n"; + log_contexts(); + } - void test_case_skipped(const TestCaseData&) override {} + void test_case_skipped(const TestCaseData &) override {} }; DOCTEST_REGISTER_REPORTER("console", 0, ConsoleReporter); @@ -6413,201 +6913,211 @@ namespace { #ifdef DOCTEST_PLATFORM_WINDOWS struct DebugOutputWindowReporter : public ConsoleReporter { - DOCTEST_THREAD_LOCAL static std::ostringstream oss; + DOCTEST_THREAD_LOCAL static std::ostringstream oss; - DebugOutputWindowReporter(const ContextOptions& co) - : ConsoleReporter(co, oss) {} + DebugOutputWindowReporter(const ContextOptions &co) : ConsoleReporter(co, oss) {} #define DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(func, type, arg) \ - void func(type arg) override { \ - bool with_col = g_no_colors; \ - g_no_colors = false; \ - ConsoleReporter::func(arg); \ - if(oss.tellp() != std::streampos{}) { \ - DOCTEST_OUTPUT_DEBUG_STRING(oss.str().c_str()); \ - oss.str(""); \ - } \ - g_no_colors = with_col; \ - } - - DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_run_start, DOCTEST_EMPTY, DOCTEST_EMPTY) - DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_run_end, const TestRunStats&, in) - DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_start, const TestCaseData&, in) - DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_reenter, const TestCaseData&, in) - DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_end, const CurrentTestCaseStats&, in) - DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_exception, const TestCaseException&, in) - DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(subcase_start, const SubcaseSignature&, in) - DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(subcase_end, DOCTEST_EMPTY, DOCTEST_EMPTY) - DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(log_assert, const AssertData&, in) - DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(log_message, const MessageData&, in) - DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_skipped, const TestCaseData&, in) + void func(type arg) override \ + { \ + bool with_col = g_no_colors; \ + g_no_colors = false; \ + ConsoleReporter::func(arg); \ + if (oss.tellp() != std::streampos{}) { \ + DOCTEST_OUTPUT_DEBUG_STRING(oss.str().c_str()); \ + oss.str(""); \ + } \ + g_no_colors = with_col; \ + } + + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_run_start, DOCTEST_EMPTY, DOCTEST_EMPTY) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_run_end, const TestRunStats &, in) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_start, const TestCaseData &, in) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_reenter, const TestCaseData &, in) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_end, const CurrentTestCaseStats &, in) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_exception, const TestCaseException &, in) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(subcase_start, const SubcaseSignature &, in) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(subcase_end, DOCTEST_EMPTY, DOCTEST_EMPTY) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(log_assert, const AssertData &, in) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(log_message, const MessageData &, in) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_skipped, const TestCaseData &, in) }; DOCTEST_THREAD_LOCAL std::ostringstream DebugOutputWindowReporter::oss; #endif // DOCTEST_PLATFORM_WINDOWS // the implementation of parseOption() - bool parseOptionImpl(int argc, const char* const* argv, const char* pattern, String* value) { - // going from the end to the beginning and stopping on the first occurrence from the end - for(int i = argc; i > 0; --i) { - auto index = i - 1; - auto temp = std::strstr(argv[index], pattern); - if(temp && (value || strlen(temp) == strlen(pattern))) { //!OCLINT prefer early exits and continue - // eliminate matches in which the chars before the option are not '-' - bool noBadCharsFound = true; - auto curr = argv[index]; - while(curr != temp) { - if(*curr++ != '-') { - noBadCharsFound = false; - break; - } - } - if(noBadCharsFound && argv[index][0] == '-') { - if(value) { - // parsing the value of an option - temp += strlen(pattern); - const unsigned len = strlen(temp); - if(len) { - *value = temp; - return true; - } - } else { - // just a flag - no value - return true; - } - } + bool parseOptionImpl(int argc, const char *const *argv, const char *pattern, String *value) + { + // going from the end to the beginning and stopping on the first occurrence from the end + for (int i = argc; i > 0; --i) { + auto index = i - 1; + auto temp = std::strstr(argv[index], pattern); + if (temp && + (value || strlen(temp) == strlen(pattern))) { //! OCLINT prefer early exits and continue + // eliminate matches in which the chars before the option are not '-' + bool noBadCharsFound = true; + auto curr = argv[index]; + while (curr != temp) { + if (*curr++ != '-') { + noBadCharsFound = false; + break; + } + } + if (noBadCharsFound && argv[index][0] == '-') { + if (value) { + // parsing the value of an option + temp += strlen(pattern); + const unsigned len = strlen(temp); + if (len) { + *value = temp; + return true; + } + } + else { + // just a flag - no value + return true; } + } } - return false; + } + return false; } // parses an option and returns the string after the '=' character - bool parseOption(int argc, const char* const* argv, const char* pattern, String* value = nullptr, - const String& defaultVal = String()) { - if(value) - *value = defaultVal; + bool parseOption(int argc, const char *const *argv, const char *pattern, + String *value = nullptr, const String &defaultVal = String()) + { + if (value) + *value = defaultVal; #ifndef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS - // offset (normally 3 for "dt-") to skip prefix - if(parseOptionImpl(argc, argv, pattern + strlen(DOCTEST_CONFIG_OPTIONS_PREFIX), value)) - return true; + // offset (normally 3 for "dt-") to skip prefix + if (parseOptionImpl(argc, argv, pattern + strlen(DOCTEST_CONFIG_OPTIONS_PREFIX), value)) + return true; #endif // DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS - return parseOptionImpl(argc, argv, pattern, value); + return parseOptionImpl(argc, argv, pattern, value); } // locates a flag on the command line - bool parseFlag(int argc, const char* const* argv, const char* pattern) { - return parseOption(argc, argv, pattern); + bool parseFlag(int argc, const char *const *argv, const char *pattern) + { + return parseOption(argc, argv, pattern); } // parses a comma separated list of words after a pattern in one of the arguments in argv - bool parseCommaSepArgs(int argc, const char* const* argv, const char* pattern, - std::vector& res) { - String filtersString; - if(parseOption(argc, argv, pattern, &filtersString)) { - // tokenize with "," as a separator, unless escaped with backslash - std::ostringstream s; - auto flush = [&s, &res]() { - auto string = s.str(); - if(string.size() > 0) { - res.push_back(string.c_str()); - } - s.str(""); - }; - - bool seenBackslash = false; - const char* current = filtersString.c_str(); - const char* end = current + strlen(current); - while(current != end) { - char character = *current++; - if(seenBackslash) { - seenBackslash = false; - if(character == ',' || character == '\\') { - s.put(character); - continue; - } - s.put('\\'); - } - if(character == '\\') { - seenBackslash = true; - } else if(character == ',') { - flush(); - } else { - s.put(character); - } - } + bool parseCommaSepArgs(int argc, const char *const *argv, const char *pattern, + std::vector &res) + { + String filtersString; + if (parseOption(argc, argv, pattern, &filtersString)) { + // tokenize with "," as a separator, unless escaped with backslash + std::ostringstream s; + auto flush = [&s, &res]() { + auto string = s.str(); + if (string.size() > 0) { + res.push_back(string.c_str()); + } + s.str(""); + }; - if(seenBackslash) { - s.put('\\'); + bool seenBackslash = false; + const char *current = filtersString.c_str(); + const char *end = current + strlen(current); + while (current != end) { + char character = *current++; + if (seenBackslash) { + seenBackslash = false; + if (character == ',' || character == '\\') { + s.put(character); + continue; } + s.put('\\'); + } + if (character == '\\') { + seenBackslash = true; + } + else if (character == ',') { flush(); - return true; + } + else { + s.put(character); + } } - return false; + + if (seenBackslash) { + s.put('\\'); + } + flush(); + return true; + } + return false; } - enum optionType - { - option_bool, - option_int - }; + enum optionType { option_bool, option_int }; // parses an int/bool option from the command line - bool parseIntOption(int argc, const char* const* argv, const char* pattern, optionType type, - int& res) { - String parsedValue; - if(!parseOption(argc, argv, pattern, &parsedValue)) - return false; - - if(type) { - // integer - // TODO: change this to use std::stoi or something else! currently it uses undefined behavior - assumes '0' on failed parse... - int theInt = std::atoi(parsedValue.c_str()); - if (theInt != 0) { - res = theInt; //!OCLINT parameter reassignment - return true; - } - } else { - // boolean - const char positive[][5] = { "1", "true", "on", "yes" }; // 5 - strlen("true") + 1 - const char negative[][6] = { "0", "false", "off", "no" }; // 6 - strlen("false") + 1 - - // if the value matches any of the positive/negative possibilities - for (unsigned i = 0; i < 4; i++) { - if (parsedValue.compare(positive[i], true) == 0) { - res = 1; //!OCLINT parameter reassignment - return true; - } - if (parsedValue.compare(negative[i], true) == 0) { - res = 0; //!OCLINT parameter reassignment - return true; - } - } - } + bool parseIntOption(int argc, const char *const *argv, const char *pattern, optionType type, + int &res) + { + String parsedValue; + if (!parseOption(argc, argv, pattern, &parsedValue)) return false; + + if (type) { + // integer + // TODO: change this to use std::stoi or something else! currently it uses undefined + // behavior - assumes '0' on failed parse... + int theInt = std::atoi(parsedValue.c_str()); + if (theInt != 0) { + res = theInt; //! OCLINT parameter reassignment + return true; + } + } + else { + // boolean + const char positive[][5] = {"1", "true", "on", "yes"}; // 5 - strlen("true") + 1 + const char negative[][6] = {"0", "false", "off", "no"}; // 6 - strlen("false") + 1 + + // if the value matches any of the positive/negative possibilities + for (unsigned i = 0; i < 4; i++) { + if (parsedValue.compare(positive[i], true) == 0) { + res = 1; //! OCLINT parameter reassignment + return true; + } + if (parsedValue.compare(negative[i], true) == 0) { + res = 0; //! OCLINT parameter reassignment + return true; + } + } + } + return false; } -} // namespace + } // namespace -Context::Context(int argc, const char* const* argv) - : p(new detail::ContextState) { + Context::Context(int argc, const char *const *argv) : p(new detail::ContextState) + { parseArgs(argc, argv, true); - if(argc) - p->binary_name = argv[0]; -} - -Context::~Context() { - if(g_cs == p) - g_cs = nullptr; + if (argc) + p->binary_name = argv[0]; + } + + Context::~Context() + { + if (g_cs == p) + g_cs = nullptr; delete p; -} + } -void Context::applyCommandLine(int argc, const char* const* argv) { + void Context::applyCommandLine(int argc, const char *const *argv) + { parseArgs(argc, argv); - if(argc) - p->binary_name = argv[0]; -} + if (argc) + p->binary_name = argv[0]; + } -// parses args -void Context::parseArgs(int argc, const char* const* argv, bool withDefaults) { + // parses args + void Context::parseArgs(int argc, const char *const *argv, bool withDefaults) + { using namespace detail; // clang-format off @@ -6635,27 +7145,27 @@ void Context::parseArgs(int argc, const char* const* argv, bool withDefaults) { String strRes; #define DOCTEST_PARSE_AS_BOOL_OR_FLAG(name, sname, var, default) \ - if(parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", option_bool, intRes) || \ - parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", option_bool, intRes)) \ - p->var = static_cast(intRes); \ - else if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name) || \ - parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname)) \ - p->var = true; \ - else if(withDefaults) \ - p->var = default + if (parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", option_bool, intRes) || \ + parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", option_bool, intRes)) \ + p->var = static_cast(intRes); \ + else if (parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name) || \ + parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname)) \ + p->var = true; \ + else if (withDefaults) \ + p->var = default #define DOCTEST_PARSE_INT_OPTION(name, sname, var, default) \ - if(parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", option_int, intRes) || \ - parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", option_int, intRes)) \ - p->var = intRes; \ - else if(withDefaults) \ - p->var = default + if (parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", option_int, intRes) || \ + parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", option_int, intRes)) \ + p->var = intRes; \ + else if (withDefaults) \ + p->var = default #define DOCTEST_PARSE_STR_OPTION(name, sname, var, default) \ - if(parseOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", &strRes, default) || \ - parseOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", &strRes, default) || \ - withDefaults) \ - p->var = strRes + if (parseOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", &strRes, default) || \ + parseOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", &strRes, default) || \ + withDefaults) \ + p->var = strRes // clang-format off DOCTEST_PARSE_STR_OPTION("out", "o", out, ""); @@ -6691,110 +7201,116 @@ void Context::parseArgs(int argc, const char* const* argv, bool withDefaults) { DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-time-in-output", "ntio", no_time_in_output, false); // clang-format on - if(withDefaults) { - p->help = false; - p->version = false; - p->count = false; - p->list_test_cases = false; - p->list_test_suites = false; - p->list_reporters = false; - } - if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "help") || - parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "h") || - parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "?")) { - p->help = true; - p->exit = true; - } - if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "version") || - parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "v")) { - p->version = true; - p->exit = true; - } - if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "count") || - parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "c")) { - p->count = true; - p->exit = true; - } - if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "list-test-cases") || - parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "ltc")) { - p->list_test_cases = true; - p->exit = true; - } - if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "list-test-suites") || - parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "lts")) { - p->list_test_suites = true; - p->exit = true; - } - if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "list-reporters") || - parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "lr")) { - p->list_reporters = true; - p->exit = true; + if (withDefaults) { + p->help = false; + p->version = false; + p->count = false; + p->list_test_cases = false; + p->list_test_suites = false; + p->list_reporters = false; } -} + if (parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "help") || + parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "h") || + parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "?")) { + p->help = true; + p->exit = true; + } + if (parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "version") || + parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "v")) { + p->version = true; + p->exit = true; + } + if (parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "count") || + parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "c")) { + p->count = true; + p->exit = true; + } + if (parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "list-test-cases") || + parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "ltc")) { + p->list_test_cases = true; + p->exit = true; + } + if (parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "list-test-suites") || + parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "lts")) { + p->list_test_suites = true; + p->exit = true; + } + if (parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "list-reporters") || + parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "lr")) { + p->list_reporters = true; + p->exit = true; + } + } -// allows the user to add procedurally to the filters from the command line -void Context::addFilter(const char* filter, const char* value) { setOption(filter, value); } + // allows the user to add procedurally to the filters from the command line + void Context::addFilter(const char *filter, const char *value) { setOption(filter, value); } -// allows the user to clear all filters from the command line -void Context::clearFilters() { - for(auto& curr : p->filters) - curr.clear(); -} + // allows the user to clear all filters from the command line + void Context::clearFilters() + { + for (auto &curr : p->filters) + curr.clear(); + } -// allows the user to override procedurally the bool options from the command line -void Context::setOption(const char* option, bool value) { + // allows the user to override procedurally the bool options from the command line + void Context::setOption(const char *option, bool value) + { setOption(option, value ? "true" : "false"); -} + } -// allows the user to override procedurally the int options from the command line -void Context::setOption(const char* option, int value) { + // allows the user to override procedurally the int options from the command line + void Context::setOption(const char *option, int value) + { setOption(option, toString(value).c_str()); -} + } -// allows the user to override procedurally the string options from the command line -void Context::setOption(const char* option, const char* value) { + // allows the user to override procedurally the string options from the command line + void Context::setOption(const char *option, const char *value) + { auto argv = String("-") + option + "=" + value; auto lvalue = argv.c_str(); parseArgs(1, &lvalue); -} + } -// users should query this in their main() and exit the program if true -bool Context::shouldExit() { return p->exit; } + // users should query this in their main() and exit the program if true + bool Context::shouldExit() { return p->exit; } -void Context::setAsDefaultForAssertsOutOfTestCases() { g_cs = p; } + void Context::setAsDefaultForAssertsOutOfTestCases() { g_cs = p; } -void Context::setAssertHandler(detail::assert_handler ah) { p->ah = ah; } + void Context::setAssertHandler(detail::assert_handler ah) { p->ah = ah; } -void Context::setCout(std::ostream* out) { p->cout = out; } + void Context::setCout(std::ostream *out) { p->cout = out; } -static class DiscardOStream : public std::ostream -{ -private: + static class DiscardOStream : public std::ostream + { + private: class : public std::streambuf { private: - // allowing some buffering decreases the amount of calls to overflow - char buf[1024]; + // allowing some buffering decreases the amount of calls to overflow + char buf[1024]; protected: - std::streamsize xsputn(const char_type*, std::streamsize count) override { return count; } + std::streamsize xsputn(const char_type *, std::streamsize count) override { return count; } - int_type overflow(int_type ch) override { - setp(std::begin(buf), std::end(buf)); - return traits_type::not_eof(ch); - } + int_type overflow(int_type ch) override + { + setp(std::begin(buf), std::end(buf)); + return traits_type::not_eof(ch); + } } discardBuf; -public: - DiscardOStream() - : std::ostream(&discardBuf) {} -} discardOut; + public: + DiscardOStream() : std::ostream(&discardBuf) {} + } discardOut; -// the main function that does all the filtering and test running -int Context::run() { + // the main function that does all the filtering and test running + int Context::run() + { using namespace detail; - // save the old context state in case such was setup - for using asserts out of a testing context + // save the old context state in case such was setup - for using asserts out of a testing + // context auto old_cs = g_cs; // this is the current contest g_cs = p; @@ -6804,277 +7320,291 @@ int Context::run() { p->resetRunData(); std::fstream fstr; - if(p->cout == nullptr) { - if(p->quiet) { - p->cout = &discardOut; - } else if(p->out.size()) { - // to a file if specified - fstr.open(p->out.c_str(), std::fstream::out); - p->cout = &fstr; - } else { + if (p->cout == nullptr) { + if (p->quiet) { + p->cout = &discardOut; + } + else if (p->out.size()) { + // to a file if specified + fstr.open(p->out.c_str(), std::fstream::out); + p->cout = &fstr; + } + else { #ifndef DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM - // stdout by default - p->cout = &std::cout; -#else // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM - return EXIT_FAILURE; + // stdout by default + p->cout = &std::cout; +#else // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM + return EXIT_FAILURE; #endif // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM - } + } } FatalConditionHandler::allocateAltStackMem(); auto cleanup_and_return = [&]() { - FatalConditionHandler::freeAltStackMem(); + FatalConditionHandler::freeAltStackMem(); - if(fstr.is_open()) - fstr.close(); + if (fstr.is_open()) + fstr.close(); - // restore context - g_cs = old_cs; - is_running_in_test = false; + // restore context + g_cs = old_cs; + is_running_in_test = false; - // we have to free the reporters which were allocated when the run started - for(auto& curr : p->reporters_currently_used) - delete curr; - p->reporters_currently_used.clear(); + // we have to free the reporters which were allocated when the run started + for (auto &curr : p->reporters_currently_used) + delete curr; + p->reporters_currently_used.clear(); - if(p->numTestCasesFailed && !p->no_exitcode) - return EXIT_FAILURE; - return EXIT_SUCCESS; + if (p->numTestCasesFailed && !p->no_exitcode) + return EXIT_FAILURE; + return EXIT_SUCCESS; }; // setup default reporter if none is given through the command line - if(p->filters[8].empty()) - p->filters[8].push_back("console"); + if (p->filters[8].empty()) + p->filters[8].push_back("console"); // check to see if any of the registered reporters has been selected - for(auto& curr : getReporters()) { - if(matchesAny(curr.first.second.c_str(), p->filters[8], false, p->case_sensitive)) - p->reporters_currently_used.push_back(curr.second(*g_cs)); + for (auto &curr : getReporters()) { + if (matchesAny(curr.first.second.c_str(), p->filters[8], false, p->case_sensitive)) + p->reporters_currently_used.push_back(curr.second(*g_cs)); } // TODO: check if there is nothing in reporters_currently_used // prepend all listeners - for(auto& curr : getListeners()) - p->reporters_currently_used.insert(p->reporters_currently_used.begin(), curr.second(*g_cs)); + for (auto &curr : getListeners()) + p->reporters_currently_used.insert(p->reporters_currently_used.begin(), curr.second(*g_cs)); #ifdef DOCTEST_PLATFORM_WINDOWS - if(isDebuggerActive() && p->no_debug_output == false) - p->reporters_currently_used.push_back(new DebugOutputWindowReporter(*g_cs)); + if (isDebuggerActive() && p->no_debug_output == false) + p->reporters_currently_used.push_back(new DebugOutputWindowReporter(*g_cs)); #endif // DOCTEST_PLATFORM_WINDOWS // handle version, help and no_run - if(p->no_run || p->version || p->help || p->list_reporters) { - DOCTEST_ITERATE_THROUGH_REPORTERS(report_query, QueryData()); + if (p->no_run || p->version || p->help || p->list_reporters) { + DOCTEST_ITERATE_THROUGH_REPORTERS(report_query, QueryData()); - return cleanup_and_return(); + return cleanup_and_return(); } - std::vector testArray; - for(auto& curr : getRegisteredTests()) - testArray.push_back(&curr); + std::vector testArray; + for (auto &curr : getRegisteredTests()) + testArray.push_back(&curr); p->numTestCases = testArray.size(); // sort the collected records - if(!testArray.empty()) { - if(p->order_by.compare("file", true) == 0) { - std::sort(testArray.begin(), testArray.end(), fileOrderComparator); - } else if(p->order_by.compare("suite", true) == 0) { - std::sort(testArray.begin(), testArray.end(), suiteOrderComparator); - } else if(p->order_by.compare("name", true) == 0) { - std::sort(testArray.begin(), testArray.end(), nameOrderComparator); - } else if(p->order_by.compare("rand", true) == 0) { - std::srand(p->rand_seed); - - // random_shuffle implementation - const auto first = &testArray[0]; - for(size_t i = testArray.size() - 1; i > 0; --i) { - int idxToSwap = std::rand() % (i + 1); - - const auto temp = first[i]; - - first[i] = first[idxToSwap]; - first[idxToSwap] = temp; - } - } else if(p->order_by.compare("none", true) == 0) { - // means no sorting - beneficial for death tests which call into the executable - // with a specific test case in mind - we don't want to slow down the startup times - } + if (!testArray.empty()) { + if (p->order_by.compare("file", true) == 0) { + std::sort(testArray.begin(), testArray.end(), fileOrderComparator); + } + else if (p->order_by.compare("suite", true) == 0) { + std::sort(testArray.begin(), testArray.end(), suiteOrderComparator); + } + else if (p->order_by.compare("name", true) == 0) { + std::sort(testArray.begin(), testArray.end(), nameOrderComparator); + } + else if (p->order_by.compare("rand", true) == 0) { + std::srand(p->rand_seed); + + // random_shuffle implementation + const auto first = &testArray[0]; + for (size_t i = testArray.size() - 1; i > 0; --i) { + int idxToSwap = std::rand() % (i + 1); + + const auto temp = first[i]; + + first[i] = first[idxToSwap]; + first[idxToSwap] = temp; + } + } + else if (p->order_by.compare("none", true) == 0) { + // means no sorting - beneficial for death tests which call into the executable + // with a specific test case in mind - we don't want to slow down the startup times + } } std::set testSuitesPassingFilt; - bool query_mode = p->count || p->list_test_cases || p->list_test_suites; - std::vector queryResults; + bool query_mode = p->count || p->list_test_cases || p->list_test_suites; + std::vector queryResults; - if(!query_mode) - DOCTEST_ITERATE_THROUGH_REPORTERS(test_run_start, DOCTEST_EMPTY); + if (!query_mode) + DOCTEST_ITERATE_THROUGH_REPORTERS(test_run_start, DOCTEST_EMPTY); // invoke the registered functions if they match the filter criteria (or just count them) - for(auto& curr : testArray) { - const auto& tc = *curr; - - bool skip_me = false; - if(tc.m_skip && !p->no_skip) - skip_me = true; - - if(!matchesAny(tc.m_file.c_str(), p->filters[0], true, p->case_sensitive)) - skip_me = true; - if(matchesAny(tc.m_file.c_str(), p->filters[1], false, p->case_sensitive)) - skip_me = true; - if(!matchesAny(tc.m_test_suite, p->filters[2], true, p->case_sensitive)) - skip_me = true; - if(matchesAny(tc.m_test_suite, p->filters[3], false, p->case_sensitive)) - skip_me = true; - if(!matchesAny(tc.m_name, p->filters[4], true, p->case_sensitive)) - skip_me = true; - if(matchesAny(tc.m_name, p->filters[5], false, p->case_sensitive)) - skip_me = true; - - if(!skip_me) - p->numTestCasesPassingFilters++; - - // skip the test if it is not in the execution range - if((p->last < p->numTestCasesPassingFilters && p->first <= p->last) || - (p->first > p->numTestCasesPassingFilters)) - skip_me = true; - - if(skip_me) { - if(!query_mode) - DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_skipped, tc); - continue; - } - - // do not execute the test if we are to only count the number of filter passing tests - if(p->count) - continue; - - // print the name of the test and don't execute it - if(p->list_test_cases) { - queryResults.push_back(&tc); - continue; - } - - // print the name of the test suite if not done already and don't execute it - if(p->list_test_suites) { - if((testSuitesPassingFilt.count(tc.m_test_suite) == 0) && tc.m_test_suite[0] != '\0') { - queryResults.push_back(&tc); - testSuitesPassingFilt.insert(tc.m_test_suite); - p->numTestSuitesPassingFilters++; - } - continue; - } - - // execute the test if it passes all the filtering - { - p->currentTest = &tc; - - p->failure_flags = TestCaseFailureReason::None; - p->seconds = 0; - - // reset atomic counters - p->numAssertsFailedCurrentTest_atomic = 0; - p->numAssertsCurrentTest_atomic = 0; - - p->fullyTraversedSubcases.clear(); - - DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_start, tc); - - p->timer.start(); - - bool run_test = true; - - do { - // reset some of the fields for subcases (except for the set of fully passed ones) - p->reachedLeaf = false; - // May not be empty if previous subcase exited via exception. - p->subcaseStack.clear(); - p->currentSubcaseDepth = 0; - - p->shouldLogCurrentException = true; - - // reset stuff for logging with INFO() - p->stringifiedContexts.clear(); + for (auto &curr : testArray) { + const auto &tc = *curr; + + bool skip_me = false; + if (tc.m_skip && !p->no_skip) + skip_me = true; + + if (!matchesAny(tc.m_file.c_str(), p->filters[0], true, p->case_sensitive)) + skip_me = true; + if (matchesAny(tc.m_file.c_str(), p->filters[1], false, p->case_sensitive)) + skip_me = true; + if (!matchesAny(tc.m_test_suite, p->filters[2], true, p->case_sensitive)) + skip_me = true; + if (matchesAny(tc.m_test_suite, p->filters[3], false, p->case_sensitive)) + skip_me = true; + if (!matchesAny(tc.m_name, p->filters[4], true, p->case_sensitive)) + skip_me = true; + if (matchesAny(tc.m_name, p->filters[5], false, p->case_sensitive)) + skip_me = true; + + if (!skip_me) + p->numTestCasesPassingFilters++; + + // skip the test if it is not in the execution range + if ((p->last < p->numTestCasesPassingFilters && p->first <= p->last) || + (p->first > p->numTestCasesPassingFilters)) + skip_me = true; + + if (skip_me) { + if (!query_mode) + DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_skipped, tc); + continue; + } + + // do not execute the test if we are to only count the number of filter passing tests + if (p->count) + continue; + + // print the name of the test and don't execute it + if (p->list_test_cases) { + queryResults.push_back(&tc); + continue; + } + + // print the name of the test suite if not done already and don't execute it + if (p->list_test_suites) { + if ((testSuitesPassingFilt.count(tc.m_test_suite) == 0) && tc.m_test_suite[0] != '\0') { + queryResults.push_back(&tc); + testSuitesPassingFilt.insert(tc.m_test_suite); + p->numTestSuitesPassingFilters++; + } + continue; + } + + // execute the test if it passes all the filtering + { + p->currentTest = &tc; + + p->failure_flags = TestCaseFailureReason::None; + p->seconds = 0; + + // reset atomic counters + p->numAssertsFailedCurrentTest_atomic = 0; + p->numAssertsCurrentTest_atomic = 0; + + p->fullyTraversedSubcases.clear(); + + DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_start, tc); + + p->timer.start(); + + bool run_test = true; + + do { + // reset some of the fields for subcases (except for the set of fully passed ones) + p->reachedLeaf = false; + // May not be empty if previous subcase exited via exception. + p->subcaseStack.clear(); + p->currentSubcaseDepth = 0; + + p->shouldLogCurrentException = true; + + // reset stuff for logging with INFO() + p->stringifiedContexts.clear(); #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS - try { + try { #endif // DOCTEST_CONFIG_NO_EXCEPTIONS -// MSVC 2015 diagnoses fatalConditionHandler as unused (because reset() is a static method) -DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4101) // unreferenced local variable - FatalConditionHandler fatalConditionHandler; // Handle signals - // execute the test - tc.m_test(); - fatalConditionHandler.reset(); -DOCTEST_MSVC_SUPPRESS_WARNING_POP + // MSVC 2015 diagnoses fatalConditionHandler as unused (because reset() is a static + // method) + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4101) // unreferenced local variable + FatalConditionHandler fatalConditionHandler; // Handle signals + // execute the test + tc.m_test(); + fatalConditionHandler.reset(); + DOCTEST_MSVC_SUPPRESS_WARNING_POP #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS - } catch(const TestFailureException&) { - p->failure_flags |= TestCaseFailureReason::AssertFailure; - } catch(...) { - DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_exception, - {translateActiveException(), false}); - p->failure_flags |= TestCaseFailureReason::Exception; - } + } + catch (const TestFailureException &) { + p->failure_flags |= TestCaseFailureReason::AssertFailure; + } + catch (...) { + DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_exception, + {translateActiveException(), false}); + p->failure_flags |= TestCaseFailureReason::Exception; + } #endif // DOCTEST_CONFIG_NO_EXCEPTIONS - // exit this loop if enough assertions have failed - even if there are more subcases - if(p->abort_after > 0 && - p->numAssertsFailed + p->numAssertsFailedCurrentTest_atomic >= p->abort_after) { - run_test = false; - p->failure_flags |= TestCaseFailureReason::TooManyFailedAsserts; - } + // exit this loop if enough assertions have failed - even if there are more subcases + if (p->abort_after > 0 && + p->numAssertsFailed + p->numAssertsFailedCurrentTest_atomic >= p->abort_after) { + run_test = false; + p->failure_flags |= TestCaseFailureReason::TooManyFailedAsserts; + } - if(!p->nextSubcaseStack.empty() && run_test) - DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_reenter, tc); - if(p->nextSubcaseStack.empty()) - run_test = false; - } while(run_test); + if (!p->nextSubcaseStack.empty() && run_test) + DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_reenter, tc); + if (p->nextSubcaseStack.empty()) + run_test = false; + } while (run_test); - p->finalizeTestCaseData(); + p->finalizeTestCaseData(); - DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_end, *g_cs); + DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_end, *g_cs); - p->currentTest = nullptr; + p->currentTest = nullptr; - // stop executing tests if enough assertions have failed - if(p->abort_after > 0 && p->numAssertsFailed >= p->abort_after) - break; - } + // stop executing tests if enough assertions have failed + if (p->abort_after > 0 && p->numAssertsFailed >= p->abort_after) + break; + } } - if(!query_mode) { - DOCTEST_ITERATE_THROUGH_REPORTERS(test_run_end, *g_cs); - } else { - QueryData qdata; - qdata.run_stats = g_cs; - qdata.data = queryResults.data(); - qdata.num_data = unsigned(queryResults.size()); - DOCTEST_ITERATE_THROUGH_REPORTERS(report_query, qdata); + if (!query_mode) { + DOCTEST_ITERATE_THROUGH_REPORTERS(test_run_end, *g_cs); + } + else { + QueryData qdata; + qdata.run_stats = g_cs; + qdata.data = queryResults.data(); + qdata.num_data = unsigned(queryResults.size()); + DOCTEST_ITERATE_THROUGH_REPORTERS(report_query, qdata); } return cleanup_and_return(); -} + } -DOCTEST_DEFINE_INTERFACE(IReporter) + DOCTEST_DEFINE_INTERFACE(IReporter) -int IReporter::get_num_active_contexts() { return detail::g_infoContexts.size(); } -const IContextScope* const* IReporter::get_active_contexts() { + int IReporter::get_num_active_contexts() { return detail::g_infoContexts.size(); } + const IContextScope *const *IReporter::get_active_contexts() + { return get_num_active_contexts() ? &detail::g_infoContexts[0] : nullptr; -} + } -int IReporter::get_num_stringified_contexts() { return detail::g_cs->stringifiedContexts.size(); } -const String* IReporter::get_stringified_contexts() { + int IReporter::get_num_stringified_contexts() { return detail::g_cs->stringifiedContexts.size(); } + const String *IReporter::get_stringified_contexts() + { return get_num_stringified_contexts() ? &detail::g_cs->stringifiedContexts[0] : nullptr; -} + } -namespace detail { - void registerReporterImpl(const char* name, int priority, reporterCreatorFunc c, bool isReporter) { - if(isReporter) - getReporters().insert(reporterMap::value_type(reporterMap::key_type(priority, name), c)); - else - getListeners().insert(reporterMap::value_type(reporterMap::key_type(priority, name), c)); + namespace detail { + void registerReporterImpl(const char *name, int priority, reporterCreatorFunc c, + bool isReporter) + { + if (isReporter) + getReporters().insert(reporterMap::value_type(reporterMap::key_type(priority, name), c)); + else + getListeners().insert(reporterMap::value_type(reporterMap::key_type(priority, name), c)); } -} // namespace detail + } // namespace detail } // namespace doctest @@ -7082,7 +7612,7 @@ namespace detail { #ifdef DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4007) // 'function' : must be 'attribute' - see issue #182 -int main(int argc, char** argv) { return doctest::Context(argc, argv).run(); } +int main(int argc, char **argv) { return doctest::Context(argc, argv).run(); } DOCTEST_MSVC_SUPPRESS_WARNING_POP #endif // DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN @@ -7104,3 +7634,5 @@ DOCTEST_SUPPRESS_COMMON_WARNINGS_POP #undef NOMINMAX #undef DOCTEST_UNDEF_NOMINMAX #endif // DOCTEST_UNDEF_NOMINMAX + +// NOLINTEND diff --git a/packages/seacas/libraries/ioss/src/exodus/Ioex_Internals.C b/packages/seacas/libraries/ioss/src/exodus/Ioex_Internals.C index efd486274e..4360b18fec 100644 --- a/packages/seacas/libraries/ioss/src/exodus/Ioex_Internals.C +++ b/packages/seacas/libraries/ioss/src/exodus/Ioex_Internals.C @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2022 National Technology & Engineering Solutions +// Copyright(C) 1999-2023 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -367,8 +367,7 @@ SideSet::SideSet(const Ioss::SideSet &other) } Internals::Internals(int exoid, int maximum_name_length, const Ioss::ParallelUtils &util) - : exodusFilePtr(exoid), nodeMapVarID(), elementMapVarID(), - maximumNameLength(maximum_name_length), parallelUtil(util) + : exodusFilePtr(exoid), maximumNameLength(maximum_name_length), parallelUtil(util) { } diff --git a/packages/seacas/libraries/ioss/src/exodus/Ioex_Internals.h b/packages/seacas/libraries/ioss/src/exodus/Ioex_Internals.h index 01a87979a6..cd6671fd22 100644 --- a/packages/seacas/libraries/ioss/src/exodus/Ioex_Internals.h +++ b/packages/seacas/libraries/ioss/src/exodus/Ioex_Internals.h @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2022 National Technology & Engineering Solutions + * Copyright(C) 1999-2023 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * @@ -409,8 +409,8 @@ namespace Ioex { int max_name_length() const { return maximumNameLength; } int exodusFilePtr{0}; - int nodeMapVarID[3]; - int elementMapVarID[2]; + int nodeMapVarID[3]{}; + int elementMapVarID[2]{}; int commIndexVar{0}; int elemCommIndexVar{0}; int maximumNameLength{32}; diff --git a/packages/seacas/libraries/ioss/src/exodus/Ioex_SuperElement.C b/packages/seacas/libraries/ioss/src/exodus/Ioex_SuperElement.C index ad770e1e4e..b727a14859 100644 --- a/packages/seacas/libraries/ioss/src/exodus/Ioex_SuperElement.C +++ b/packages/seacas/libraries/ioss/src/exodus/Ioex_SuperElement.C @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2020 National Technology & Engineering Solutions +// Copyright(C) 1999-2020, 2023 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -264,19 +264,19 @@ int64_t Ioex::SuperElement::internal_put_field_data(const Ioss::Field & /* field Ioss::Property Ioex::SuperElement::get_implicit_property(const std::string &the_name) const { if (Ioss::Utils::str_equal(the_name, "numDOF")) { - return Ioss::Property(the_name, static_cast(numDOF)); + return {the_name, static_cast(numDOF)}; } if (Ioss::Utils::str_equal(the_name, "num_nodes")) { - return Ioss::Property(the_name, static_cast(num_nodes)); + return {the_name, static_cast(num_nodes)}; } if (Ioss::Utils::str_equal(the_name, "numEIG")) { - return Ioss::Property(the_name, static_cast(numEIG)); + return {the_name, static_cast(numEIG)}; } if (Ioss::Utils::str_equal(the_name, "num_dim")) { - return Ioss::Property(the_name, static_cast(num_dim)); + return {the_name, static_cast(num_dim)}; } if (Ioss::Utils::str_equal(the_name, "numConstraints")) { - return Ioss::Property(the_name, static_cast(numDOF) - static_cast(numEIG)); + return {the_name, static_cast(numDOF) - static_cast(numEIG)}; } return Ioss::GroupingEntity::get_implicit_property(the_name); diff --git a/packages/seacas/libraries/ioss/src/exodus/Ioex_Utils.C b/packages/seacas/libraries/ioss/src/exodus/Ioex_Utils.C index d5bcb34be4..dd1b31ceae 100644 --- a/packages/seacas/libraries/ioss/src/exodus/Ioex_Utils.C +++ b/packages/seacas/libraries/ioss/src/exodus/Ioex_Utils.C @@ -482,7 +482,7 @@ namespace Ioex { } } db_has_name = true; - return (std::string(buffer.data())); + return {buffer.data()}; } db_has_name = false; return Ioss::Utils::encode_entity_name(basename, id); diff --git a/packages/seacas/libraries/ioss/src/exonull/Ioexnl_SuperElement.C b/packages/seacas/libraries/ioss/src/exonull/Ioexnl_SuperElement.C index fb690c7882..bc0fcabf91 100644 --- a/packages/seacas/libraries/ioss/src/exonull/Ioexnl_SuperElement.C +++ b/packages/seacas/libraries/ioss/src/exonull/Ioexnl_SuperElement.C @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2020 National Technology & Engineering Solutions +// Copyright(C) 1999-2020, 2023 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -265,19 +265,19 @@ int64_t Ioexnl::SuperElement::internal_put_field_data(const Ioss::Field & /* fie Ioss::Property Ioexnl::SuperElement::get_implicit_property(const std::string &the_name) const { if (Ioss::Utils::str_equal(the_name, "numDOF")) { - return Ioss::Property(the_name, static_cast(numDOF)); + return {the_name, static_cast(numDOF)}; } if (Ioss::Utils::str_equal(the_name, "num_nodes")) { - return Ioss::Property(the_name, static_cast(num_nodes)); + return {the_name, static_cast(num_nodes)}; } if (Ioss::Utils::str_equal(the_name, "numEIG")) { - return Ioss::Property(the_name, static_cast(numEIG)); + return {the_name, static_cast(numEIG)}; } if (Ioss::Utils::str_equal(the_name, "num_dim")) { - return Ioss::Property(the_name, static_cast(num_dim)); + return {the_name, static_cast(num_dim)}; } if (Ioss::Utils::str_equal(the_name, "numConstraints")) { - return Ioss::Property(the_name, static_cast(numDOF) - static_cast(numEIG)); + return {the_name, static_cast(numDOF) - static_cast(numEIG)}; } return Ioss::GroupingEntity::get_implicit_property(the_name); diff --git a/packages/seacas/libraries/ioss/src/generated/Iogn_DashSurfaceMesh.h b/packages/seacas/libraries/ioss/src/generated/Iogn_DashSurfaceMesh.h index 56ec43cb74..e3184db19d 100644 --- a/packages/seacas/libraries/ioss/src/generated/Iogn_DashSurfaceMesh.h +++ b/packages/seacas/libraries/ioss/src/generated/Iogn_DashSurfaceMesh.h @@ -35,9 +35,9 @@ namespace Iogn { inline std::string getTopologyName(Topology topology) { switch (topology) { - case Shell4: return std::string(Ioss::Shell4::name); - case Hex8: return std::string(Ioss::Hex8::name); - case Beam2: return std::string(Ioss::Beam2::name); + case Shell4: return {Ioss::Shell4::name}; + case Hex8: return {Ioss::Hex8::name}; + case Beam2: return {Ioss::Beam2::name}; } throw std::exception(); } diff --git a/packages/seacas/libraries/ioss/src/heartbeat/Iohb_DatabaseIO.C b/packages/seacas/libraries/ioss/src/heartbeat/Iohb_DatabaseIO.C index be08422dbf..2d250e84fa 100644 --- a/packages/seacas/libraries/ioss/src/heartbeat/Iohb_DatabaseIO.C +++ b/packages/seacas/libraries/ioss/src/heartbeat/Iohb_DatabaseIO.C @@ -47,7 +47,7 @@ namespace { std::string time_stamp(const std::string &format) { if (format.empty()) { - return std::string(""); + return {""}; } const int length = 256; static char time_string[length]; @@ -58,9 +58,9 @@ namespace { size_t error = strftime(time_string, length, format.c_str(), local_time); if (error != 0) { time_string[length - 1] = '\0'; - return std::string(time_string); + return {time_string}; } - return std::string("[ERROR]"); + return {"[ERROR]"}; } std::ostream *open_stream(const std::string &filename, bool *needs_delete, bool append_file) diff --git a/packages/seacas/libraries/ioss/src/hopscotch_growth_policy.h b/packages/seacas/libraries/ioss/src/hopscotch_growth_policy.h index 3409f4d3d2..89ecbaeba6 100644 --- a/packages/seacas/libraries/ioss/src/hopscotch_growth_policy.h +++ b/packages/seacas/libraries/ioss/src/hopscotch_growth_policy.h @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2018 Thibaut Goetghebuer-Planchon + * Copyright (c) 2018, 2023 Thibaut Goetghebuer-Planchon * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -69,167 +69,165 @@ #endif #endif -namespace tsl { - namespace hh { - +namespace tsl::hh { + + /** + * Grow the hash table by a factor of GrowthFactor keeping the bucket count to a + * power of two. It allows the table to use a mask operation instead of a modulo + * operation to map a hash to a bucket. + * + * GrowthFactor must be a power of two >= 2. + */ + template class power_of_two_growth_policy + { + public: /** - * Grow the hash table by a factor of GrowthFactor keeping the bucket count to a - * power of two. It allows the table to use a mask operation instead of a modulo - * operation to map a hash to a bucket. + * Called on the hash table creation and on rehash. The number of buckets for + * the table is passed in parameter. This number is a minimum, the policy may + * update this value with a higher value if needed (but not lower). * - * GrowthFactor must be a power of two >= 2. + * If 0 is given, min_bucket_count_in_out must still be 0 after the policy + * creation and bucket_for_hash must always return 0 in this case. */ - template class power_of_two_growth_policy + explicit power_of_two_growth_policy(std::size_t &min_bucket_count_in_out) { - public: - /** - * Called on the hash table creation and on rehash. The number of buckets for - * the table is passed in parameter. This number is a minimum, the policy may - * update this value with a higher value if needed (but not lower). - * - * If 0 is given, min_bucket_count_in_out must still be 0 after the policy - * creation and bucket_for_hash must always return 0 in this case. - */ - explicit power_of_two_growth_policy(std::size_t &min_bucket_count_in_out) - { - if (min_bucket_count_in_out > max_bucket_count()) { - TSL_HH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); - } - - if (min_bucket_count_in_out > 0) { - min_bucket_count_in_out = round_up_to_power_of_two(min_bucket_count_in_out); - m_mask = min_bucket_count_in_out - 1; - } - else { - m_mask = 0; - } + if (min_bucket_count_in_out > max_bucket_count()) { + TSL_HH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); } - /** - * Return the bucket [0, bucket_count()) to which the hash belongs. - * If bucket_count() is 0, it must always return 0. - */ - std::size_t bucket_for_hash(std::size_t hash) const noexcept { return hash & m_mask; } - - /** - * Return the bucket count to use when the bucket array grows on rehash. - */ - std::size_t next_bucket_count() const - { - if ((m_mask + 1) > max_bucket_count() / GrowthFactor) { - TSL_HH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); - } - - return (m_mask + 1) * GrowthFactor; + if (min_bucket_count_in_out > 0) { + min_bucket_count_in_out = round_up_to_power_of_two(min_bucket_count_in_out); + m_mask = min_bucket_count_in_out - 1; } - - /** - * Return the maximum number of buckets supported by the policy. - */ - std::size_t max_bucket_count() const - { - // Largest power of two. - return (std::numeric_limits::max() / 2) + 1; + else { + m_mask = 0; } + } - /** - * Reset the growth policy as if it was created with a bucket count of 0. - * After a clear, the policy must always return 0 when bucket_for_hash is - * called. - */ - void clear() noexcept { m_mask = 0; } - - private: - static std::size_t round_up_to_power_of_two(std::size_t value) - { - if (is_power_of_two(value)) { - return value; - } - - if (value == 0) { - return 1; - } - - --value; - for (std::size_t i = 1; i < sizeof(std::size_t) * CHAR_BIT; i *= 2) { - value |= value >> i; - } - - return value + 1; - } + /** + * Return the bucket [0, bucket_count()) to which the hash belongs. + * If bucket_count() is 0, it must always return 0. + */ + std::size_t bucket_for_hash(std::size_t hash) const noexcept { return hash & m_mask; } - static constexpr bool is_power_of_two(std::size_t value) - { - return value != 0 && (value & (value - 1)) == 0; + /** + * Return the bucket count to use when the bucket array grows on rehash. + */ + std::size_t next_bucket_count() const + { + if ((m_mask + 1) > max_bucket_count() / GrowthFactor) { + TSL_HH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); } - private: - static_assert(is_power_of_two(GrowthFactor) && GrowthFactor >= 2, - "GrowthFactor must be a power of two >= 2."); + return (m_mask + 1) * GrowthFactor; + } - std::size_t m_mask; - }; + /** + * Return the maximum number of buckets supported by the policy. + */ + std::size_t max_bucket_count() const + { + // Largest power of two. + return (std::numeric_limits::max() / 2) + 1; + } /** - * Grow the hash table by GrowthFactor::num / GrowthFactor::den and use a modulo - * to map a hash to a bucket. Slower but it can be useful if you want a slower - * growth. + * Reset the growth policy as if it was created with a bucket count of 0. + * After a clear, the policy must always return 0 when bucket_for_hash is + * called. */ - template > class mod_growth_policy + void clear() noexcept { m_mask = 0; } + + private: + static std::size_t round_up_to_power_of_two(std::size_t value) + { + if (is_power_of_two(value)) { + return value; + } + + if (value == 0) { + return 1; + } + + --value; + for (std::size_t i = 1; i < sizeof(std::size_t) * CHAR_BIT; i *= 2) { + value |= value >> i; + } + + return value + 1; + } + + static constexpr bool is_power_of_two(std::size_t value) + { + return value != 0 && (value & (value - 1)) == 0; + } + + private: + static_assert(is_power_of_two(GrowthFactor) && GrowthFactor >= 2, + "GrowthFactor must be a power of two >= 2."); + + std::size_t m_mask; + }; + + /** + * Grow the hash table by GrowthFactor::num / GrowthFactor::den and use a modulo + * to map a hash to a bucket. Slower but it can be useful if you want a slower + * growth. + */ + template > class mod_growth_policy + { + public: + explicit mod_growth_policy(std::size_t &min_bucket_count_in_out) + { + if (min_bucket_count_in_out > max_bucket_count()) { + TSL_HH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); + } + + if (min_bucket_count_in_out > 0) { + m_mod = min_bucket_count_in_out; + } + else { + m_mod = 1; + } + } + + std::size_t bucket_for_hash(std::size_t hash) const noexcept { return hash % m_mod; } + + std::size_t next_bucket_count() const { - public: - explicit mod_growth_policy(std::size_t &min_bucket_count_in_out) - { - if (min_bucket_count_in_out > max_bucket_count()) { - TSL_HH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); - } - - if (min_bucket_count_in_out > 0) { - m_mod = min_bucket_count_in_out; - } - else { - m_mod = 1; - } + if (m_mod == max_bucket_count()) { + TSL_HH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); + } + + const double next_bucket_count = std::ceil(double(m_mod) * REHASH_SIZE_MULTIPLICATION_FACTOR); + if (!std::isnormal(next_bucket_count)) { + TSL_HH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); } - std::size_t bucket_for_hash(std::size_t hash) const noexcept { return hash % m_mod; } - - std::size_t next_bucket_count() const - { - if (m_mod == max_bucket_count()) { - TSL_HH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); - } - - const double next_bucket_count = - std::ceil(double(m_mod) * REHASH_SIZE_MULTIPLICATION_FACTOR); - if (!std::isnormal(next_bucket_count)) { - TSL_HH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); - } - - if (next_bucket_count > double(max_bucket_count())) { - return max_bucket_count(); - } - else { - return std::size_t(next_bucket_count); - } + if (next_bucket_count > double(max_bucket_count())) { + return max_bucket_count(); + } + else { + return std::size_t(next_bucket_count); } + } - std::size_t max_bucket_count() const { return MAX_BUCKET_COUNT; } + std::size_t max_bucket_count() const { return MAX_BUCKET_COUNT; } - void clear() noexcept { m_mod = 1; } + void clear() noexcept { m_mod = 1; } - private: - static constexpr double REHASH_SIZE_MULTIPLICATION_FACTOR = - 1.0 * GrowthFactor::num / GrowthFactor::den; - static const std::size_t MAX_BUCKET_COUNT = std::size_t( - double(std::numeric_limits::max() / REHASH_SIZE_MULTIPLICATION_FACTOR)); + private: + static constexpr double REHASH_SIZE_MULTIPLICATION_FACTOR = + 1.0 * GrowthFactor::num / GrowthFactor::den; + static const std::size_t MAX_BUCKET_COUNT = std::size_t( + double(std::numeric_limits::max() / REHASH_SIZE_MULTIPLICATION_FACTOR)); - static_assert(REHASH_SIZE_MULTIPLICATION_FACTOR >= 1.1, "Growth factor should be >= 1.1."); + static_assert(REHASH_SIZE_MULTIPLICATION_FACTOR >= 1.1, "Growth factor should be >= 1.1."); - std::size_t m_mod; - }; + std::size_t m_mod; + }; - namespace detail { + namespace detail { #if SIZE_MAX >= ULLONG_MAX #define TSL_HH_NB_PRIMES 51 @@ -239,163 +237,160 @@ namespace tsl { #define TSL_HH_NB_PRIMES 23 #endif - static constexpr const std::array PRIMES = {{ - 1u, - 5u, - 17u, - 29u, - 37u, - 53u, - 67u, - 79u, - 97u, - 131u, - 193u, - 257u, - 389u, - 521u, - 769u, - 1031u, - 1543u, - 2053u, - 3079u, - 6151u, - 12289u, - 24593u, - 49157u, + static constexpr const std::array PRIMES = {{ + 1u, + 5u, + 17u, + 29u, + 37u, + 53u, + 67u, + 79u, + 97u, + 131u, + 193u, + 257u, + 389u, + 521u, + 769u, + 1031u, + 1543u, + 2053u, + 3079u, + 6151u, + 12289u, + 24593u, + 49157u, #if SIZE_MAX >= ULONG_MAX - 98317ul, - 196613ul, - 393241ul, - 786433ul, - 1572869ul, - 3145739ul, - 6291469ul, - 12582917ul, - 25165843ul, - 50331653ul, - 100663319ul, - 201326611ul, - 402653189ul, - 805306457ul, - 1610612741ul, - 3221225473ul, - 4294967291ul, + 98317ul, + 196613ul, + 393241ul, + 786433ul, + 1572869ul, + 3145739ul, + 6291469ul, + 12582917ul, + 25165843ul, + 50331653ul, + 100663319ul, + 201326611ul, + 402653189ul, + 805306457ul, + 1610612741ul, + 3221225473ul, + 4294967291ul, #endif #if SIZE_MAX >= ULLONG_MAX - 6442450939ull, - 12884901893ull, - 25769803751ull, - 51539607551ull, - 103079215111ull, - 206158430209ull, - 412316860441ull, - 824633720831ull, - 1649267441651ull, - 3298534883309ull, - 6597069766657ull, + 6442450939ull, + 12884901893ull, + 25769803751ull, + 51539607551ull, + 103079215111ull, + 206158430209ull, + 412316860441ull, + 824633720831ull, + 1649267441651ull, + 3298534883309ull, + 6597069766657ull, #endif - }}; - - template static constexpr std::size_t mod(std::size_t hash) - { - return hash % PRIMES[IPrime]; - } + }}; - // MOD_PRIME[iprime](hash) returns hash % PRIMES[iprime]. This table allows for - // faster modulo as the compiler can optimize the modulo code better with a - // constant known at the compilation. - static constexpr const std::array MOD_PRIME = - {{ - &mod<0>, &mod<1>, &mod<2>, &mod<3>, &mod<4>, &mod<5>, &mod<6>, &mod<7>, - &mod<8>, &mod<9>, &mod<10>, &mod<11>, &mod<12>, &mod<13>, &mod<14>, &mod<15>, - &mod<16>, &mod<17>, &mod<18>, &mod<19>, &mod<20>, &mod<21>, &mod<22>, + template static constexpr std::size_t mod(std::size_t hash) + { + return hash % PRIMES[IPrime]; + } + + // MOD_PRIME[iprime](hash) returns hash % PRIMES[iprime]. This table allows for + // faster modulo as the compiler can optimize the modulo code better with a + // constant known at the compilation. + static constexpr const std::array MOD_PRIME = {{ + &mod<0>, &mod<1>, &mod<2>, &mod<3>, &mod<4>, &mod<5>, &mod<6>, &mod<7>, &mod<8>, + &mod<9>, &mod<10>, &mod<11>, &mod<12>, &mod<13>, &mod<14>, &mod<15>, &mod<16>, &mod<17>, + &mod<18>, &mod<19>, &mod<20>, &mod<21>, &mod<22>, #if SIZE_MAX >= ULONG_MAX - &mod<23>, &mod<24>, &mod<25>, &mod<26>, &mod<27>, &mod<28>, &mod<29>, &mod<30>, - &mod<31>, &mod<32>, &mod<33>, &mod<34>, &mod<35>, &mod<36>, &mod<37>, &mod<38>, - &mod<39>, + &mod<23>, &mod<24>, &mod<25>, &mod<26>, &mod<27>, &mod<28>, &mod<29>, &mod<30>, &mod<31>, + &mod<32>, &mod<33>, &mod<34>, &mod<35>, &mod<36>, &mod<37>, &mod<38>, &mod<39>, #endif #if SIZE_MAX >= ULLONG_MAX - &mod<40>, &mod<41>, &mod<42>, &mod<43>, &mod<44>, &mod<45>, &mod<46>, &mod<47>, - &mod<48>, &mod<49>, &mod<50>, + &mod<40>, &mod<41>, &mod<42>, &mod<43>, &mod<44>, &mod<45>, &mod<46>, &mod<47>, &mod<48>, + &mod<49>, &mod<50>, #endif - }}; - - } // namespace detail - - /** - * Grow the hash table by using prime numbers as bucket count. Slower than - * tsl::hh::power_of_two_growth_policy in general but will probably distribute - * the values around better in the buckets with a poor hash function. - * - * To allow the compiler to optimize the modulo operation, a lookup table is - * used with constant primes numbers. - * - * With a switch the code would look like: - * \code - * switch(iprime) { // iprime is the current prime of the hash table - * case 0: hash % 5ul; - * break; - * case 1: hash % 17ul; - * break; - * case 2: hash % 29ul; - * break; - * ... - * } - * \endcode - * - * Due to the constant variable in the modulo the compiler is able to optimize - * the operation by a series of multiplications, substractions and shifts. - * - * The 'hash % 5' could become something like 'hash - (hash * 0xCCCCCCCD) >> 34) - * * 5' in a 64 bits environment. - */ - class prime_growth_policy + }}; + + } // namespace detail + + /** + * Grow the hash table by using prime numbers as bucket count. Slower than + * tsl::hh::power_of_two_growth_policy in general but will probably distribute + * the values around better in the buckets with a poor hash function. + * + * To allow the compiler to optimize the modulo operation, a lookup table is + * used with constant primes numbers. + * + * With a switch the code would look like: + * \code + * switch(iprime) { // iprime is the current prime of the hash table + * case 0: hash % 5ul; + * break; + * case 1: hash % 17ul; + * break; + * case 2: hash % 29ul; + * break; + * ... + * } + * \endcode + * + * Due to the constant variable in the modulo the compiler is able to optimize + * the operation by a series of multiplications, substractions and shifts. + * + * The 'hash % 5' could become something like 'hash - (hash * 0xCCCCCCCD) >> 34) + * * 5' in a 64 bits environment. + */ + class prime_growth_policy + { + public: + explicit prime_growth_policy(std::size_t &min_bucket_count_in_out) { - public: - explicit prime_growth_policy(std::size_t &min_bucket_count_in_out) - { - auto it_prime = - std::lower_bound(detail::PRIMES.begin(), detail::PRIMES.end(), min_bucket_count_in_out); - if (it_prime == detail::PRIMES.end()) { - TSL_HH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); - } - - m_iprime = static_cast(std::distance(detail::PRIMES.begin(), it_prime)); - if (min_bucket_count_in_out > 0) { - min_bucket_count_in_out = *it_prime; - } - else { - min_bucket_count_in_out = 0; - } + auto it_prime = + std::lower_bound(detail::PRIMES.begin(), detail::PRIMES.end(), min_bucket_count_in_out); + if (it_prime == detail::PRIMES.end()) { + TSL_HH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); } - std::size_t bucket_for_hash(std::size_t hash) const noexcept - { - return detail::MOD_PRIME[m_iprime](hash); + m_iprime = static_cast(std::distance(detail::PRIMES.begin(), it_prime)); + if (min_bucket_count_in_out > 0) { + min_bucket_count_in_out = *it_prime; + } + else { + min_bucket_count_in_out = 0; } + } - std::size_t next_bucket_count() const - { - if (m_iprime + 1 >= detail::PRIMES.size()) { - TSL_HH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); - } + std::size_t bucket_for_hash(std::size_t hash) const noexcept + { + return detail::MOD_PRIME[m_iprime](hash); + } - return detail::PRIMES[m_iprime + 1]; + std::size_t next_bucket_count() const + { + if (m_iprime + 1 >= detail::PRIMES.size()) { + TSL_HH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); } - std::size_t max_bucket_count() const { return detail::PRIMES.back(); } + return detail::PRIMES[m_iprime + 1]; + } + + std::size_t max_bucket_count() const { return detail::PRIMES.back(); } - void clear() noexcept { m_iprime = 0; } + void clear() noexcept { m_iprime = 0; } - private: - unsigned int m_iprime; + private: + unsigned int m_iprime; - static_assert(std::numeric_limits::max() >= detail::PRIMES.size(), - "The type of m_iprime is not big enough."); - }; + static_assert(std::numeric_limits::max() >= detail::PRIMES.size(), + "The type of m_iprime is not big enough."); + }; - } // namespace hh -} // namespace tsl +} // namespace tsl::hh #endif diff --git a/packages/seacas/libraries/ioss/src/hopscotch_hash.h b/packages/seacas/libraries/ioss/src/hopscotch_hash.h index 9117cff012..4f25cc43c6 100644 --- a/packages/seacas/libraries/ioss/src/hopscotch_hash.h +++ b/packages/seacas/libraries/ioss/src/hopscotch_hash.h @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2017, 2022 Thibaut Goetghebuer-Planchon + * Copyright (c) 2017, 2022, 2023 Thibaut Goetghebuer-Planchon * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -47,6 +47,7 @@ #define TSL_HH_NO_RANGE_ERASE_WITH_CONST_ITERATOR #endif +// NOLINTBEGIN namespace tsl { namespace detail_hopscotch_hash { @@ -708,8 +709,8 @@ namespace tsl { hopscotch_hash &operator=(const hopscotch_hash &other) { if (&other != this) { - Hash:: operator=(other); - KeyEqual:: operator=(other); + Hash::operator=(other); + KeyEqual::operator=(other); GrowthPolicy::operator=(other); m_buckets_data = other.m_buckets_data; @@ -1862,5 +1863,6 @@ namespace tsl { } // end namespace detail_hopscotch_hash } // end namespace tsl +// NOLINTEND #endif diff --git a/packages/seacas/libraries/ioss/src/main/cgns_decomp.C b/packages/seacas/libraries/ioss/src/main/cgns_decomp.C index 741422a118..7d282204c3 100644 --- a/packages/seacas/libraries/ioss/src/main/cgns_decomp.C +++ b/packages/seacas/libraries/ioss/src/main/cgns_decomp.C @@ -185,7 +185,7 @@ namespace { return true; } - explicit Interface(const std::string &app_version) : version(app_version) + explicit Interface(std::string app_version) : version(std::move(app_version)) { options_.usage("[options] input_file"); options_.enroll("help", Ioss::GetLongOption::NoValue, "Print this summary and exit", nullptr); diff --git a/packages/seacas/libraries/ioss/src/main/cth_pressure_map.C b/packages/seacas/libraries/ioss/src/main/cth_pressure_map.C index 45ae0dce57..29404dc8b3 100644 --- a/packages/seacas/libraries/ioss/src/main/cth_pressure_map.C +++ b/packages/seacas/libraries/ioss/src/main/cth_pressure_map.C @@ -767,9 +767,7 @@ namespace { // Iterate through results fields and transfer to output // database... If a prefix is specified, only transfer fields // whose names begin with the prefix - Ioss::NameList::const_iterator IF; - for (IF = fields.begin(); IF != fields.end(); ++IF) { - std::string field_name = *IF; + for (const auto &field_name : fields) { if (field_name != "ids" && !oge->field_exists(field_name) && Ioss::Utils::substr_equal(prefix, field_name)) { // If the field does not already exist, add it to the output node block @@ -787,13 +785,10 @@ namespace { // database and transfer to output database. Ioss::NameList state_fields = ige->field_describe(role); - Ioss::NameList::const_iterator IF; - // Complication here is that if the 'role' is 'Ioss::Field::MESH', // then the 'ids' field must be transferred first... if (role == Ioss::Field::MESH) { - for (IF = state_fields.begin(); IF != state_fields.end(); ++IF) { - std::string field_name = *IF; + for (const auto &field_name : state_fields) { assert(oge->field_exists(field_name)); if (field_name == "ids") { transfer_field_data_internal(ige, oge, field_name); @@ -802,8 +797,7 @@ namespace { } } - for (IF = state_fields.begin(); IF != state_fields.end(); ++IF) { - std::string field_name = *IF; + for (const auto &field_name : state_fields) { // All of the 'Ioss::EntityBlock' derived classes have a // 'connectivity' field, but it is only interesting on the // Ioss::ElementBlock class. On the other classes, it just @@ -878,11 +872,11 @@ namespace { void add_sideset(Ioss::Region &ss_region, Ioss::Region & /* region */, Ioss::Region &output_region, Globals &globals) { - Ioss::SideSet *pressures = new Ioss::SideSet(output_region.get_database(), "cth_pressures"); + auto *pressures = new Ioss::SideSet(output_region.get_database(), "cth_pressures"); // Each element block in the sset file will be a surside in the mesh file... { - const Ioss::ElementBlockContainer &ebs = ss_region.get_element_blocks(); - Ioss::ElementBlockContainer::const_iterator i = ebs.begin(); + const auto &ebs = ss_region.get_element_blocks(); + auto i = ebs.begin(); while (i != ebs.end()) { std::string name = (*i)->name(); name = "ss" + name; @@ -908,8 +902,8 @@ namespace { { // Each element block in the sset file will be a surface in the mesh file... { - const Ioss::ElementBlockContainer &ebs = ss_region.get_element_blocks(); - Ioss::ElementBlockContainer::const_iterator i = ebs.begin(); + const auto &ebs = ss_region.get_element_blocks(); + auto i = ebs.begin(); while (i != ebs.end()) { std::string name = (*i)->name(); name = "ss" + name; @@ -975,8 +969,8 @@ namespace { if (globals.convert_gage) { ss_region.begin_state(1); - const Ioss::ElementBlockContainer &ebs = ss_region.get_element_blocks(); - Ioss::ElementBlockContainer::const_iterator i = ebs.begin(); + const auto &ebs = ss_region.get_element_blocks(); + auto i = ebs.begin(); while (i != ebs.end()) { // The gage pressure conversion is currently only applied to the field "cth_pressure" @@ -1001,8 +995,8 @@ namespace { if (globals.offset_time > 0.0) { int ostep = output_region.add_state(0.0); output_region.begin_state(ostep); - const Ioss::ElementBlockContainer &ebs = ss_region.get_element_blocks(); - Ioss::ElementBlockContainer::const_iterator i = ebs.begin(); + const auto &ebs = ss_region.get_element_blocks(); + auto i = ebs.begin(); while (i != ebs.end()) { const std::string &eb_name = (*i)->name(); std::string name = "ss" + eb_name; @@ -1012,11 +1006,8 @@ namespace { std::exit(EXIT_FAILURE); } - Ioss::NameList state_fields = (*i)->field_describe(Ioss::Field::TRANSIENT); - Ioss::NameList::const_iterator IF; - - for (IF = state_fields.begin(); IF != state_fields.end(); ++IF) { - std::string field_name = *IF; + auto state_fields = (*i)->field_describe(Ioss::Field::TRANSIENT); + for (const auto &field_name : state_fields) { // NOTE: Only dealing with the "cth_" fields here. // If there are other fields, we probably have an invalid // output database... @@ -1024,7 +1015,7 @@ namespace { int isize = (*i)->get_field(field_name).get_size(); int count = (*i)->get_field(field_name).raw_count(); data.resize(isize); - double *rdata = reinterpret_cast(&data[0]); + auto *rdata = reinterpret_cast(&data[0]); for (int ii = 0; ii < count; ii++) { rdata[ii] = globals.offset_pressure; } @@ -1052,22 +1043,19 @@ namespace { output_region.begin_state(ostep); ss_region.begin_state(istep); - const Ioss::ElementBlockContainer &ebs = ss_region.get_element_blocks(); - Ioss::ElementBlockContainer::const_iterator i = ebs.begin(); + const auto &ebs = ss_region.get_element_blocks(); + auto i = ebs.begin(); while (i != ebs.end()) { const std::string &eb_name = (*i)->name(); std::string name = "ss" + eb_name; - Ioss::SideBlock *fb = output_region.get_sideblock(name); + auto *fb = output_region.get_sideblock(name); if (fb == nullptr) { std::cerr << "INTERNAL ERROR: Could not find side block named '" << name << "'\n"; std::exit(EXIT_FAILURE); } - Ioss::NameList state_fields = (*i)->field_describe(Ioss::Field::TRANSIENT); - Ioss::NameList::const_iterator IF; - - for (IF = state_fields.begin(); IF != state_fields.end(); ++IF) { - std::string field_name = *IF; + auto state_fields = (*i)->field_describe(Ioss::Field::TRANSIENT); + for (const auto &field_name : state_fields) { if (globals.convert_gage && field_name == cth_pressure) { // Subtract the time zero pressures (stored in // time_zero_field_data) from each time step @@ -1077,7 +1065,7 @@ namespace { int isize = (*i)->get_field(field_name).get_size(); int count = (*i)->get_field(field_name).raw_count(); data.resize(isize); - double *rdata = reinterpret_cast(&data[0]); + auto *rdata = reinterpret_cast(&data[0]); (*i)->get_field_data(field_name, &data[0], isize); for (int ii = 0; ii < count; ii++) { @@ -1095,7 +1083,7 @@ namespace { int isize = (*i)->get_field(field_name).get_size(); int count = (*i)->get_field(field_name).raw_count(); data.resize(isize); - double *rdata = reinterpret_cast(&data[0]); + auto *rdata = reinterpret_cast(&data[0]); (*i)->get_field_data(field_name, &data[0], isize); for (int ii = 0; ii < count; ii++) { @@ -1137,8 +1125,8 @@ namespace { // an // "equilibrium" state in case the CTH analysis was not run out to an equilibrium // state. If ZERO was specified, then it simply zeros out the pressure field at the last step. - const Ioss::ElementBlockContainer &ebs = ss_region.get_element_blocks(); - Ioss::ElementBlockContainer::const_iterator i = ebs.begin(); + const auto &ebs = ss_region.get_element_blocks(); + auto i = ebs.begin(); while (i != ebs.end()) { const std::string &eb_name = (*i)->name(); std::string name = "ss" + eb_name; @@ -1149,11 +1137,8 @@ namespace { throw std::runtime_error(msg.str()); } - Ioss::NameList state_fields = (*i)->field_describe(Ioss::Field::TRANSIENT); - Ioss::NameList::const_iterator IF; - - for (IF = state_fields.begin(); IF != state_fields.end(); ++IF) { - std::string field_name = *IF; + auto state_fields = (*i)->field_describe(Ioss::Field::TRANSIENT); + for (const auto &field_name : state_fields) { if (Ioss::Utils::substr_equal("cth_", field_name)) { if (field_name == cth_pressure && (globals.final_pressure == Globals::ZERO || @@ -1171,7 +1156,7 @@ namespace { int isize = (*i)->get_field(field_name).get_size(); int count = (*i)->get_field(field_name).raw_count(); data.resize(isize); - double *rdata = reinterpret_cast(&data[0]); + auto *rdata = reinterpret_cast(&data[0]); for (int ii = 0; ii < count; ii++) { rdata[ii] = value; } @@ -1204,12 +1189,11 @@ namespace { { // Each element block in the sset file will be a surface in the mesh file... { - const Ioss::ElementBlockContainer &ebs = ss_region.get_element_blocks(); - Ioss::ElementBlockContainer::const_iterator i = ebs.begin(); - while (i != ebs.end()) { - std::string name = (*i)->name(); - name = "ss" + name; - Ioss::SideBlock *fb = output_region.get_sideblock(name); + const auto &ebs = ss_region.get_element_blocks(); + for (auto *eb : ebs) { + std::string name = eb->name(); + name = "ss" + name; + auto *fb = output_region.get_sideblock(name); assert(fb != nullptr); if (globals.debug) { @@ -1218,8 +1202,7 @@ namespace { // Each element variable in the sset file which begins with // "cth_" will be a sideset variable in the outptut file... } - transfer_fields((*i), fb, Ioss::Field::TRANSIENT, "cth_"); - ++i; + transfer_fields(eb, fb, Ioss::Field::TRANSIENT, "cth_"); } } } @@ -1228,20 +1211,17 @@ namespace { { // Define output fields... { - const Ioss::VariableType *v3d = Ioss::VariableType::factory("vector_3d"); + const auto *v3d = Ioss::VariableType::factory("vector_3d"); output_region.begin_mode(Ioss::STATE_DEFINE_TRANSIENT); - Ioss::NodeBlock *nb = (*output_region.get_node_blocks().begin()); - int num_nodes = nb->entity_count(); - Ioss::Field node_normal("node_normal", Ioss::Field::REAL, v3d, Ioss::Field::TRANSIENT, - num_nodes); + auto *nb = (*output_region.get_node_blocks().begin()); + int num_nodes = nb->entity_count(); + Ioss::Field node_normal("node_normal", Ioss::Field::REAL, v3d, Ioss::Field::TRANSIENT, + num_nodes); nb->field_add(node_normal); // Iterate over the element blocks and calculate both node normals and face normals... - const Ioss::ElementBlockContainer &ebs = output_region.get_element_blocks(); - Ioss::ElementBlockContainer::const_iterator ib = ebs.begin(); - while (ib != ebs.end()) { - Ioss::ElementBlock *eb = *ib; - ++ib; + const auto &ebs = output_region.get_element_blocks(); + for (auto *eb : ebs) { int num_elem = eb->entity_count(); Ioss::Field face_normal("face_normal", Ioss::Field::REAL, v3d, Ioss::Field::TRANSIENT, num_elem); @@ -1254,8 +1234,8 @@ namespace { int ostep = output_region.add_state(0.0); output_region.begin_state(ostep); - Ioss::NodeBlock *nb = (*region.get_node_blocks().begin()); - Ioss::NodeBlock *nbo = (*output_region.get_node_blocks().begin()); + auto *nb = (*region.get_node_blocks().begin()); + auto *nbo = (*output_region.get_node_blocks().begin()); // Get the nodal coordinates... int num_nodes = nb->entity_count(); @@ -1271,17 +1251,13 @@ namespace { std::fill(node_normal.begin(), node_normal.end(), 0.0); // Iterate over the element blocks and calculate both node normals and face normals... - std::vector conn; - std::vector face_normal; - const Ioss::ElementBlockContainer &ebs = region.get_element_blocks(); - - Ioss::ElementBlockContainer::const_iterator ib = ebs.begin(); - while (ib != ebs.end()) { - Ioss::ElementBlock *eb = *ib; - ++ib; + std::vector conn; + std::vector face_normal; + const auto &ebs = region.get_element_blocks(); + for (const auto *eb : ebs) { const std::string &name = (*eb).name(); - Ioss::ElementBlock *ebo = output_region.get_element_block(name); + auto *ebo = output_region.get_element_block(name); if (ebo == nullptr) { std::cerr << "INTERNAL ERROR: Could not find element block named '" << name << "'\n"; std::exit(EXIT_FAILURE); diff --git a/packages/seacas/libraries/ioss/src/main/shell_interface.C b/packages/seacas/libraries/ioss/src/main/shell_interface.C index 079d9d5708..cb542c8ea6 100644 --- a/packages/seacas/libraries/ioss/src/main/shell_interface.C +++ b/packages/seacas/libraries/ioss/src/main/shell_interface.C @@ -21,7 +21,7 @@ #include // for string, char_traits #include // for vector -IOShell::Interface::Interface(const std::string &app_version) : version(app_version) +IOShell::Interface::Interface(std::string app_version) : version(std::move(app_version)) { enroll_options(); } diff --git a/packages/seacas/libraries/ioss/src/main/shell_interface.h b/packages/seacas/libraries/ioss/src/main/shell_interface.h index 713d389a69..4a4f6f0123 100644 --- a/packages/seacas/libraries/ioss/src/main/shell_interface.h +++ b/packages/seacas/libraries/ioss/src/main/shell_interface.h @@ -20,7 +20,7 @@ namespace IOShell { class Interface { public: - explicit Interface(const std::string &app_version); + explicit Interface(std::string app_version); ~Interface(); bool parse_options(int argc, char **argv, int my_processor); diff --git a/packages/seacas/libraries/ioss/src/main/shell_to_hex.C b/packages/seacas/libraries/ioss/src/main/shell_to_hex.C index 97ba657b28..f42257caa6 100644 --- a/packages/seacas/libraries/ioss/src/main/shell_to_hex.C +++ b/packages/seacas/libraries/ioss/src/main/shell_to_hex.C @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2022 National Technology & Engineering Solutions +// Copyright(C) 1999-2023 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -281,8 +281,8 @@ namespace { void transfer_nodeblock(Ioss::Region ®ion, Ioss::Region &output_region, bool debug) { - const Ioss::NodeBlockContainer &nbs = region.get_node_blocks(); - Ioss::NodeBlockContainer::const_iterator i = nbs.begin(); + const auto &nbs = region.get_node_blocks(); + auto i = nbs.begin(); while (i != nbs.end()) { const std::string &name = (*i)->name(); if (debug) { @@ -306,9 +306,9 @@ namespace { void transfer_elementblock(Ioss::Region ®ion, Ioss::Region &output_region, bool debug) { - const Ioss::ElementBlockContainer &ebs = region.get_element_blocks(); - Ioss::ElementBlockContainer::const_iterator i = ebs.begin(); - size_t total_elements = 0; + const auto &ebs = region.get_element_blocks(); + auto i = ebs.begin(); + size_t total_elements = 0; while (i != ebs.end()) { const std::string &name = (*i)->name(); if (debug) { @@ -342,14 +342,11 @@ namespace { void transfer_properties(Ioss::GroupingEntity *ige, Ioss::GroupingEntity *oge) { - Ioss::NameList names; - ige->property_describe(&names); - + auto names = ige->property_describe(); // Iterate through properties and transfer to output database... - Ioss::NameList::const_iterator I; - for (I = names.begin(); I != names.end(); ++I) { - if (!oge->property_exists(*I)) { - oge->property_add(ige->get_property(*I)); + for (const auto &name : names) { + if (!oge->property_exists(name)) { + oge->property_add(ige->get_property(name)); } } } @@ -380,13 +377,13 @@ namespace { std::fill(node_normal.begin(), node_normal.end(), 0.0); // Iterate over the element blocks and calculate node normals - std::vector conn; - std::vector output_conn; - const Ioss::ElementBlockContainer &ebs = region.get_element_blocks(); - const Ioss::ElementBlockContainer &out_ebs = output_region.get_element_blocks(); + std::vector conn; + std::vector output_conn; + const auto &ebs = region.get_element_blocks(); + const auto &out_ebs = output_region.get_element_blocks(); - Ioss::ElementBlockContainer::const_iterator ib = ebs.begin(); - Ioss::ElementBlockContainer::const_iterator out_ib = out_ebs.begin(); + auto ib = ebs.begin(); + auto out_ib = out_ebs.begin(); while (ib != ebs.end() && out_ib != out_ebs.end()) { Ioss::ElementBlock *eb = *ib; ++ib; diff --git a/packages/seacas/libraries/ioss/src/main/skinner.C b/packages/seacas/libraries/ioss/src/main/skinner.C index ac76781b65..43bc4c0008 100644 --- a/packages/seacas/libraries/ioss/src/main/skinner.C +++ b/packages/seacas/libraries/ioss/src/main/skinner.C @@ -540,9 +540,8 @@ namespace { out.reserve(oeb->entity_count() * comp_count); auto offset = ieb->get_offset(); - for (size_t i = 0; i < boundary_faces.size(); i++) { - const auto &face = boundary_faces[i]; - auto element_id = face.element[0] / 10 - 1; + for (const auto &face : boundary_faces) { + auto element_id = face.element[0] / 10 - 1; for (int j = 0; j < comp_count; j++) { auto value = in[comp_count * (element_id - offset) + j]; out.push_back(value); diff --git a/packages/seacas/libraries/ioss/src/main/sphgen.C b/packages/seacas/libraries/ioss/src/main/sphgen.C index d5356f3582..776236b3fc 100644 --- a/packages/seacas/libraries/ioss/src/main/sphgen.C +++ b/packages/seacas/libraries/ioss/src/main/sphgen.C @@ -225,9 +225,9 @@ namespace { // The first time, just count the number of hex elements since // that will be the number of output element and nodes in the // sphere mesh. - size_t sph_node_count = 0; - const Ioss::ElementBlockContainer &ebs = region.get_element_blocks(); - Ioss::ElementBlockContainer::const_iterator I = ebs.begin(); + size_t sph_node_count = 0; + const auto &ebs = region.get_element_blocks(); + auto I = ebs.begin(); while (I != ebs.end()) { Ioss::ElementBlock *eb = *I; ++I; @@ -236,11 +236,10 @@ namespace { sph_node_count += eb->entity_count(); // Add the element block... - int num_elem = eb->entity_count(); - std::string name = eb->name(); - Ioss::ElementBlock *ebn = - new Ioss::ElementBlock(output_region.get_database(), name, "sphere", num_elem); - int id = eb->get_property("id").get_int(); + int num_elem = eb->entity_count(); + std::string name = eb->name(); + auto *ebn = new Ioss::ElementBlock(output_region.get_database(), name, "sphere", num_elem); + int id = eb->get_property("id").get_int(); ebn->property_add(Ioss::Property("id", id)); ebn->field_add(Ioss::Field("radius", Ioss::Field::REAL, "scalar", Ioss::Field::ATTRIBUTE, num_elem, 1)); @@ -268,11 +267,11 @@ namespace { output_region.begin_mode(Ioss::STATE_MODEL); - Ioss::NodeBlock *nb = region.get_node_blocks()[0]; + auto *nb = region.get_node_blocks()[0]; std::vector coordinates; nb->get_field_data("mesh_model_coordinates", coordinates); - Ioss::NodeBlock *onb = output_region.get_node_blocks()[0]; + auto *onb = output_region.get_node_blocks()[0]; std::vector node_ids(sph_node_count); for (size_t i = 0; i < sph_node_count; i++) { node_ids[i] = i + 1; @@ -292,13 +291,13 @@ namespace { hex_volume(*I, coordinates, ¢roids[3 * offset], volume, radius, globals.scale_factor); // Find corresponding output element block... - Ioss::ElementBlock *output_eb = output_region.get_element_block((*I)->name()); + auto *output_eb = output_region.get_element_block((*I)->name()); if (output_eb == nullptr) { fmt::print(stderr, "ERROR: Could not find output element block '{}'\n", (*I)->name()); std::exit(EXIT_FAILURE); } - Ioss::NodeSet *output_ns = output_region.get_nodeset((*I)->name() + "_nodes"); + auto *output_ns = output_region.get_nodeset((*I)->name() + "_nodes"); if (output_ns == nullptr) { fmt::print(stderr, "ERROR: Could not find output node set '{}_nodes'\n", (*I)->name()); std::exit(EXIT_FAILURE); diff --git a/packages/seacas/libraries/ioss/src/main/vector3d.C b/packages/seacas/libraries/ioss/src/main/vector3d.C index ec9f0b0ef4..c054cc98ae 100644 --- a/packages/seacas/libraries/ioss/src/main/vector3d.C +++ b/packages/seacas/libraries/ioss/src/main/vector3d.C @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2020 National Technology & Engineering Solutions +// Copyright(C) 1999-2020, 2023 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -90,7 +90,7 @@ vector3d operator/(const vector3d &lhs, double scalar) vector3d tmp(lhs); return tmp /= scalar; } - return vector3d(HUGE_VAL, HUGE_VAL, HUGE_VAL); + return {HUGE_VAL, HUGE_VAL, HUGE_VAL}; } vector3d &vector3d::operator/=(double scalar) diff --git a/packages/seacas/libraries/ioss/src/main/vector3d.h b/packages/seacas/libraries/ioss/src/main/vector3d.h index 98eaa56948..68beaba3e1 100644 --- a/packages/seacas/libraries/ioss/src/main/vector3d.h +++ b/packages/seacas/libraries/ioss/src/main/vector3d.h @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2020, 2022 National Technology & Engineering Solutions + * Copyright(C) 1999-2020, 2022, 2023 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * @@ -48,7 +48,7 @@ vector3d operator-(const vector3d &lhs, const vector3d &rhs); //---------------------------------------------------------------------------- inline vector3d vector3d::cross(const vector3d &from) const { - return vector3d(y * from.z - z * from.y, z * from.x - x * from.z, x * from.y - y * from.x); + return {y * from.z - z * from.y, z * from.x - x * from.z, x * from.y - y * from.x}; } //---------------------------------------------------------------------------- inline vector3d &vector3d::operator+=(const vector3d &from) diff --git a/packages/seacas/libraries/ioss/src/robin_growth_policy.h b/packages/seacas/libraries/ioss/src/robin_growth_policy.h index 36752ef422..69abb23fd0 100644 --- a/packages/seacas/libraries/ioss/src/robin_growth_policy.h +++ b/packages/seacas/libraries/ioss/src/robin_growth_policy.h @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2017 Thibaut Goetghebuer-Planchon + * Copyright (c) 2017, 2023 Thibaut Goetghebuer-Planchon * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -71,167 +71,165 @@ #define TSL_RH_UNUSED(x) static_cast(x) -namespace tsl { - namespace rh { - +namespace tsl::rh { + + /** + * Grow the hash table by a factor of GrowthFactor keeping the bucket count to a + * power of two. It allows the table to use a mask operation instead of a modulo + * operation to map a hash to a bucket. + * + * GrowthFactor must be a power of two >= 2. + */ + template class power_of_two_growth_policy + { + public: /** - * Grow the hash table by a factor of GrowthFactor keeping the bucket count to a - * power of two. It allows the table to use a mask operation instead of a modulo - * operation to map a hash to a bucket. + * Called on the hash table creation and on rehash. The number of buckets for + * the table is passed in parameter. This number is a minimum, the policy may + * update this value with a higher value if needed (but not lower). * - * GrowthFactor must be a power of two >= 2. + * If 0 is given, min_bucket_count_in_out must still be 0 after the policy + * creation and bucket_for_hash must always return 0 in this case. */ - template class power_of_two_growth_policy + explicit power_of_two_growth_policy(std::size_t &min_bucket_count_in_out) { - public: - /** - * Called on the hash table creation and on rehash. The number of buckets for - * the table is passed in parameter. This number is a minimum, the policy may - * update this value with a higher value if needed (but not lower). - * - * If 0 is given, min_bucket_count_in_out must still be 0 after the policy - * creation and bucket_for_hash must always return 0 in this case. - */ - explicit power_of_two_growth_policy(std::size_t &min_bucket_count_in_out) - { - if (min_bucket_count_in_out > max_bucket_count()) { - TSL_RH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); - } - - if (min_bucket_count_in_out > 0) { - min_bucket_count_in_out = round_up_to_power_of_two(min_bucket_count_in_out); - m_mask = min_bucket_count_in_out - 1; - } - else { - m_mask = 0; - } + if (min_bucket_count_in_out > max_bucket_count()) { + TSL_RH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); } - /** - * Return the bucket [0, bucket_count()) to which the hash belongs. - * If bucket_count() is 0, it must always return 0. - */ - std::size_t bucket_for_hash(std::size_t hash) const noexcept { return hash & m_mask; } - - /** - * Return the number of buckets that should be used on next growth. - */ - std::size_t next_bucket_count() const - { - if ((m_mask + 1) > max_bucket_count() / GrowthFactor) { - TSL_RH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); - } - - return (m_mask + 1) * GrowthFactor; + if (min_bucket_count_in_out > 0) { + min_bucket_count_in_out = round_up_to_power_of_two(min_bucket_count_in_out); + m_mask = min_bucket_count_in_out - 1; } - - /** - * Return the maximum number of buckets supported by the policy. - */ - std::size_t max_bucket_count() const - { - // Largest power of two. - return (std::numeric_limits::max() / 2) + 1; + else { + m_mask = 0; } + } - /** - * Reset the growth policy as if it was created with a bucket count of 0. - * After a clear, the policy must always return 0 when bucket_for_hash is - * called. - */ - void clear() noexcept { m_mask = 0; } - - private: - static std::size_t round_up_to_power_of_two(std::size_t value) - { - if (is_power_of_two(value)) { - return value; - } - - if (value == 0) { - return 1; - } - - --value; - for (std::size_t i = 1; i < sizeof(std::size_t) * CHAR_BIT; i *= 2) { - value |= value >> i; - } - - return value + 1; - } + /** + * Return the bucket [0, bucket_count()) to which the hash belongs. + * If bucket_count() is 0, it must always return 0. + */ + std::size_t bucket_for_hash(std::size_t hash) const noexcept { return hash & m_mask; } - static constexpr bool is_power_of_two(std::size_t value) - { - return value != 0 && (value & (value - 1)) == 0; + /** + * Return the number of buckets that should be used on next growth. + */ + std::size_t next_bucket_count() const + { + if ((m_mask + 1) > max_bucket_count() / GrowthFactor) { + TSL_RH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); } - protected: - static_assert(is_power_of_two(GrowthFactor) && GrowthFactor >= 2, - "GrowthFactor must be a power of two >= 2."); + return (m_mask + 1) * GrowthFactor; + } - std::size_t m_mask; - }; + /** + * Return the maximum number of buckets supported by the policy. + */ + std::size_t max_bucket_count() const + { + // Largest power of two. + return (std::numeric_limits::max() / 2) + 1; + } /** - * Grow the hash table by GrowthFactor::num / GrowthFactor::den and use a modulo - * to map a hash to a bucket. Slower but it can be useful if you want a slower - * growth. + * Reset the growth policy as if it was created with a bucket count of 0. + * After a clear, the policy must always return 0 when bucket_for_hash is + * called. */ - template > class mod_growth_policy + void clear() noexcept { m_mask = 0; } + + private: + static std::size_t round_up_to_power_of_two(std::size_t value) + { + if (is_power_of_two(value)) { + return value; + } + + if (value == 0) { + return 1; + } + + --value; + for (std::size_t i = 1; i < sizeof(std::size_t) * CHAR_BIT; i *= 2) { + value |= value >> i; + } + + return value + 1; + } + + static constexpr bool is_power_of_two(std::size_t value) + { + return value != 0 && (value & (value - 1)) == 0; + } + + protected: + static_assert(is_power_of_two(GrowthFactor) && GrowthFactor >= 2, + "GrowthFactor must be a power of two >= 2."); + + std::size_t m_mask; + }; + + /** + * Grow the hash table by GrowthFactor::num / GrowthFactor::den and use a modulo + * to map a hash to a bucket. Slower but it can be useful if you want a slower + * growth. + */ + template > class mod_growth_policy + { + public: + explicit mod_growth_policy(std::size_t &min_bucket_count_in_out) + { + if (min_bucket_count_in_out > max_bucket_count()) { + TSL_RH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); + } + + if (min_bucket_count_in_out > 0) { + m_mod = min_bucket_count_in_out; + } + else { + m_mod = 1; + } + } + + std::size_t bucket_for_hash(std::size_t hash) const noexcept { return hash % m_mod; } + + std::size_t next_bucket_count() const { - public: - explicit mod_growth_policy(std::size_t &min_bucket_count_in_out) - { - if (min_bucket_count_in_out > max_bucket_count()) { - TSL_RH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); - } - - if (min_bucket_count_in_out > 0) { - m_mod = min_bucket_count_in_out; - } - else { - m_mod = 1; - } + if (m_mod == max_bucket_count()) { + TSL_RH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); + } + + const double next_bucket_count = std::ceil(double(m_mod) * REHASH_SIZE_MULTIPLICATION_FACTOR); + if (!std::isnormal(next_bucket_count)) { + TSL_RH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); } - std::size_t bucket_for_hash(std::size_t hash) const noexcept { return hash % m_mod; } - - std::size_t next_bucket_count() const - { - if (m_mod == max_bucket_count()) { - TSL_RH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); - } - - const double next_bucket_count = - std::ceil(double(m_mod) * REHASH_SIZE_MULTIPLICATION_FACTOR); - if (!std::isnormal(next_bucket_count)) { - TSL_RH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); - } - - if (next_bucket_count > double(max_bucket_count())) { - return max_bucket_count(); - } - else { - return std::size_t(next_bucket_count); - } + if (next_bucket_count > double(max_bucket_count())) { + return max_bucket_count(); + } + else { + return std::size_t(next_bucket_count); } + } - std::size_t max_bucket_count() const { return MAX_BUCKET_COUNT; } + std::size_t max_bucket_count() const { return MAX_BUCKET_COUNT; } - void clear() noexcept { m_mod = 1; } + void clear() noexcept { m_mod = 1; } - private: - static constexpr double REHASH_SIZE_MULTIPLICATION_FACTOR = - 1.0 * GrowthFactor::num / GrowthFactor::den; - static const std::size_t MAX_BUCKET_COUNT = std::size_t( - double(std::numeric_limits::max() / REHASH_SIZE_MULTIPLICATION_FACTOR)); + private: + static constexpr double REHASH_SIZE_MULTIPLICATION_FACTOR = + 1.0 * GrowthFactor::num / GrowthFactor::den; + static const std::size_t MAX_BUCKET_COUNT = std::size_t( + double(std::numeric_limits::max() / REHASH_SIZE_MULTIPLICATION_FACTOR)); - static_assert(REHASH_SIZE_MULTIPLICATION_FACTOR >= 1.1, "Growth factor should be >= 1.1."); + static_assert(REHASH_SIZE_MULTIPLICATION_FACTOR >= 1.1, "Growth factor should be >= 1.1."); - std::size_t m_mod; - }; + std::size_t m_mod; + }; - namespace detail { + namespace detail { #if SIZE_MAX >= ULLONG_MAX #define TSL_RH_NB_PRIMES 51 @@ -241,163 +239,160 @@ namespace tsl { #define TSL_RH_NB_PRIMES 23 #endif - static constexpr const std::array PRIMES = {{ - 1u, - 5u, - 17u, - 29u, - 37u, - 53u, - 67u, - 79u, - 97u, - 131u, - 193u, - 257u, - 389u, - 521u, - 769u, - 1031u, - 1543u, - 2053u, - 3079u, - 6151u, - 12289u, - 24593u, - 49157u, + static constexpr const std::array PRIMES = {{ + 1u, + 5u, + 17u, + 29u, + 37u, + 53u, + 67u, + 79u, + 97u, + 131u, + 193u, + 257u, + 389u, + 521u, + 769u, + 1031u, + 1543u, + 2053u, + 3079u, + 6151u, + 12289u, + 24593u, + 49157u, #if SIZE_MAX >= ULONG_MAX - 98317ul, - 196613ul, - 393241ul, - 786433ul, - 1572869ul, - 3145739ul, - 6291469ul, - 12582917ul, - 25165843ul, - 50331653ul, - 100663319ul, - 201326611ul, - 402653189ul, - 805306457ul, - 1610612741ul, - 3221225473ul, - 4294967291ul, + 98317ul, + 196613ul, + 393241ul, + 786433ul, + 1572869ul, + 3145739ul, + 6291469ul, + 12582917ul, + 25165843ul, + 50331653ul, + 100663319ul, + 201326611ul, + 402653189ul, + 805306457ul, + 1610612741ul, + 3221225473ul, + 4294967291ul, #endif #if SIZE_MAX >= ULLONG_MAX - 6442450939ull, - 12884901893ull, - 25769803751ull, - 51539607551ull, - 103079215111ull, - 206158430209ull, - 412316860441ull, - 824633720831ull, - 1649267441651ull, - 3298534883309ull, - 6597069766657ull, + 6442450939ull, + 12884901893ull, + 25769803751ull, + 51539607551ull, + 103079215111ull, + 206158430209ull, + 412316860441ull, + 824633720831ull, + 1649267441651ull, + 3298534883309ull, + 6597069766657ull, #endif - }}; - - template static constexpr std::size_t mod(std::size_t hash) - { - return hash % PRIMES[IPrime]; - } + }}; - // MOD_PRIME[iprime](hash) returns hash % PRIMES[iprime]. This table allows for - // faster modulo as the compiler can optimize the modulo code better with a - // constant known at the compilation. - static constexpr const std::array MOD_PRIME = - {{ - &mod<0>, &mod<1>, &mod<2>, &mod<3>, &mod<4>, &mod<5>, &mod<6>, &mod<7>, - &mod<8>, &mod<9>, &mod<10>, &mod<11>, &mod<12>, &mod<13>, &mod<14>, &mod<15>, - &mod<16>, &mod<17>, &mod<18>, &mod<19>, &mod<20>, &mod<21>, &mod<22>, + template static constexpr std::size_t mod(std::size_t hash) + { + return hash % PRIMES[IPrime]; + } + + // MOD_PRIME[iprime](hash) returns hash % PRIMES[iprime]. This table allows for + // faster modulo as the compiler can optimize the modulo code better with a + // constant known at the compilation. + static constexpr const std::array MOD_PRIME = {{ + &mod<0>, &mod<1>, &mod<2>, &mod<3>, &mod<4>, &mod<5>, &mod<6>, &mod<7>, &mod<8>, + &mod<9>, &mod<10>, &mod<11>, &mod<12>, &mod<13>, &mod<14>, &mod<15>, &mod<16>, &mod<17>, + &mod<18>, &mod<19>, &mod<20>, &mod<21>, &mod<22>, #if SIZE_MAX >= ULONG_MAX - &mod<23>, &mod<24>, &mod<25>, &mod<26>, &mod<27>, &mod<28>, &mod<29>, &mod<30>, - &mod<31>, &mod<32>, &mod<33>, &mod<34>, &mod<35>, &mod<36>, &mod<37>, &mod<38>, - &mod<39>, + &mod<23>, &mod<24>, &mod<25>, &mod<26>, &mod<27>, &mod<28>, &mod<29>, &mod<30>, &mod<31>, + &mod<32>, &mod<33>, &mod<34>, &mod<35>, &mod<36>, &mod<37>, &mod<38>, &mod<39>, #endif #if SIZE_MAX >= ULLONG_MAX - &mod<40>, &mod<41>, &mod<42>, &mod<43>, &mod<44>, &mod<45>, &mod<46>, &mod<47>, - &mod<48>, &mod<49>, &mod<50>, + &mod<40>, &mod<41>, &mod<42>, &mod<43>, &mod<44>, &mod<45>, &mod<46>, &mod<47>, &mod<48>, + &mod<49>, &mod<50>, #endif - }}; - - } // namespace detail - - /** - * Grow the hash table by using prime numbers as bucket count. Slower than - * tsl::rh::power_of_two_growth_policy in general but will probably distribute - * the values around better in the buckets with a poor hash function. - * - * To allow the compiler to optimize the modulo operation, a lookup table is - * used with constant primes numbers. - * - * With a switch the code would look like: - * \code - * switch(iprime) { // iprime is the current prime of the hash table - * case 0: hash % 5ul; - * break; - * case 1: hash % 17ul; - * break; - * case 2: hash % 29ul; - * break; - * ... - * } - * \endcode - * - * Due to the constant variable in the modulo the compiler is able to optimize - * the operation by a series of multiplications, substractions and shifts. - * - * The 'hash % 5' could become something like 'hash - (hash * 0xCCCCCCCD) >> 34) - * * 5' in a 64 bits environment. - */ - class prime_growth_policy + }}; + + } // namespace detail + + /** + * Grow the hash table by using prime numbers as bucket count. Slower than + * tsl::rh::power_of_two_growth_policy in general but will probably distribute + * the values around better in the buckets with a poor hash function. + * + * To allow the compiler to optimize the modulo operation, a lookup table is + * used with constant primes numbers. + * + * With a switch the code would look like: + * \code + * switch(iprime) { // iprime is the current prime of the hash table + * case 0: hash % 5ul; + * break; + * case 1: hash % 17ul; + * break; + * case 2: hash % 29ul; + * break; + * ... + * } + * \endcode + * + * Due to the constant variable in the modulo the compiler is able to optimize + * the operation by a series of multiplications, substractions and shifts. + * + * The 'hash % 5' could become something like 'hash - (hash * 0xCCCCCCCD) >> 34) + * * 5' in a 64 bits environment. + */ + class prime_growth_policy + { + public: + explicit prime_growth_policy(std::size_t &min_bucket_count_in_out) { - public: - explicit prime_growth_policy(std::size_t &min_bucket_count_in_out) - { - auto it_prime = - std::lower_bound(detail::PRIMES.begin(), detail::PRIMES.end(), min_bucket_count_in_out); - if (it_prime == detail::PRIMES.end()) { - TSL_RH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); - } - - m_iprime = static_cast(std::distance(detail::PRIMES.begin(), it_prime)); - if (min_bucket_count_in_out > 0) { - min_bucket_count_in_out = *it_prime; - } - else { - min_bucket_count_in_out = 0; - } + auto it_prime = + std::lower_bound(detail::PRIMES.begin(), detail::PRIMES.end(), min_bucket_count_in_out); + if (it_prime == detail::PRIMES.end()) { + TSL_RH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); } - std::size_t bucket_for_hash(std::size_t hash) const noexcept - { - return detail::MOD_PRIME[m_iprime](hash); + m_iprime = static_cast(std::distance(detail::PRIMES.begin(), it_prime)); + if (min_bucket_count_in_out > 0) { + min_bucket_count_in_out = *it_prime; + } + else { + min_bucket_count_in_out = 0; } + } - std::size_t next_bucket_count() const - { - if (m_iprime + 1 >= detail::PRIMES.size()) { - TSL_RH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); - } + std::size_t bucket_for_hash(std::size_t hash) const noexcept + { + return detail::MOD_PRIME[m_iprime](hash); + } - return detail::PRIMES[m_iprime + 1]; + std::size_t next_bucket_count() const + { + if (m_iprime + 1 >= detail::PRIMES.size()) { + TSL_RH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); } - std::size_t max_bucket_count() const { return detail::PRIMES.back(); } + return detail::PRIMES[m_iprime + 1]; + } + + std::size_t max_bucket_count() const { return detail::PRIMES.back(); } - void clear() noexcept { m_iprime = 0; } + void clear() noexcept { m_iprime = 0; } - private: - unsigned int m_iprime; + private: + unsigned int m_iprime; - static_assert(std::numeric_limits::max() >= detail::PRIMES.size(), - "The type of m_iprime is not big enough."); - }; + static_assert(std::numeric_limits::max() >= detail::PRIMES.size(), + "The type of m_iprime is not big enough."); + }; - } // namespace rh -} // namespace tsl +} // namespace tsl::rh #endif diff --git a/packages/seacas/libraries/ioss/src/robin_hash.h b/packages/seacas/libraries/ioss/src/robin_hash.h index e652d02fb3..4835d651fa 100644 --- a/packages/seacas/libraries/ioss/src/robin_hash.h +++ b/packages/seacas/libraries/ioss/src/robin_hash.h @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2017 Thibaut Goetghebuer-Planchon + * Copyright (c) 2017, 2023 Thibaut Goetghebuer-Planchon * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -42,1557 +42,1540 @@ #include "robin_growth_policy.h" -namespace tsl { +namespace tsl::detail_robin_hash { + + template struct make_void + { + using type = void; + }; + + template struct has_is_transparent : std::false_type + { + }; + + template + struct has_is_transparent::type> + : std::true_type + { + }; + + template struct is_power_of_two_policy : std::false_type + { + }; + + template + struct is_power_of_two_policy> : std::true_type + { + }; + + // Only available in C++17, we need to be compatible with C++11 + template const T &clamp(const T &v, const T &lo, const T &hi) + { + return std::min(hi, std::max(lo, v)); + } + + template + static T numeric_cast(U value, const char *error_message = "numeric_cast() failed.") + { + T ret = static_cast(value); + if (static_cast(ret) != value) { + TSL_RH_THROW_OR_TERMINATE(std::runtime_error, error_message); + } - namespace detail_robin_hash { + const bool is_same_signedness = (std::is_unsigned::value && std::is_unsigned::value) || + (std::is_signed::value && std::is_signed::value); + if (!is_same_signedness && (ret < T{}) != (value < U{})) { + TSL_RH_THROW_OR_TERMINATE(std::runtime_error, error_message); + } - template struct make_void - { - using type = void; - }; + return ret; + } - template struct has_is_transparent : std::false_type + template static T deserialize_value(Deserializer &deserializer) + { + // MSVC < 2017 is not conformant, circumvent the problem by removing the + // template keyword +#if defined(_MSC_VER) && _MSC_VER < 1910 + return deserializer.Deserializer::operator()(); +#else + return deserializer.Deserializer::template operator()(); +#endif + } + + /** + * Fixed size type used to represent size_type values on serialization. Need to + * be big enough to represent a std::size_t on 32 and 64 bits platforms, and + * must be the same size on both platforms. + */ + using slz_size_type = std::uint64_t; + static_assert(std::numeric_limits::max() >= + std::numeric_limits::max(), + "slz_size_type must be >= std::size_t"); + + using truncated_hash_type = std::uint32_t; + + /** + * Helper class that stores a truncated hash if StoreHash is true and nothing + * otherwise. + */ + template class bucket_entry_hash + { + public: + bool bucket_hash_equal(std::size_t /*hash*/) const noexcept { return true; } + + truncated_hash_type truncated_hash() const noexcept { return 0; } + + protected: + void set_hash(truncated_hash_type /*hash*/) noexcept {} + }; + + template <> class bucket_entry_hash + { + public: + bool bucket_hash_equal(std::size_t my_hash) const noexcept { - }; + return m_hash == truncated_hash_type(my_hash); + } - template - struct has_is_transparent::type> - : std::true_type + truncated_hash_type truncated_hash() const noexcept { return m_hash; } + + protected: + void set_hash(truncated_hash_type my_hash) noexcept { m_hash = truncated_hash_type(my_hash); } + + private: + truncated_hash_type m_hash; + }; + + /** + * Each bucket entry has: + * - A value of type `ValueType`. + * - An integer to store how far the value of the bucket, if any, is from its + * ideal bucket (ex: if the current bucket 5 has the value 'foo' and + * `hash('foo') % nb_buckets` == 3, `dist_from_ideal_bucket()` will return 2 as + * the current value of the bucket is two buckets away from its ideal bucket) If + * there is no value in the bucket (i.e. `empty()` is true) + * `dist_from_ideal_bucket()` will be < 0. + * - A marker which tells us if the bucket is the last bucket of the bucket + * array (useful for the iterator of the hash table). + * - If `StoreHash` is true, 32 bits of the hash of the value, if any, are also + * stored in the bucket. If the size of the hash is more than 32 bits, it is + * truncated. We don't store the full hash as storing the hash is a potential + * opportunity to use the unused space due to the alignment of the bucket_entry + * structure. We can thus potentially store the hash without any extra space + * (which would not be possible with 64 bits of the hash). + */ + template + class bucket_entry : public bucket_entry_hash + { + using bucket_hash = bucket_entry_hash; + + public: + using value_type = ValueType; + using distance_type = std::int16_t; + + bucket_entry() noexcept + : bucket_hash(), m_dist_from_ideal_bucket(EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET), + m_last_bucket(false) { - }; + tsl_rh_assert(empty()); + } - template struct is_power_of_two_policy : std::false_type + bucket_entry(bool last_bucket) noexcept + : bucket_hash(), m_dist_from_ideal_bucket(EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET), + m_last_bucket(last_bucket) { - }; + tsl_rh_assert(empty()); + } - template - struct is_power_of_two_policy> - : std::true_type + bucket_entry(const bucket_entry &other) noexcept( + std::is_nothrow_copy_constructible::value) + : bucket_hash(other), m_dist_from_ideal_bucket(EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET), + m_last_bucket(other.m_last_bucket) { - }; + if (!other.empty()) { + ::new (static_cast(std::addressof(m_value))) value_type(other.value()); + m_dist_from_ideal_bucket = other.m_dist_from_ideal_bucket; + } + tsl_rh_assert(empty() == other.empty()); + } - // Only available in C++17, we need to be compatible with C++11 - template const T &clamp(const T &v, const T &lo, const T &hi) + /** + * Never really used, but still necessary as we must call resize on an empty + * `std::vector`. and we need to support move-only types. See + * robin_hash constructor for details. + */ + bucket_entry(bucket_entry &&other) noexcept( + std::is_nothrow_move_constructible::value) + : bucket_hash(std::move(other)), + m_dist_from_ideal_bucket(EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET), + m_last_bucket(other.m_last_bucket) { - return std::min(hi, std::max(lo, v)); + if (!other.empty()) { + ::new (static_cast(std::addressof(m_value))) value_type(std::move(other.value())); + m_dist_from_ideal_bucket = other.m_dist_from_ideal_bucket; + } + tsl_rh_assert(empty() == other.empty()); } - template - static T numeric_cast(U value, const char *error_message = "numeric_cast() failed.") + bucket_entry &operator=(const bucket_entry &other) noexcept( + std::is_nothrow_copy_constructible::value) { - T ret = static_cast(value); - if (static_cast(ret) != value) { - TSL_RH_THROW_OR_TERMINATE(std::runtime_error, error_message); + if (this != &other) { + clear(); + + bucket_hash::operator=(other); + if (!other.empty()) { + ::new (static_cast(std::addressof(m_value))) value_type(other.value()); + } + + m_dist_from_ideal_bucket = other.m_dist_from_ideal_bucket; + m_last_bucket = other.m_last_bucket; } - const bool is_same_signedness = (std::is_unsigned::value && std::is_unsigned::value) || - (std::is_signed::value && std::is_signed::value); - if (!is_same_signedness && (ret < T{}) != (value < U{})) { - TSL_RH_THROW_OR_TERMINATE(std::runtime_error, error_message); + return *this; + } + + bucket_entry &operator=(bucket_entry &&) = delete; + + ~bucket_entry() noexcept { clear(); } + + void clear() noexcept + { + if (!empty()) { + destroy_value(); + m_dist_from_ideal_bucket = EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET; } + } - return ret; + bool empty() const noexcept + { + return m_dist_from_ideal_bucket == EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET; } - template static T deserialize_value(Deserializer &deserializer) + value_type &value() noexcept { - // MSVC < 2017 is not conformant, circumvent the problem by removing the - // template keyword -#if defined(_MSC_VER) && _MSC_VER < 1910 - return deserializer.Deserializer::operator()(); + tsl_rh_assert(!empty()); +#if defined(__cplusplus) && __cplusplus >= 201703L + return *std::launder(reinterpret_cast(std::addressof(m_value))); #else - return deserializer.Deserializer::template operator()(); + return *reinterpret_cast(std::addressof(m_value)); #endif } - /** - * Fixed size type used to represent size_type values on serialization. Need to - * be big enough to represent a std::size_t on 32 and 64 bits platforms, and - * must be the same size on both platforms. - */ - using slz_size_type = std::uint64_t; - static_assert(std::numeric_limits::max() >= - std::numeric_limits::max(), - "slz_size_type must be >= std::size_t"); + const value_type &value() const noexcept + { + tsl_rh_assert(!empty()); +#if defined(__cplusplus) && __cplusplus >= 201703L + return *std::launder(reinterpret_cast(std::addressof(m_value))); +#else + return *reinterpret_cast(std::addressof(m_value)); +#endif + } - using truncated_hash_type = std::uint32_t; + distance_type dist_from_ideal_bucket() const noexcept { return m_dist_from_ideal_bucket; } - /** - * Helper class that stores a truncated hash if StoreHash is true and nothing - * otherwise. - */ - template class bucket_entry_hash + bool last_bucket() const noexcept { return m_last_bucket; } + + void set_as_last_bucket() noexcept { m_last_bucket = true; } + + template + void set_value_of_empty_bucket(distance_type dist_from_ideal_bucket, + truncated_hash_type my_hash, Args &&...value_type_args) { - public: - bool bucket_hash_equal(std::size_t /*hash*/) const noexcept { return true; } + tsl_rh_assert(dist_from_ideal_bucket >= 0); + tsl_rh_assert(empty()); - truncated_hash_type truncated_hash() const noexcept { return 0; } + ::new (static_cast(std::addressof(m_value))) + value_type(std::forward(value_type_args)...); + this->set_hash(my_hash); + m_dist_from_ideal_bucket = dist_from_ideal_bucket; - protected: - void set_hash(truncated_hash_type /*hash*/) noexcept {} - }; + tsl_rh_assert(!empty()); + } - template <> class bucket_entry_hash + void swap_with_value_in_bucket(distance_type &dist_from_ideal_bucket, + truncated_hash_type &my_hash, value_type &value) { - public: - bool bucket_hash_equal(std::size_t my_hash) const noexcept - { - return m_hash == truncated_hash_type(my_hash); - } + tsl_rh_assert(!empty()); + tsl_rh_assert(dist_from_ideal_bucket > m_dist_from_ideal_bucket); - truncated_hash_type truncated_hash() const noexcept { return m_hash; } + using std::swap; + swap(value, this->value()); + swap(dist_from_ideal_bucket, m_dist_from_ideal_bucket); - protected: - void set_hash(truncated_hash_type my_hash) noexcept { m_hash = truncated_hash_type(my_hash); } + if (StoreHash) { + const truncated_hash_type tmp_hash = this->truncated_hash(); + this->set_hash(my_hash); + my_hash = tmp_hash; + } + else { + // Avoid warning of unused variable if StoreHash is false + TSL_RH_UNUSED(my_hash); + } + } - private: - truncated_hash_type m_hash; - }; + static truncated_hash_type truncate_hash(std::size_t my_hash) noexcept + { + return truncated_hash_type(my_hash); + } + + private: + void destroy_value() noexcept + { + tsl_rh_assert(!empty()); + value().~value_type(); + } + public: + static const distance_type EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET = -1; + static const distance_type DIST_FROM_IDEAL_BUCKET_LIMIT = 8192; + static_assert(DIST_FROM_IDEAL_BUCKET_LIMIT <= std::numeric_limits::max() - 1, + "DIST_FROM_IDEAL_BUCKET_LIMIT must be <= " + "std::numeric_limits::max() - 1."); + + private: + distance_type m_dist_from_ideal_bucket; + bool m_last_bucket; + alignas(value_type) unsigned char m_value[sizeof(value_type)]; + }; + + /** + * Internal common class used by `robin_map` and `robin_set`. + * + * ValueType is what will be stored by `robin_hash` (usually `std::pair` + * for map and `Key` for set). + * + * `KeySelect` should be a `FunctionObject` which takes a `ValueType` in + * parameter and returns a reference to the key. + * + * `ValueSelect` should be a `FunctionObject` which takes a `ValueType` in + * parameter and returns a reference to the value. `ValueSelect` should be void + * if there is no value (in a set for example). + * + * The strong exception guarantee only holds if the expression + * `std::is_nothrow_swappable\:\:value && + * std::is_nothrow_move_constructible\:\:value` is true. + * + * Behaviour is undefined if the destructor of `ValueType` throws. + */ + template + class robin_hash : private Hash, private KeyEqual, private GrowthPolicy + { + private: + template + using has_mapped_type = typename std::integral_constant::value>; + + static_assert(noexcept(std::declval().bucket_for_hash(std::size_t(0))), + "GrowthPolicy::bucket_for_hash must be noexcept."); + static_assert(noexcept(std::declval().clear()), + "GrowthPolicy::clear must be noexcept."); + + public: + template class robin_iterator; + + using key_type = typename KeySelect::key_type; + using value_type = ValueType; + using size_type = std::size_t; + using difference_type = std::ptrdiff_t; + using hasher = Hash; + using key_equal = KeyEqual; + using allocator_type = Allocator; + using reference = value_type &; + using const_reference = const value_type &; + using pointer = value_type *; + using const_pointer = const value_type *; + using iterator = robin_iterator; + using const_iterator = robin_iterator; + + private: /** - * Each bucket entry has: - * - A value of type `ValueType`. - * - An integer to store how far the value of the bucket, if any, is from its - * ideal bucket (ex: if the current bucket 5 has the value 'foo' and - * `hash('foo') % nb_buckets` == 3, `dist_from_ideal_bucket()` will return 2 as - * the current value of the bucket is two buckets away from its ideal bucket) If - * there is no value in the bucket (i.e. `empty()` is true) - * `dist_from_ideal_bucket()` will be < 0. - * - A marker which tells us if the bucket is the last bucket of the bucket - * array (useful for the iterator of the hash table). - * - If `StoreHash` is true, 32 bits of the hash of the value, if any, are also - * stored in the bucket. If the size of the hash is more than 32 bits, it is - * truncated. We don't store the full hash as storing the hash is a potential - * opportunity to use the unused space due to the alignment of the bucket_entry - * structure. We can thus potentially store the hash without any extra space - * (which would not be possible with 64 bits of the hash). + * Either store the hash because we are asked by the `StoreHash` template + * parameter or store the hash because it doesn't cost us anything in size and + * can be used to speed up rehash. */ - template - class bucket_entry : public bucket_entry_hash - { - using bucket_hash = bucket_entry_hash; + static constexpr bool STORE_HASH = + StoreHash || + ((sizeof(tsl::detail_robin_hash::bucket_entry) == + sizeof(tsl::detail_robin_hash::bucket_entry)) && + (sizeof(std::size_t) == sizeof(truncated_hash_type) || + is_power_of_two_policy::value) && + // Don't store the hash for primitive types with default hash. + (!std::is_arithmetic::value || !std::is_same>::value)); - public: - using value_type = ValueType; - using distance_type = std::int16_t; + /** + * Only use the stored hash on lookup if we are explicitly asked. We are not + * sure how slow the KeyEqual operation is. An extra comparison may slow + * things down with a fast KeyEqual. + */ + static constexpr bool USE_STORED_HASH_ON_LOOKUP = StoreHash; - bucket_entry() noexcept - : bucket_hash(), m_dist_from_ideal_bucket(EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET), - m_last_bucket(false) - { - tsl_rh_assert(empty()); + /** + * We can only use the hash on rehash if the size of the hash type is the same + * as the stored one or if we use a power of two modulo. In the case of the + * power of two modulo, we just mask the least significant bytes, we just have + * to check that the truncated_hash_type didn't truncated more bytes. + */ + static bool USE_STORED_HASH_ON_REHASH(size_type bucket_count) + { + if (STORE_HASH && sizeof(std::size_t) == sizeof(truncated_hash_type)) { + TSL_RH_UNUSED(bucket_count); + return true; } - - bucket_entry(bool last_bucket) noexcept - : bucket_hash(), m_dist_from_ideal_bucket(EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET), - m_last_bucket(last_bucket) - { - tsl_rh_assert(empty()); + else if (STORE_HASH && is_power_of_two_policy::value) { + return bucket_count == 0 || + (bucket_count - 1) <= std::numeric_limits::max(); } - - bucket_entry(const bucket_entry &other) noexcept( - std::is_nothrow_copy_constructible::value) - : bucket_hash(other), m_dist_from_ideal_bucket(EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET), - m_last_bucket(other.m_last_bucket) - { - if (!other.empty()) { - ::new (static_cast(std::addressof(m_value))) value_type(other.value()); - m_dist_from_ideal_bucket = other.m_dist_from_ideal_bucket; - } - tsl_rh_assert(empty() == other.empty()); + else { + TSL_RH_UNUSED(bucket_count); + return false; } + } - /** - * Never really used, but still necessary as we must call resize on an empty - * `std::vector`. and we need to support move-only types. See - * robin_hash constructor for details. - */ - bucket_entry(bucket_entry &&other) noexcept( - std::is_nothrow_move_constructible::value) - : bucket_hash(std::move(other)), - m_dist_from_ideal_bucket(EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET), - m_last_bucket(other.m_last_bucket) - { - if (!other.empty()) { - ::new (static_cast(std::addressof(m_value))) value_type(std::move(other.value())); - m_dist_from_ideal_bucket = other.m_dist_from_ideal_bucket; - } - tsl_rh_assert(empty() == other.empty()); - } + using bucket_entry = tsl::detail_robin_hash::bucket_entry; + using distance_type = typename bucket_entry::distance_type; - bucket_entry &operator=(const bucket_entry &other) noexcept( - std::is_nothrow_copy_constructible::value) - { - if (this != &other) { - clear(); + using buckets_allocator = + typename std::allocator_traits::template rebind_alloc; + using buckets_container_type = std::vector; - bucket_hash::operator=(other); - if (!other.empty()) { - ::new (static_cast(std::addressof(m_value))) value_type(other.value()); - } + public: + /** + * The 'operator*()' and 'operator->()' methods return a const reference and + * const pointer respectively to the stored value type. + * + * In case of a map, to get a mutable reference to the value associated to a + * key (the '.second' in the stored pair), you have to call 'value()'. + * + * The main reason for this is that if we returned a `std::pair&` + * instead of a `const std::pair&`, the user may modify the key which + * will put the map in a undefined state. + */ + template class robin_iterator + { + friend class robin_hash; - m_dist_from_ideal_bucket = other.m_dist_from_ideal_bucket; - m_last_bucket = other.m_last_bucket; - } + private: + using bucket_entry_ptr = + typename std::conditional::type; - return *this; - } + robin_iterator(bucket_entry_ptr bucket) noexcept : m_bucket(bucket) {} - bucket_entry &operator=(bucket_entry &&) = delete; + public: + using iterator_category = std::forward_iterator_tag; + using value_type = const typename robin_hash::value_type; + using difference_type = std::ptrdiff_t; + using reference = value_type &; + using pointer = value_type *; - ~bucket_entry() noexcept { clear(); } + robin_iterator() noexcept = default; - void clear() noexcept + // Copy constructor from iterator to const_iterator. + template ::type * = nullptr> + robin_iterator(const robin_iterator &other) noexcept : m_bucket(other.m_bucket) { - if (!empty()) { - destroy_value(); - m_dist_from_ideal_bucket = EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET; - } } - bool empty() const noexcept - { - return m_dist_from_ideal_bucket == EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET; - } + robin_iterator(const robin_iterator &other) = default; + robin_iterator(robin_iterator &&other) = default; + robin_iterator &operator=(const robin_iterator &other) = default; + robin_iterator &operator=(robin_iterator &&other) = default; - value_type &value() noexcept + const typename robin_hash::key_type &key() const { return KeySelect()(m_bucket->value()); } + + template ::value && IsConst>::type * = nullptr> + const typename U::value_type &value() const { - tsl_rh_assert(!empty()); -#if defined(__cplusplus) && __cplusplus >= 201703L - return *std::launder(reinterpret_cast(std::addressof(m_value))); -#else - return *reinterpret_cast(std::addressof(m_value)); -#endif + return U()(m_bucket->value()); } - const value_type &value() const noexcept + template ::value && !IsConst>::type * = nullptr> + typename U::value_type &value() const { - tsl_rh_assert(!empty()); -#if defined(__cplusplus) && __cplusplus >= 201703L - return *std::launder(reinterpret_cast(std::addressof(m_value))); -#else - return *reinterpret_cast(std::addressof(m_value)); -#endif + return U()(m_bucket->value()); } - distance_type dist_from_ideal_bucket() const noexcept { return m_dist_from_ideal_bucket; } - - bool last_bucket() const noexcept { return m_last_bucket; } + reference operator*() const { return m_bucket->value(); } - void set_as_last_bucket() noexcept { m_last_bucket = true; } + pointer operator->() const { return std::addressof(m_bucket->value()); } - template - void set_value_of_empty_bucket(distance_type dist_from_ideal_bucket, - truncated_hash_type my_hash, Args &&...value_type_args) + robin_iterator &operator++() { - tsl_rh_assert(dist_from_ideal_bucket >= 0); - tsl_rh_assert(empty()); - - ::new (static_cast(std::addressof(m_value))) - value_type(std::forward(value_type_args)...); - this->set_hash(my_hash); - m_dist_from_ideal_bucket = dist_from_ideal_bucket; + while (true) { + if (m_bucket->last_bucket()) { + ++m_bucket; + return *this; + } - tsl_rh_assert(!empty()); + ++m_bucket; + if (!m_bucket->empty()) { + return *this; + } + } } - void swap_with_value_in_bucket(distance_type &dist_from_ideal_bucket, - truncated_hash_type &my_hash, value_type &value) + robin_iterator operator++(int) { - tsl_rh_assert(!empty()); - tsl_rh_assert(dist_from_ideal_bucket > m_dist_from_ideal_bucket); - - using std::swap; - swap(value, this->value()); - swap(dist_from_ideal_bucket, m_dist_from_ideal_bucket); + robin_iterator tmp(*this); + ++*this; - if (StoreHash) { - const truncated_hash_type tmp_hash = this->truncated_hash(); - this->set_hash(my_hash); - my_hash = tmp_hash; - } - else { - // Avoid warning of unused variable if StoreHash is false - TSL_RH_UNUSED(my_hash); - } + return tmp; } - static truncated_hash_type truncate_hash(std::size_t my_hash) noexcept + friend bool operator==(const robin_iterator &lhs, const robin_iterator &rhs) { - return truncated_hash_type(my_hash); + return lhs.m_bucket == rhs.m_bucket; } - private: - void destroy_value() noexcept + friend bool operator!=(const robin_iterator &lhs, const robin_iterator &rhs) { - tsl_rh_assert(!empty()); - value().~value_type(); + return !(lhs == rhs); } - public: - static const distance_type EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET = -1; - static const distance_type DIST_FROM_IDEAL_BUCKET_LIMIT = 8192; - static_assert(DIST_FROM_IDEAL_BUCKET_LIMIT <= std::numeric_limits::max() - 1, - "DIST_FROM_IDEAL_BUCKET_LIMIT must be <= " - "std::numeric_limits::max() - 1."); - private: - distance_type m_dist_from_ideal_bucket; - bool m_last_bucket; - alignas(value_type) unsigned char m_value[sizeof(value_type)]; + bucket_entry_ptr m_bucket; }; + public: +#if defined(__cplusplus) && __cplusplus >= 201402L + robin_hash(size_type bucket_count, const Hash &my_hash, const KeyEqual &equal, + const Allocator &alloc, float min_load_factor = DEFAULT_MIN_LOAD_FACTOR, + float max_load_factor = DEFAULT_MAX_LOAD_FACTOR) + : Hash(my_hash), KeyEqual(equal), GrowthPolicy(bucket_count), + m_buckets_data(bucket_count, alloc), + m_buckets(m_buckets_data.empty() ? static_empty_bucket_ptr() : m_buckets_data.data()), + m_bucket_count(bucket_count) + { + if (bucket_count > max_bucket_count()) { + TSL_RH_THROW_OR_TERMINATE(std::length_error, "The map exceeds its maximum bucket count."); + } + + if (m_bucket_count > 0) { + tsl_rh_assert(!m_buckets_data.empty()); + m_buckets_data.back().set_as_last_bucket(); + } + + this->min_load_factor(min_load_factor); + this->max_load_factor(max_load_factor); + } +#else /** - * Internal common class used by `robin_map` and `robin_set`. + * C++11 doesn't support the creation of a std::vector with a custom allocator + * and 'count' default-inserted elements. The needed contructor `explicit + * vector(size_type count, const Allocator& alloc = Allocator());` is only + * available in C++14 and later. We thus must resize after using the + * `vector(const Allocator& alloc)` constructor. * - * ValueType is what will be stored by `robin_hash` (usually `std::pair` - * for map and `Key` for set). - * - * `KeySelect` should be a `FunctionObject` which takes a `ValueType` in - * parameter and returns a reference to the key. - * - * `ValueSelect` should be a `FunctionObject` which takes a `ValueType` in - * parameter and returns a reference to the value. `ValueSelect` should be void - * if there is no value (in a set for example). - * - * The strong exception guarantee only holds if the expression - * `std::is_nothrow_swappable\:\:value && - * std::is_nothrow_move_constructible\:\:value` is true. - * - * Behaviour is undefined if the destructor of `ValueType` throws. + * We can't use `vector(size_type count, const T& value, const Allocator& + * alloc)` as it requires the value T to be copyable. */ - template - class robin_hash : private Hash, private KeyEqual, private GrowthPolicy + robin_hash(size_type bucket_count, const Hash &my_hash, const KeyEqual &equal, + const Allocator &alloc, float min_load_factor = DEFAULT_MIN_LOAD_FACTOR, + float max_load_factor = DEFAULT_MAX_LOAD_FACTOR) + : Hash(my_hash), KeyEqual(equal), GrowthPolicy(bucket_count), m_buckets_data(alloc), + m_buckets(static_empty_bucket_ptr()), m_bucket_count(bucket_count) { - private: - template - using has_mapped_type = typename std::integral_constant::value>; + if (bucket_count > max_bucket_count()) { + TSL_RH_THROW_OR_TERMINATE(std::length_error, "The map exceeds its maximum bucket count."); + } - static_assert(noexcept(std::declval().bucket_for_hash(std::size_t(0))), - "GrowthPolicy::bucket_for_hash must be noexcept."); - static_assert(noexcept(std::declval().clear()), - "GrowthPolicy::clear must be noexcept."); + if (m_bucket_count > 0) { + m_buckets_data.resize(m_bucket_count); + m_buckets = m_buckets_data.data(); - public: - template class robin_iterator; - - using key_type = typename KeySelect::key_type; - using value_type = ValueType; - using size_type = std::size_t; - using difference_type = std::ptrdiff_t; - using hasher = Hash; - using key_equal = KeyEqual; - using allocator_type = Allocator; - using reference = value_type &; - using const_reference = const value_type &; - using pointer = value_type *; - using const_pointer = const value_type *; - using iterator = robin_iterator; - using const_iterator = robin_iterator; + tsl_rh_assert(!m_buckets_data.empty()); + m_buckets_data.back().set_as_last_bucket(); + } - private: - /** - * Either store the hash because we are asked by the `StoreHash` template - * parameter or store the hash because it doesn't cost us anything in size and - * can be used to speed up rehash. - */ - static constexpr bool STORE_HASH = - StoreHash || ((sizeof(tsl::detail_robin_hash::bucket_entry) == - sizeof(tsl::detail_robin_hash::bucket_entry)) && - (sizeof(std::size_t) == sizeof(truncated_hash_type) || - is_power_of_two_policy::value) && - // Don't store the hash for primitive types with default hash. - (!std::is_arithmetic::value || - !std::is_same>::value)); + this->min_load_factor(min_load_factor); + this->max_load_factor(max_load_factor); + } +#endif - /** - * Only use the stored hash on lookup if we are explicitly asked. We are not - * sure how slow the KeyEqual operation is. An extra comparison may slow - * things down with a fast KeyEqual. - */ - static constexpr bool USE_STORED_HASH_ON_LOOKUP = StoreHash; + robin_hash(const robin_hash &other) + : Hash(other), KeyEqual(other), GrowthPolicy(other), m_buckets_data(other.m_buckets_data), + m_buckets(m_buckets_data.empty() ? static_empty_bucket_ptr() : m_buckets_data.data()), + m_bucket_count(other.m_bucket_count), m_nb_elements(other.m_nb_elements), + m_load_threshold(other.m_load_threshold), m_min_load_factor(other.m_min_load_factor), + m_max_load_factor(other.m_max_load_factor), + m_grow_on_next_insert(other.m_grow_on_next_insert), + m_try_shrink_on_next_insert(other.m_try_shrink_on_next_insert) + { + } - /** - * We can only use the hash on rehash if the size of the hash type is the same - * as the stored one or if we use a power of two modulo. In the case of the - * power of two modulo, we just mask the least significant bytes, we just have - * to check that the truncated_hash_type didn't truncated more bytes. - */ - static bool USE_STORED_HASH_ON_REHASH(size_type bucket_count) - { - if (STORE_HASH && sizeof(std::size_t) == sizeof(truncated_hash_type)) { - TSL_RH_UNUSED(bucket_count); - return true; - } - else if (STORE_HASH && is_power_of_two_policy::value) { - return bucket_count == 0 || - (bucket_count - 1) <= std::numeric_limits::max(); - } - else { - TSL_RH_UNUSED(bucket_count); - return false; - } - } + robin_hash(robin_hash &&other) noexcept( + std::is_nothrow_move_constructible::value &&std::is_nothrow_move_constructible< + KeyEqual>::value &&std::is_nothrow_move_constructible::value + &&std::is_nothrow_move_constructible::value) + : Hash(std::move(static_cast(other))), + KeyEqual(std::move(static_cast(other))), + GrowthPolicy(std::move(static_cast(other))), + m_buckets_data(std::move(other.m_buckets_data)), + m_buckets(m_buckets_data.empty() ? static_empty_bucket_ptr() : m_buckets_data.data()), + m_bucket_count(other.m_bucket_count), m_nb_elements(other.m_nb_elements), + m_load_threshold(other.m_load_threshold), m_min_load_factor(other.m_min_load_factor), + m_max_load_factor(other.m_max_load_factor), + m_grow_on_next_insert(other.m_grow_on_next_insert), + m_try_shrink_on_next_insert(other.m_try_shrink_on_next_insert) + { + other.clear_and_shrink(); + } - using bucket_entry = tsl::detail_robin_hash::bucket_entry; - using distance_type = typename bucket_entry::distance_type; + robin_hash &operator=(const robin_hash &other) + { + if (&other != this) { + Hash::operator=(other); + KeyEqual::operator=(other); + GrowthPolicy::operator=(other); - using buckets_allocator = - typename std::allocator_traits::template rebind_alloc; - using buckets_container_type = std::vector; + m_buckets_data = other.m_buckets_data; + m_buckets = m_buckets_data.empty() ? static_empty_bucket_ptr() : m_buckets_data.data(); + m_bucket_count = other.m_bucket_count; + m_nb_elements = other.m_nb_elements; - public: - /** - * The 'operator*()' and 'operator->()' methods return a const reference and - * const pointer respectively to the stored value type. - * - * In case of a map, to get a mutable reference to the value associated to a - * key (the '.second' in the stored pair), you have to call 'value()'. - * - * The main reason for this is that if we returned a `std::pair&` - * instead of a `const std::pair&`, the user may modify the key which - * will put the map in a undefined state. - */ - template class robin_iterator - { - friend class robin_hash; + m_load_threshold = other.m_load_threshold; + m_min_load_factor = other.m_min_load_factor; + m_max_load_factor = other.m_max_load_factor; - private: - using bucket_entry_ptr = - typename std::conditional::type; + m_grow_on_next_insert = other.m_grow_on_next_insert; + m_try_shrink_on_next_insert = other.m_try_shrink_on_next_insert; + } - robin_iterator(bucket_entry_ptr bucket) noexcept : m_bucket(bucket) {} + return *this; + } - public: - using iterator_category = std::forward_iterator_tag; - using value_type = const typename robin_hash::value_type; - using difference_type = std::ptrdiff_t; - using reference = value_type &; - using pointer = value_type *; + robin_hash &operator=(robin_hash &&other) + { + other.swap(*this); + other.clear_and_shrink(); - robin_iterator() noexcept {} + return *this; + } - // Copy constructor from iterator to const_iterator. - template ::type * = nullptr> - robin_iterator(const robin_iterator &other) noexcept : m_bucket(other.m_bucket) - { - } + allocator_type get_allocator() const { return m_buckets_data.get_allocator(); } - robin_iterator(const robin_iterator &other) = default; - robin_iterator(robin_iterator &&other) = default; - robin_iterator &operator=(const robin_iterator &other) = default; - robin_iterator &operator=(robin_iterator &&other) = default; + /* + * Iterators + */ + iterator begin() noexcept + { + std::size_t i = 0; + while (i < m_bucket_count && m_buckets[i].empty()) { + i++; + } - const typename robin_hash::key_type &key() const { return KeySelect()(m_bucket->value()); } + return iterator(m_buckets + i); + } - template ::value && IsConst>::type * = nullptr> - const typename U::value_type &value() const - { - return U()(m_bucket->value()); - } + const_iterator begin() const noexcept { return cbegin(); } - template ::value && !IsConst>::type * = nullptr> - typename U::value_type &value() const - { - return U()(m_bucket->value()); - } + const_iterator cbegin() const noexcept + { + std::size_t i = 0; + while (i < m_bucket_count && m_buckets[i].empty()) { + i++; + } - reference operator*() const { return m_bucket->value(); } + return const_iterator(m_buckets + i); + } - pointer operator->() const { return std::addressof(m_bucket->value()); } + iterator end() noexcept { return iterator(m_buckets + m_bucket_count); } - robin_iterator &operator++() - { - while (true) { - if (m_bucket->last_bucket()) { - ++m_bucket; - return *this; - } + const_iterator end() const noexcept { return cend(); } - ++m_bucket; - if (!m_bucket->empty()) { - return *this; - } - } - } + const_iterator cend() const noexcept { return const_iterator(m_buckets + m_bucket_count); } - robin_iterator operator++(int) - { - robin_iterator tmp(*this); - ++*this; + /* + * Capacity + */ + bool empty() const noexcept { return m_nb_elements == 0; } - return tmp; - } + size_type size() const noexcept { return m_nb_elements; } - friend bool operator==(const robin_iterator &lhs, const robin_iterator &rhs) - { - return lhs.m_bucket == rhs.m_bucket; - } + size_type max_size() const noexcept { return m_buckets_data.max_size(); } - friend bool operator!=(const robin_iterator &lhs, const robin_iterator &rhs) - { - return !(lhs == rhs); + /* + * Modifiers + */ + void clear() noexcept + { + if (m_min_load_factor > 0.0f) { + clear_and_shrink(); + } + else { + for (auto &bucket : m_buckets_data) { + bucket.clear(); } - private: - bucket_entry_ptr m_bucket; - }; - - public: -#if defined(__cplusplus) && __cplusplus >= 201402L - robin_hash(size_type bucket_count, const Hash &my_hash, const KeyEqual &equal, - const Allocator &alloc, float min_load_factor = DEFAULT_MIN_LOAD_FACTOR, - float max_load_factor = DEFAULT_MAX_LOAD_FACTOR) - : Hash(my_hash), KeyEqual(equal), GrowthPolicy(bucket_count), - m_buckets_data(bucket_count, alloc), - m_buckets(m_buckets_data.empty() ? static_empty_bucket_ptr() : m_buckets_data.data()), - m_bucket_count(bucket_count), m_nb_elements(0), m_grow_on_next_insert(false), - m_try_shrink_on_next_insert(false) - { - if (bucket_count > max_bucket_count()) { - TSL_RH_THROW_OR_TERMINATE(std::length_error, "The map exceeds its maximum bucket count."); - } + m_nb_elements = 0; + m_grow_on_next_insert = false; + } + } - if (m_bucket_count > 0) { - tsl_rh_assert(!m_buckets_data.empty()); - m_buckets_data.back().set_as_last_bucket(); - } + template std::pair insert(P &&value) + { + return insert_impl(KeySelect()(value), std::forward

(value)); + } - this->min_load_factor(min_load_factor); - this->max_load_factor(max_load_factor); + template iterator insert_hint(const_iterator hint, P &&value) + { + if (hint != cend() && compare_keys(KeySelect()(*hint), KeySelect()(value))) { + return mutable_iterator(hint); } -#else - /** - * C++11 doesn't support the creation of a std::vector with a custom allocator - * and 'count' default-inserted elements. The needed contructor `explicit - * vector(size_type count, const Allocator& alloc = Allocator());` is only - * available in C++14 and later. We thus must resize after using the - * `vector(const Allocator& alloc)` constructor. - * - * We can't use `vector(size_type count, const T& value, const Allocator& - * alloc)` as it requires the value T to be copyable. - */ - robin_hash(size_type bucket_count, const Hash &my_hash, const KeyEqual &equal, - const Allocator &alloc, float min_load_factor = DEFAULT_MIN_LOAD_FACTOR, - float max_load_factor = DEFAULT_MAX_LOAD_FACTOR) - : Hash(my_hash), KeyEqual(equal), GrowthPolicy(bucket_count), m_buckets_data(alloc), - m_buckets(static_empty_bucket_ptr()), m_bucket_count(bucket_count), m_nb_elements(0), - m_grow_on_next_insert(false), m_try_shrink_on_next_insert(false) - { - if (bucket_count > max_bucket_count()) { - TSL_RH_THROW_OR_TERMINATE(std::length_error, "The map exceeds its maximum bucket count."); - } - if (m_bucket_count > 0) { - m_buckets_data.resize(m_bucket_count); - m_buckets = m_buckets_data.data(); + return insert(std::forward

(value)).first; + } - tsl_rh_assert(!m_buckets_data.empty()); - m_buckets_data.back().set_as_last_bucket(); + template void insert(InputIt first, InputIt last) + { + if (std::is_base_of::iterator_category>::value) { + const auto nb_elements_insert = std::distance(first, last); + const size_type nb_free_buckets = m_load_threshold - size(); + tsl_rh_assert(m_load_threshold >= size()); + + if (nb_elements_insert > 0 && nb_free_buckets < size_type(nb_elements_insert)) { + reserve(size() + size_type(nb_elements_insert)); } - - this->min_load_factor(min_load_factor); - this->max_load_factor(max_load_factor); } -#endif - robin_hash(const robin_hash &other) - : Hash(other), KeyEqual(other), GrowthPolicy(other), m_buckets_data(other.m_buckets_data), - m_buckets(m_buckets_data.empty() ? static_empty_bucket_ptr() : m_buckets_data.data()), - m_bucket_count(other.m_bucket_count), m_nb_elements(other.m_nb_elements), - m_load_threshold(other.m_load_threshold), m_min_load_factor(other.m_min_load_factor), - m_max_load_factor(other.m_max_load_factor), - m_grow_on_next_insert(other.m_grow_on_next_insert), - m_try_shrink_on_next_insert(other.m_try_shrink_on_next_insert) - { + for (; first != last; ++first) { + insert(*first); } + } - robin_hash(robin_hash &&other) noexcept( - std::is_nothrow_move_constructible::value &&std::is_nothrow_move_constructible< - KeyEqual>::value &&std::is_nothrow_move_constructible::value - &&std::is_nothrow_move_constructible::value) - : Hash(std::move(static_cast(other))), - KeyEqual(std::move(static_cast(other))), - GrowthPolicy(std::move(static_cast(other))), - m_buckets_data(std::move(other.m_buckets_data)), - m_buckets(m_buckets_data.empty() ? static_empty_bucket_ptr() : m_buckets_data.data()), - m_bucket_count(other.m_bucket_count), m_nb_elements(other.m_nb_elements), - m_load_threshold(other.m_load_threshold), m_min_load_factor(other.m_min_load_factor), - m_max_load_factor(other.m_max_load_factor), - m_grow_on_next_insert(other.m_grow_on_next_insert), - m_try_shrink_on_next_insert(other.m_try_shrink_on_next_insert) - { - other.clear_and_shrink(); + template std::pair insert_or_assign(K &&key, M &&obj) + { + auto it = try_emplace(std::forward(key), std::forward(obj)); + if (!it.second) { + it.first.value() = std::forward(obj); } - robin_hash &operator=(const robin_hash &other) - { - if (&other != this) { - Hash:: operator=(other); - KeyEqual:: operator=(other); - GrowthPolicy::operator=(other); - - m_buckets_data = other.m_buckets_data; - m_buckets = m_buckets_data.empty() ? static_empty_bucket_ptr() : m_buckets_data.data(); - m_bucket_count = other.m_bucket_count; - m_nb_elements = other.m_nb_elements; - - m_load_threshold = other.m_load_threshold; - m_min_load_factor = other.m_min_load_factor; - m_max_load_factor = other.m_max_load_factor; - - m_grow_on_next_insert = other.m_grow_on_next_insert; - m_try_shrink_on_next_insert = other.m_try_shrink_on_next_insert; - } + return it; + } + + template iterator insert_or_assign(const_iterator hint, K &&key, M &&obj) + { + if (hint != cend() && compare_keys(KeySelect()(*hint), key)) { + auto it = mutable_iterator(hint); + it.value() = std::forward(obj); - return *this; + return it; } - robin_hash &operator=(robin_hash &&other) - { - other.swap(*this); - other.clear_and_shrink(); + return insert_or_assign(std::forward(key), std::forward(obj)).first; + } - return *this; - } + template std::pair emplace(Args &&...args) + { + return insert(value_type(std::forward(args)...)); + } - allocator_type get_allocator() const { return m_buckets_data.get_allocator(); } + template iterator emplace_hint(const_iterator hint, Args &&...args) + { + return insert_hint(hint, value_type(std::forward(args)...)); + } - /* - * Iterators - */ - iterator begin() noexcept - { - std::size_t i = 0; - while (i < m_bucket_count && m_buckets[i].empty()) { - i++; - } + template std::pair try_emplace(K &&key, Args &&...args) + { + return insert_impl(key, std::piecewise_construct, std::forward_as_tuple(std::forward(key)), + std::forward_as_tuple(std::forward(args)...)); + } - return iterator(m_buckets + i); + template + iterator try_emplace_hint(const_iterator hint, K &&key, Args &&...args) + { + if (hint != cend() && compare_keys(KeySelect()(*hint), key)) { + return mutable_iterator(hint); } - const_iterator begin() const noexcept { return cbegin(); } + return try_emplace(std::forward(key), std::forward(args)...).first; + } - const_iterator cbegin() const noexcept - { - std::size_t i = 0; - while (i < m_bucket_count && m_buckets[i].empty()) { - i++; - } + /** + * Here to avoid `template size_type erase(const K& key)` being used + * when we use an `iterator` instead of a `const_iterator`. + */ + iterator erase(iterator pos) + { + erase_from_bucket(pos); - return const_iterator(m_buckets + i); + /** + * Erase bucket used a backward shift after clearing the bucket. + * Check if there is a new value in the bucket, if not get the next + * non-empty. + */ + if (pos.m_bucket->empty()) { + ++pos; } - iterator end() noexcept { return iterator(m_buckets + m_bucket_count); } + m_try_shrink_on_next_insert = true; - const_iterator end() const noexcept { return cend(); } + return pos; + } - const_iterator cend() const noexcept { return const_iterator(m_buckets + m_bucket_count); } + iterator erase(const_iterator pos) { return erase(mutable_iterator(pos)); } - /* - * Capacity - */ - bool empty() const noexcept { return m_nb_elements == 0; } + iterator erase(const_iterator first, const_iterator last) + { + if (first == last) { + return mutable_iterator(first); + } - size_type size() const noexcept { return m_nb_elements; } + auto first_mutable = mutable_iterator(first); + auto last_mutable = mutable_iterator(last); + for (auto it = first_mutable.m_bucket; it != last_mutable.m_bucket; ++it) { + if (!it->empty()) { + it->clear(); + m_nb_elements--; + } + } - size_type max_size() const noexcept { return m_buckets_data.max_size(); } + if (last_mutable == end()) { + m_try_shrink_on_next_insert = true; + return end(); + } /* - * Modifiers + * Backward shift on the values which come after the deleted values. + * We try to move the values closer to their ideal bucket. */ - void clear() noexcept - { - if (m_min_load_factor > 0.0f) { - clear_and_shrink(); - } - else { - for (auto &bucket : m_buckets_data) { - bucket.clear(); - } + auto icloser_bucket = static_cast(first_mutable.m_bucket - m_buckets); + auto ito_move_closer_value = static_cast(last_mutable.m_bucket - m_buckets); + tsl_rh_assert(ito_move_closer_value > icloser_bucket); + + const std::size_t ireturn_bucket = + ito_move_closer_value - + std::min(ito_move_closer_value - icloser_bucket, + std::size_t(m_buckets[ito_move_closer_value].dist_from_ideal_bucket())); + + while (ito_move_closer_value < m_bucket_count && + m_buckets[ito_move_closer_value].dist_from_ideal_bucket() > 0) { + icloser_bucket = + ito_move_closer_value - + std::min(ito_move_closer_value - icloser_bucket, + std::size_t(m_buckets[ito_move_closer_value].dist_from_ideal_bucket())); - m_nb_elements = 0; - m_grow_on_next_insert = false; - } - } + tsl_rh_assert(m_buckets[icloser_bucket].empty()); + const distance_type new_distance = + distance_type(m_buckets[ito_move_closer_value].dist_from_ideal_bucket() - + (ito_move_closer_value - icloser_bucket)); + m_buckets[icloser_bucket].set_value_of_empty_bucket( + new_distance, m_buckets[ito_move_closer_value].truncated_hash(), + std::move(m_buckets[ito_move_closer_value].value())); + m_buckets[ito_move_closer_value].clear(); - template std::pair insert(P &&value) - { - return insert_impl(KeySelect()(value), std::forward

(value)); + ++icloser_bucket; + ++ito_move_closer_value; } - template iterator insert_hint(const_iterator hint, P &&value) - { - if (hint != cend() && compare_keys(KeySelect()(*hint), KeySelect()(value))) { - return mutable_iterator(hint); - } - - return insert(std::forward

(value)).first; - } + m_try_shrink_on_next_insert = true; - template void insert(InputIt first, InputIt last) - { - if (std::is_base_of::iterator_category>::value) { - const auto nb_elements_insert = std::distance(first, last); - const size_type nb_free_buckets = m_load_threshold - size(); - tsl_rh_assert(m_load_threshold >= size()); - - if (nb_elements_insert > 0 && nb_free_buckets < size_type(nb_elements_insert)) { - reserve(size() + size_type(nb_elements_insert)); - } - } + return iterator(m_buckets + ireturn_bucket); + } - for (; first != last; ++first) { - insert(*first); - } - } + template size_type erase(const K &key) { return erase(key, hash_key(key)); } - template std::pair insert_or_assign(K &&key, M &&obj) - { - auto it = try_emplace(std::forward(key), std::forward(obj)); - if (!it.second) { - it.first.value() = std::forward(obj); - } + template size_type erase(const K &key, std::size_t my_hash) + { + auto it = find(key, my_hash); + if (it != end()) { + erase_from_bucket(it); + m_try_shrink_on_next_insert = true; - return it; + return 1; } - - template iterator insert_or_assign(const_iterator hint, K &&key, M &&obj) - { - if (hint != cend() && compare_keys(KeySelect()(*hint), key)) { - auto it = mutable_iterator(hint); - it.value() = std::forward(obj); - - return it; - } - - return insert_or_assign(std::forward(key), std::forward(obj)).first; + else { + return 0; } + } - template std::pair emplace(Args &&...args) - { - return insert(value_type(std::forward(args)...)); - } + void swap(robin_hash &other) + { + using std::swap; + + swap(static_cast(*this), static_cast(other)); + swap(static_cast(*this), static_cast(other)); + swap(static_cast(*this), static_cast(other)); + swap(m_buckets_data, other.m_buckets_data); + swap(m_buckets, other.m_buckets); + swap(m_bucket_count, other.m_bucket_count); + swap(m_nb_elements, other.m_nb_elements); + swap(m_load_threshold, other.m_load_threshold); + swap(m_min_load_factor, other.m_min_load_factor); + swap(m_max_load_factor, other.m_max_load_factor); + swap(m_grow_on_next_insert, other.m_grow_on_next_insert); + swap(m_try_shrink_on_next_insert, other.m_try_shrink_on_next_insert); + } - template iterator emplace_hint(const_iterator hint, Args &&...args) - { - return insert_hint(hint, value_type(std::forward(args)...)); - } + /* + * Lookup + */ + template ::value>::type * = nullptr> + typename U::value_type &at(const K &key) + { + return at(key, hash_key(key)); + } - template - std::pair try_emplace(K &&key, Args &&...args) - { - return insert_impl(key, std::piecewise_construct, - std::forward_as_tuple(std::forward(key)), - std::forward_as_tuple(std::forward(args)...)); - } + template ::value>::type * = nullptr> + typename U::value_type &at(const K &key, std::size_t my_hash) + { + return const_cast( + static_cast(this)->at(key, my_hash)); + } - template - iterator try_emplace_hint(const_iterator hint, K &&key, Args &&...args) - { - if (hint != cend() && compare_keys(KeySelect()(*hint), key)) { - return mutable_iterator(hint); - } + template ::value>::type * = nullptr> + const typename U::value_type &at(const K &key) const + { + return at(key, hash_key(key)); + } - return try_emplace(std::forward(key), std::forward(args)...).first; + template ::value>::type * = nullptr> + const typename U::value_type &at(const K &key, std::size_t my_hash) const + { + auto it = find(key, my_hash); + if (it != cend()) { + return it.value(); } - - /** - * Here to avoid `template size_type erase(const K& key)` being used - * when we use an `iterator` instead of a `const_iterator`. - */ - iterator erase(iterator pos) - { - erase_from_bucket(pos); - - /** - * Erase bucket used a backward shift after clearing the bucket. - * Check if there is a new value in the bucket, if not get the next - * non-empty. - */ - if (pos.m_bucket->empty()) { - ++pos; - } - - m_try_shrink_on_next_insert = true; - - return pos; + else { + TSL_RH_THROW_OR_TERMINATE(std::out_of_range, "Couldn't find key."); } + } - iterator erase(const_iterator pos) { return erase(mutable_iterator(pos)); } - - iterator erase(const_iterator first, const_iterator last) - { - if (first == last) { - return mutable_iterator(first); - } + template ::value>::type * = nullptr> + typename U::value_type &operator[](K &&key) + { + return try_emplace(std::forward(key)).first.value(); + } - auto first_mutable = mutable_iterator(first); - auto last_mutable = mutable_iterator(last); - for (auto it = first_mutable.m_bucket; it != last_mutable.m_bucket; ++it) { - if (!it->empty()) { - it->clear(); - m_nb_elements--; - } - } + template size_type count(const K &key) const { return count(key, hash_key(key)); } - if (last_mutable == end()) { - m_try_shrink_on_next_insert = true; - return end(); - } + template size_type count(const K &key, std::size_t my_hash) const + { + if (find(key, my_hash) != cend()) { + return 1; + } + else { + return 0; + } + } - /* - * Backward shift on the values which come after the deleted values. - * We try to move the values closer to their ideal bucket. - */ - std::size_t icloser_bucket = static_cast(first_mutable.m_bucket - m_buckets); - std::size_t ito_move_closer_value = - static_cast(last_mutable.m_bucket - m_buckets); - tsl_rh_assert(ito_move_closer_value > icloser_bucket); + template iterator find(const K &key) { return find_impl(key, hash_key(key)); } - const std::size_t ireturn_bucket = - ito_move_closer_value - - std::min(ito_move_closer_value - icloser_bucket, - std::size_t(m_buckets[ito_move_closer_value].dist_from_ideal_bucket())); + template iterator find(const K &key, std::size_t my_hash) + { + return find_impl(key, my_hash); + } - while (ito_move_closer_value < m_bucket_count && - m_buckets[ito_move_closer_value].dist_from_ideal_bucket() > 0) { - icloser_bucket = - ito_move_closer_value - - std::min(ito_move_closer_value - icloser_bucket, - std::size_t(m_buckets[ito_move_closer_value].dist_from_ideal_bucket())); - - tsl_rh_assert(m_buckets[icloser_bucket].empty()); - const distance_type new_distance = - distance_type(m_buckets[ito_move_closer_value].dist_from_ideal_bucket() - - (ito_move_closer_value - icloser_bucket)); - m_buckets[icloser_bucket].set_value_of_empty_bucket( - new_distance, m_buckets[ito_move_closer_value].truncated_hash(), - std::move(m_buckets[ito_move_closer_value].value())); - m_buckets[ito_move_closer_value].clear(); - - ++icloser_bucket; - ++ito_move_closer_value; - } + template const_iterator find(const K &key) const + { + return find_impl(key, hash_key(key)); + } - m_try_shrink_on_next_insert = true; + template const_iterator find(const K &key, std::size_t my_hash) const + { + return find_impl(key, my_hash); + } - return iterator(m_buckets + ireturn_bucket); - } + template bool contains(const K &key) const { return contains(key, hash_key(key)); } - template size_type erase(const K &key) { return erase(key, hash_key(key)); } + template bool contains(const K &key, std::size_t my_hash) const + { + return count(key, my_hash) != 0; + } - template size_type erase(const K &key, std::size_t my_hash) - { - auto it = find(key, my_hash); - if (it != end()) { - erase_from_bucket(it); - m_try_shrink_on_next_insert = true; + template std::pair equal_range(const K &key) + { + return equal_range(key, hash_key(key)); + } - return 1; - } - else { - return 0; - } - } + template std::pair equal_range(const K &key, std::size_t my_hash) + { + iterator it = find(key, my_hash); + return std::make_pair(it, (it == end()) ? it : std::next(it)); + } - void swap(robin_hash &other) - { - using std::swap; - - swap(static_cast(*this), static_cast(other)); - swap(static_cast(*this), static_cast(other)); - swap(static_cast(*this), static_cast(other)); - swap(m_buckets_data, other.m_buckets_data); - swap(m_buckets, other.m_buckets); - swap(m_bucket_count, other.m_bucket_count); - swap(m_nb_elements, other.m_nb_elements); - swap(m_load_threshold, other.m_load_threshold); - swap(m_min_load_factor, other.m_min_load_factor); - swap(m_max_load_factor, other.m_max_load_factor); - swap(m_grow_on_next_insert, other.m_grow_on_next_insert); - swap(m_try_shrink_on_next_insert, other.m_try_shrink_on_next_insert); - } + template std::pair equal_range(const K &key) const + { + return equal_range(key, hash_key(key)); + } - /* - * Lookup - */ - template ::value>::type * = nullptr> - typename U::value_type &at(const K &key) - { - return at(key, hash_key(key)); - } + template + std::pair equal_range(const K &key, std::size_t my_hash) const + { + const_iterator it = find(key, my_hash); + return std::make_pair(it, (it == cend()) ? it : std::next(it)); + } - template ::value>::type * = nullptr> - typename U::value_type &at(const K &key, std::size_t my_hash) - { - return const_cast( - static_cast(this)->at(key, my_hash)); - } + /* + * Bucket interface + */ + size_type bucket_count() const { return m_bucket_count; } - template ::value>::type * = nullptr> - const typename U::value_type &at(const K &key) const - { - return at(key, hash_key(key)); - } + size_type max_bucket_count() const + { + return std::min(GrowthPolicy::max_bucket_count(), m_buckets_data.max_size()); + } - template ::value>::type * = nullptr> - const typename U::value_type &at(const K &key, std::size_t my_hash) const - { - auto it = find(key, my_hash); - if (it != cend()) { - return it.value(); - } - else { - TSL_RH_THROW_OR_TERMINATE(std::out_of_range, "Couldn't find key."); - } + /* + * Hash policy + */ + float load_factor() const + { + if (bucket_count() == 0) { + return 0; } - template ::value>::type * = nullptr> - typename U::value_type &operator[](K &&key) - { - return try_emplace(std::forward(key)).first.value(); - } + return float(m_nb_elements) / float(bucket_count()); + } - template size_type count(const K &key) const { return count(key, hash_key(key)); } + float min_load_factor() const { return m_min_load_factor; } - template size_type count(const K &key, std::size_t my_hash) const - { - if (find(key, my_hash) != cend()) { - return 1; - } - else { - return 0; - } - } + float max_load_factor() const { return m_max_load_factor; } - template iterator find(const K &key) { return find_impl(key, hash_key(key)); } + void min_load_factor(float ml) + { + m_min_load_factor = clamp(ml, float(MINIMUM_MIN_LOAD_FACTOR), float(MAXIMUM_MIN_LOAD_FACTOR)); + } - template iterator find(const K &key, std::size_t my_hash) - { - return find_impl(key, my_hash); - } + void max_load_factor(float ml) + { + m_max_load_factor = clamp(ml, float(MINIMUM_MAX_LOAD_FACTOR), float(MAXIMUM_MAX_LOAD_FACTOR)); + m_load_threshold = size_type(float(bucket_count()) * m_max_load_factor); + tsl_rh_assert(bucket_count() == 0 || m_load_threshold < bucket_count()); + } - template const_iterator find(const K &key) const - { - return find_impl(key, hash_key(key)); - } + void rehash(size_type my_count) + { + my_count = std::max(my_count, size_type(std::ceil(float(size()) / max_load_factor()))); + rehash_impl(my_count); + } - template const_iterator find(const K &key, std::size_t my_hash) const - { - return find_impl(key, my_hash); - } + void reserve(size_type my_count) + { + rehash(size_type(std::ceil(float(my_count) / max_load_factor()))); + } - template bool contains(const K &key) const { return contains(key, hash_key(key)); } + /* + * Observers + */ + hasher hash_function() const { return static_cast(*this); } - template bool contains(const K &key, std::size_t my_hash) const - { - return count(key, my_hash) != 0; - } + key_equal key_eq() const { return static_cast(*this); } - template std::pair equal_range(const K &key) - { - return equal_range(key, hash_key(key)); - } + /* + * Other + */ + iterator mutable_iterator(const_iterator pos) + { + return iterator(const_cast(pos.m_bucket)); + } - template - std::pair equal_range(const K &key, std::size_t my_hash) - { - iterator it = find(key, my_hash); - return std::make_pair(it, (it == end()) ? it : std::next(it)); - } + template void serialize(Serializer &serializer) const + { + serialize_impl(serializer); + } - template std::pair equal_range(const K &key) const - { - return equal_range(key, hash_key(key)); - } + template void deserialize(Deserializer &deserializer, bool hash_compatible) + { + deserialize_impl(deserializer, hash_compatible); + } - template - std::pair equal_range(const K &key, std::size_t my_hash) const - { - const_iterator it = find(key, my_hash); - return std::make_pair(it, (it == cend()) ? it : std::next(it)); - } + private: + template std::size_t hash_key(const K &key) const { return Hash::operator()(key); } - /* - * Bucket interface - */ - size_type bucket_count() const { return m_bucket_count; } + template bool compare_keys(const K1 &key1, const K2 &key2) const + { + return KeyEqual::operator()(key1, key2); + } - size_type max_bucket_count() const - { - return std::min(GrowthPolicy::max_bucket_count(), m_buckets_data.max_size()); - } + std::size_t bucket_for_hash(std::size_t my_hash) const + { + const std::size_t bucket = GrowthPolicy::bucket_for_hash(my_hash); + tsl_rh_assert(bucket < m_bucket_count || (bucket == 0 && m_bucket_count == 0)); - /* - * Hash policy - */ - float load_factor() const - { - if (bucket_count() == 0) { - return 0; - } + return bucket; + } - return float(m_nb_elements) / float(bucket_count()); - } + template ::value>::type * = nullptr> + std::size_t next_bucket(std::size_t index) const noexcept + { + tsl_rh_assert(index < bucket_count()); - float min_load_factor() const { return m_min_load_factor; } + return (index + 1) & this->m_mask; + } - float max_load_factor() const { return m_max_load_factor; } + template ::value>::type * = nullptr> + std::size_t next_bucket(std::size_t index) const noexcept + { + tsl_rh_assert(index < bucket_count()); - void min_load_factor(float ml) - { - m_min_load_factor = - clamp(ml, float(MINIMUM_MIN_LOAD_FACTOR), float(MAXIMUM_MIN_LOAD_FACTOR)); - } + index++; + return (index != bucket_count()) ? index : 0; + } - void max_load_factor(float ml) - { - m_max_load_factor = - clamp(ml, float(MINIMUM_MAX_LOAD_FACTOR), float(MAXIMUM_MAX_LOAD_FACTOR)); - m_load_threshold = size_type(float(bucket_count()) * m_max_load_factor); - tsl_rh_assert(bucket_count() == 0 || m_load_threshold < bucket_count()); - } + template iterator find_impl(const K &key, std::size_t my_hash) + { + return mutable_iterator(static_cast(this)->find(key, my_hash)); + } - void rehash(size_type my_count) - { - my_count = std::max(my_count, size_type(std::ceil(float(size()) / max_load_factor()))); - rehash_impl(my_count); - } + template const_iterator find_impl(const K &key, std::size_t my_hash) const + { + std::size_t ibucket = bucket_for_hash(my_hash); + distance_type dist_from_ideal_bucket = 0; + + while (dist_from_ideal_bucket <= m_buckets[ibucket].dist_from_ideal_bucket()) { + if (TSL_RH_LIKELY( + (!USE_STORED_HASH_ON_LOOKUP || m_buckets[ibucket].bucket_hash_equal(my_hash)) && + compare_keys(KeySelect()(m_buckets[ibucket].value()), key))) { + return const_iterator(m_buckets + ibucket); + } - void reserve(size_type my_count) - { - rehash(size_type(std::ceil(float(my_count) / max_load_factor()))); + ibucket = next_bucket(ibucket); + dist_from_ideal_bucket++; } - /* - * Observers - */ - hasher hash_function() const { return static_cast(*this); } + return cend(); + } - key_equal key_eq() const { return static_cast(*this); } + void erase_from_bucket(iterator pos) + { + pos.m_bucket->clear(); + m_nb_elements--; - /* - * Other + /** + * Backward shift, swap the empty bucket, previous_ibucket, with the values + * on its right, ibucket, until we cross another empty bucket or if the + * other bucket has a distance_from_ideal_bucket == 0. + * + * We try to move the values closer to their ideal bucket. */ - iterator mutable_iterator(const_iterator pos) - { - return iterator(const_cast(pos.m_bucket)); - } + auto previous_ibucket = static_cast(pos.m_bucket - m_buckets); + auto ibucket = next_bucket(previous_ibucket); - template void serialize(Serializer &serializer) const - { - serialize_impl(serializer); - } + while (m_buckets[ibucket].dist_from_ideal_bucket() > 0) { + tsl_rh_assert(m_buckets[previous_ibucket].empty()); - template - void deserialize(Deserializer &deserializer, bool hash_compatible) - { - deserialize_impl(deserializer, hash_compatible); - } + const auto new_distance = distance_type(m_buckets[ibucket].dist_from_ideal_bucket() - 1); + m_buckets[previous_ibucket].set_value_of_empty_bucket( + new_distance, m_buckets[ibucket].truncated_hash(), + std::move(m_buckets[ibucket].value())); + m_buckets[ibucket].clear(); - private: - template std::size_t hash_key(const K &key) const { return Hash::operator()(key); } - - template bool compare_keys(const K1 &key1, const K2 &key2) const - { - return KeyEqual::operator()(key1, key2); + previous_ibucket = ibucket; + ibucket = next_bucket(ibucket); } + } - std::size_t bucket_for_hash(std::size_t my_hash) const - { - const std::size_t bucket = GrowthPolicy::bucket_for_hash(my_hash); - tsl_rh_assert(bucket < m_bucket_count || (bucket == 0 && m_bucket_count == 0)); - - return bucket; - } - - template ::value>::type * = nullptr> - std::size_t next_bucket(std::size_t index) const noexcept - { - tsl_rh_assert(index < bucket_count()); - - return (index + 1) & this->m_mask; - } + template + std::pair insert_impl(const K &key, Args &&...value_type_args) + { + const std::size_t my_hash = hash_key(key); - template ::value>::type * = nullptr> - std::size_t next_bucket(std::size_t index) const noexcept - { - tsl_rh_assert(index < bucket_count()); + std::size_t ibucket = bucket_for_hash(my_hash); + distance_type dist_from_ideal_bucket = 0; - index++; - return (index != bucket_count()) ? index : 0; - } + while (dist_from_ideal_bucket <= m_buckets[ibucket].dist_from_ideal_bucket()) { + if ((!USE_STORED_HASH_ON_LOOKUP || m_buckets[ibucket].bucket_hash_equal(my_hash)) && + compare_keys(KeySelect()(m_buckets[ibucket].value()), key)) { + return std::make_pair(iterator(m_buckets + ibucket), false); + } - template iterator find_impl(const K &key, std::size_t my_hash) - { - return mutable_iterator(static_cast(this)->find(key, my_hash)); + ibucket = next_bucket(ibucket); + dist_from_ideal_bucket++; } - template const_iterator find_impl(const K &key, std::size_t my_hash) const - { - std::size_t ibucket = bucket_for_hash(my_hash); - distance_type dist_from_ideal_bucket = 0; + while (rehash_on_extreme_load(dist_from_ideal_bucket)) { + ibucket = bucket_for_hash(my_hash); + dist_from_ideal_bucket = 0; while (dist_from_ideal_bucket <= m_buckets[ibucket].dist_from_ideal_bucket()) { - if (TSL_RH_LIKELY( - (!USE_STORED_HASH_ON_LOOKUP || m_buckets[ibucket].bucket_hash_equal(my_hash)) && - compare_keys(KeySelect()(m_buckets[ibucket].value()), key))) { - return const_iterator(m_buckets + ibucket); - } - ibucket = next_bucket(ibucket); dist_from_ideal_bucket++; } - - return cend(); } - void erase_from_bucket(iterator pos) - { - pos.m_bucket->clear(); - m_nb_elements--; - - /** - * Backward shift, swap the empty bucket, previous_ibucket, with the values - * on its right, ibucket, until we cross another empty bucket or if the - * other bucket has a distance_from_ideal_bucket == 0. - * - * We try to move the values closer to their ideal bucket. - */ - std::size_t previous_ibucket = static_cast(pos.m_bucket - m_buckets); - std::size_t ibucket = next_bucket(previous_ibucket); - - while (m_buckets[ibucket].dist_from_ideal_bucket() > 0) { - tsl_rh_assert(m_buckets[previous_ibucket].empty()); - - const distance_type new_distance = - distance_type(m_buckets[ibucket].dist_from_ideal_bucket() - 1); - m_buckets[previous_ibucket].set_value_of_empty_bucket( - new_distance, m_buckets[ibucket].truncated_hash(), - std::move(m_buckets[ibucket].value())); - m_buckets[ibucket].clear(); - - previous_ibucket = ibucket; - ibucket = next_bucket(ibucket); - } + if (m_buckets[ibucket].empty()) { + m_buckets[ibucket].set_value_of_empty_bucket(dist_from_ideal_bucket, + bucket_entry::truncate_hash(my_hash), + std::forward(value_type_args)...); + } + else { + insert_value(ibucket, dist_from_ideal_bucket, bucket_entry::truncate_hash(my_hash), + std::forward(value_type_args)...); } - template - std::pair insert_impl(const K &key, Args &&...value_type_args) - { - const std::size_t my_hash = hash_key(key); + m_nb_elements++; + /* + * The value will be inserted in ibucket in any case, either because it was + * empty or by stealing the bucket (robin hood). + */ + return std::make_pair(iterator(m_buckets + ibucket), true); + } - std::size_t ibucket = bucket_for_hash(my_hash); - distance_type dist_from_ideal_bucket = 0; + template + void insert_value(std::size_t ibucket, distance_type dist_from_ideal_bucket, + truncated_hash_type my_hash, Args &&...value_type_args) + { + value_type value(std::forward(value_type_args)...); + insert_value_impl(ibucket, dist_from_ideal_bucket, my_hash, value); + } - while (dist_from_ideal_bucket <= m_buckets[ibucket].dist_from_ideal_bucket()) { - if ((!USE_STORED_HASH_ON_LOOKUP || m_buckets[ibucket].bucket_hash_equal(my_hash)) && - compare_keys(KeySelect()(m_buckets[ibucket].value()), key)) { - return std::make_pair(iterator(m_buckets + ibucket), false); + void insert_value(std::size_t ibucket, distance_type dist_from_ideal_bucket, + truncated_hash_type my_hash, value_type &&value) + { + insert_value_impl(ibucket, dist_from_ideal_bucket, my_hash, value); + } + + /* + * We don't use `value_type&& value` as last argument due to a bug in MSVC + * when `value_type` is a pointer, The compiler is not able to see the + * difference between `std::string*` and `std::string*&&` resulting in a + * compilation error. + * + * The `value` will be in a moved state at the end of the function. + */ + void insert_value_impl(std::size_t ibucket, distance_type dist_from_ideal_bucket, + truncated_hash_type my_hash, value_type &value) + { + tsl_rh_assert(dist_from_ideal_bucket > m_buckets[ibucket].dist_from_ideal_bucket()); + m_buckets[ibucket].swap_with_value_in_bucket(dist_from_ideal_bucket, my_hash, value); + ibucket = next_bucket(ibucket); + dist_from_ideal_bucket++; + + while (!m_buckets[ibucket].empty()) { + if (dist_from_ideal_bucket > m_buckets[ibucket].dist_from_ideal_bucket()) { + if (dist_from_ideal_bucket > bucket_entry::DIST_FROM_IDEAL_BUCKET_LIMIT) { + /** + * The number of probes is really high, rehash the map on the next + * insert. Difficult to do now as rehash may throw an exception. + */ + m_grow_on_next_insert = true; } - ibucket = next_bucket(ibucket); - dist_from_ideal_bucket++; + m_buckets[ibucket].swap_with_value_in_bucket(dist_from_ideal_bucket, my_hash, value); } - while (rehash_on_extreme_load(dist_from_ideal_bucket)) { - ibucket = bucket_for_hash(my_hash); - dist_from_ideal_bucket = 0; + ibucket = next_bucket(ibucket); + dist_from_ideal_bucket++; + } - while (dist_from_ideal_bucket <= m_buckets[ibucket].dist_from_ideal_bucket()) { - ibucket = next_bucket(ibucket); - dist_from_ideal_bucket++; - } - } + m_buckets[ibucket].set_value_of_empty_bucket(dist_from_ideal_bucket, my_hash, + std::move(value)); + } - if (m_buckets[ibucket].empty()) { - m_buckets[ibucket].set_value_of_empty_bucket(dist_from_ideal_bucket, - bucket_entry::truncate_hash(my_hash), - std::forward(value_type_args)...); - } - else { - insert_value(ibucket, dist_from_ideal_bucket, bucket_entry::truncate_hash(my_hash), - std::forward(value_type_args)...); + void rehash_impl(size_type my_count) + { + robin_hash new_table(my_count, static_cast(*this), static_cast(*this), + get_allocator(), m_min_load_factor, m_max_load_factor); + + const bool use_stored_hash = USE_STORED_HASH_ON_REHASH(new_table.bucket_count()); + for (auto &bucket : m_buckets_data) { + if (bucket.empty()) { + continue; } - m_nb_elements++; - /* - * The value will be inserted in ibucket in any case, either because it was - * empty or by stealing the bucket (robin hood). - */ - return std::make_pair(iterator(m_buckets + ibucket), true); - } + const std::size_t my_hash = use_stored_hash + ? bucket.truncated_hash() + : new_table.hash_key(KeySelect()(bucket.value())); - template - void insert_value(std::size_t ibucket, distance_type dist_from_ideal_bucket, - truncated_hash_type my_hash, Args &&...value_type_args) - { - value_type value(std::forward(value_type_args)...); - insert_value_impl(ibucket, dist_from_ideal_bucket, my_hash, value); + new_table.insert_value_on_rehash(new_table.bucket_for_hash(my_hash), 0, + bucket_entry::truncate_hash(my_hash), + std::move(bucket.value())); } - void insert_value(std::size_t ibucket, distance_type dist_from_ideal_bucket, - truncated_hash_type my_hash, value_type &&value) - { - insert_value_impl(ibucket, dist_from_ideal_bucket, my_hash, value); - } - - /* - * We don't use `value_type&& value` as last argument due to a bug in MSVC - * when `value_type` is a pointer, The compiler is not able to see the - * difference between `std::string*` and `std::string*&&` resulting in a - * compilation error. - * - * The `value` will be in a moved state at the end of the function. - */ - void insert_value_impl(std::size_t ibucket, distance_type dist_from_ideal_bucket, - truncated_hash_type my_hash, value_type &value) - { - tsl_rh_assert(dist_from_ideal_bucket > m_buckets[ibucket].dist_from_ideal_bucket()); - m_buckets[ibucket].swap_with_value_in_bucket(dist_from_ideal_bucket, my_hash, value); - ibucket = next_bucket(ibucket); - dist_from_ideal_bucket++; + new_table.m_nb_elements = m_nb_elements; + new_table.swap(*this); + } - while (!m_buckets[ibucket].empty()) { - if (dist_from_ideal_bucket > m_buckets[ibucket].dist_from_ideal_bucket()) { - if (dist_from_ideal_bucket > bucket_entry::DIST_FROM_IDEAL_BUCKET_LIMIT) { - /** - * The number of probes is really high, rehash the map on the next - * insert. Difficult to do now as rehash may throw an exception. - */ - m_grow_on_next_insert = true; - } + void clear_and_shrink() noexcept + { + GrowthPolicy::clear(); + m_buckets_data.clear(); + m_buckets = static_empty_bucket_ptr(); + m_bucket_count = 0; + m_nb_elements = 0; + m_load_threshold = 0; + m_grow_on_next_insert = false; + m_try_shrink_on_next_insert = false; + } + void insert_value_on_rehash(std::size_t ibucket, distance_type dist_from_ideal_bucket, + truncated_hash_type my_hash, value_type &&value) + { + while (true) { + if (dist_from_ideal_bucket > m_buckets[ibucket].dist_from_ideal_bucket()) { + if (m_buckets[ibucket].empty()) { + m_buckets[ibucket].set_value_of_empty_bucket(dist_from_ideal_bucket, my_hash, + std::move(value)); + return; + } + else { m_buckets[ibucket].swap_with_value_in_bucket(dist_from_ideal_bucket, my_hash, value); } - - ibucket = next_bucket(ibucket); - dist_from_ideal_bucket++; } - m_buckets[ibucket].set_value_of_empty_bucket(dist_from_ideal_bucket, my_hash, - std::move(value)); + dist_from_ideal_bucket++; + ibucket = next_bucket(ibucket); } + } - void rehash_impl(size_type my_count) - { - robin_hash new_table(my_count, static_cast(*this), static_cast(*this), - get_allocator(), m_min_load_factor, m_max_load_factor); + /** + * Grow the table if m_grow_on_next_insert is true or we reached the + * max_load_factor. Shrink the table if m_try_shrink_on_next_insert is true + * (an erase occurred) and we're below the min_load_factor. + * + * Return true if the table has been rehashed. + */ + bool rehash_on_extreme_load(distance_type curr_dist_from_ideal_bucket) + { + if (m_grow_on_next_insert || + curr_dist_from_ideal_bucket > bucket_entry::DIST_FROM_IDEAL_BUCKET_LIMIT || + size() >= m_load_threshold) { + rehash_impl(GrowthPolicy::next_bucket_count()); + m_grow_on_next_insert = false; - const bool use_stored_hash = USE_STORED_HASH_ON_REHASH(new_table.bucket_count()); - for (auto &bucket : m_buckets_data) { - if (bucket.empty()) { - continue; - } + return true; + } - const std::size_t my_hash = use_stored_hash - ? bucket.truncated_hash() - : new_table.hash_key(KeySelect()(bucket.value())); + if (m_try_shrink_on_next_insert) { + m_try_shrink_on_next_insert = false; + if (m_min_load_factor != 0.0f && load_factor() < m_min_load_factor) { + reserve(size() + 1); - new_table.insert_value_on_rehash(new_table.bucket_for_hash(my_hash), 0, - bucket_entry::truncate_hash(my_hash), - std::move(bucket.value())); + return true; } - - new_table.m_nb_elements = m_nb_elements; - new_table.swap(*this); } - void clear_and_shrink() noexcept - { - GrowthPolicy::clear(); - m_buckets_data.clear(); - m_buckets = static_empty_bucket_ptr(); - m_bucket_count = 0; - m_nb_elements = 0; - m_load_threshold = 0; - m_grow_on_next_insert = false; - m_try_shrink_on_next_insert = false; - } + return false; + } - void insert_value_on_rehash(std::size_t ibucket, distance_type dist_from_ideal_bucket, - truncated_hash_type my_hash, value_type &&value) - { - while (true) { - if (dist_from_ideal_bucket > m_buckets[ibucket].dist_from_ideal_bucket()) { - if (m_buckets[ibucket].empty()) { - m_buckets[ibucket].set_value_of_empty_bucket(dist_from_ideal_bucket, my_hash, - std::move(value)); - return; - } - else { - m_buckets[ibucket].swap_with_value_in_bucket(dist_from_ideal_bucket, my_hash, value); - } - } + template void serialize_impl(Serializer &serializer) const + { + const slz_size_type version = SERIALIZATION_PROTOCOL_VERSION; + serializer(version); - dist_from_ideal_bucket++; - ibucket = next_bucket(ibucket); - } - } + // Indicate if the truncated hash of each bucket is stored. Use a + // std::int16_t instead of a bool to avoid the need for the serializer to + // support an extra 'bool' type. + const auto hash_stored_for_bucket = static_cast(STORE_HASH); + serializer(hash_stored_for_bucket); - /** - * Grow the table if m_grow_on_next_insert is true or we reached the - * max_load_factor. Shrink the table if m_try_shrink_on_next_insert is true - * (an erase occurred) and we're below the min_load_factor. - * - * Return true if the table has been rehashed. - */ - bool rehash_on_extreme_load(distance_type curr_dist_from_ideal_bucket) - { - if (m_grow_on_next_insert || - curr_dist_from_ideal_bucket > bucket_entry::DIST_FROM_IDEAL_BUCKET_LIMIT || - size() >= m_load_threshold) { - rehash_impl(GrowthPolicy::next_bucket_count()); - m_grow_on_next_insert = false; + const slz_size_type nb_elements = m_nb_elements; + serializer(nb_elements); - return true; - } + const slz_size_type bucket_count = m_buckets_data.size(); + serializer(bucket_count); + + const float min_load_factor = m_min_load_factor; + serializer(min_load_factor); - if (m_try_shrink_on_next_insert) { - m_try_shrink_on_next_insert = false; - if (m_min_load_factor != 0.0f && load_factor() < m_min_load_factor) { - reserve(size() + 1); + const float max_load_factor = m_max_load_factor; + serializer(max_load_factor); - return true; + for (const bucket_entry &bucket : m_buckets_data) { + if (bucket.empty()) { + const std::int16_t empty_bucket = bucket_entry::EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET; + serializer(empty_bucket); + } + else { + const std::int16_t dist_from_ideal_bucket = bucket.dist_from_ideal_bucket(); + serializer(dist_from_ideal_bucket); + if (STORE_HASH) { + const std::uint32_t truncated_hash = bucket.truncated_hash(); + serializer(truncated_hash); } + serializer(bucket.value()); } - - return false; } + } - template void serialize_impl(Serializer &serializer) const - { - const slz_size_type version = SERIALIZATION_PROTOCOL_VERSION; - serializer(version); - - // Indicate if the truncated hash of each bucket is stored. Use a - // std::int16_t instead of a bool to avoid the need for the serializer to - // support an extra 'bool' type. - const std::int16_t hash_stored_for_bucket = static_cast(STORE_HASH); - serializer(hash_stored_for_bucket); + template + void deserialize_impl(Deserializer &deserializer, bool hash_compatible) + { + tsl_rh_assert(m_buckets_data.empty()); // Current hash table must be empty - const slz_size_type nb_elements = m_nb_elements; - serializer(nb_elements); + const slz_size_type version = deserialize_value(deserializer); + // For now we only have one version of the serialization protocol. + // If it doesn't match there is a problem with the file. + if (version != SERIALIZATION_PROTOCOL_VERSION) { + TSL_RH_THROW_OR_TERMINATE(std::runtime_error, "Can't deserialize the ordered_map/set. " + "The protocol version header is invalid."); + } - const slz_size_type bucket_count = m_buckets_data.size(); - serializer(bucket_count); + const bool hash_stored_for_bucket = + deserialize_value(deserializer) ? true : false; + if (hash_compatible && STORE_HASH != hash_stored_for_bucket) { + TSL_RH_THROW_OR_TERMINATE(std::runtime_error, + "Can't deserialize a map with a different StoreHash " + "than the one used during the serialization when " + "hash compatibility is used"); + } - const float min_load_factor = m_min_load_factor; - serializer(min_load_factor); + const slz_size_type nb_elements = deserialize_value(deserializer); + const slz_size_type bucket_count_ds = deserialize_value(deserializer); + const float min_load_factor = deserialize_value(deserializer); + const float max_load_factor = deserialize_value(deserializer); - const float max_load_factor = m_max_load_factor; - serializer(max_load_factor); + if (min_load_factor < MINIMUM_MIN_LOAD_FACTOR || min_load_factor > MAXIMUM_MIN_LOAD_FACTOR) { + TSL_RH_THROW_OR_TERMINATE(std::runtime_error, + "Invalid min_load_factor. Check that the serializer " + "and deserializer support floats correctly as they " + "can be converted implicitly to ints."); + } - for (const bucket_entry &bucket : m_buckets_data) { - if (bucket.empty()) { - const std::int16_t empty_bucket = bucket_entry::EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET; - serializer(empty_bucket); - } - else { - const std::int16_t dist_from_ideal_bucket = bucket.dist_from_ideal_bucket(); - serializer(dist_from_ideal_bucket); - if (STORE_HASH) { - const std::uint32_t truncated_hash = bucket.truncated_hash(); - serializer(truncated_hash); - } - serializer(bucket.value()); - } - } + if (max_load_factor < MINIMUM_MAX_LOAD_FACTOR || max_load_factor > MAXIMUM_MAX_LOAD_FACTOR) { + TSL_RH_THROW_OR_TERMINATE(std::runtime_error, + "Invalid max_load_factor. Check that the serializer " + "and deserializer support floats correctly as they " + "can be converted implicitly to ints."); } - template - void deserialize_impl(Deserializer &deserializer, bool hash_compatible) - { - tsl_rh_assert(m_buckets_data.empty()); // Current hash table must be empty - - const slz_size_type version = deserialize_value(deserializer); - // For now we only have one version of the serialization protocol. - // If it doesn't match there is a problem with the file. - if (version != SERIALIZATION_PROTOCOL_VERSION) { - TSL_RH_THROW_OR_TERMINATE(std::runtime_error, "Can't deserialize the ordered_map/set. " - "The protocol version header is invalid."); - } + this->min_load_factor(min_load_factor); + this->max_load_factor(max_load_factor); - const bool hash_stored_for_bucket = - deserialize_value(deserializer) ? true : false; - if (hash_compatible && STORE_HASH != hash_stored_for_bucket) { - TSL_RH_THROW_OR_TERMINATE(std::runtime_error, - "Can't deserialize a map with a different StoreHash " - "than the one used during the serialization when " - "hash compatibility is used"); - } + if (bucket_count_ds == 0) { + tsl_rh_assert(nb_elements == 0); + return; + } - const slz_size_type nb_elements = deserialize_value(deserializer); - const slz_size_type bucket_count_ds = deserialize_value(deserializer); - const float min_load_factor = deserialize_value(deserializer); - const float max_load_factor = deserialize_value(deserializer); - - if (min_load_factor < MINIMUM_MIN_LOAD_FACTOR || - min_load_factor > MAXIMUM_MIN_LOAD_FACTOR) { - TSL_RH_THROW_OR_TERMINATE(std::runtime_error, - "Invalid min_load_factor. Check that the serializer " - "and deserializer support floats correctly as they " - "can be converted implicitly to ints."); - } + if (!hash_compatible) { + reserve(numeric_cast(nb_elements, "Deserialized nb_elements is too big.")); + for (slz_size_type ibucket = 0; ibucket < bucket_count_ds; ibucket++) { + const distance_type dist_from_ideal_bucket = + deserialize_value(deserializer); + if (dist_from_ideal_bucket != bucket_entry::EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET) { + if (hash_stored_for_bucket) { + TSL_RH_UNUSED(deserialize_value(deserializer)); + } - if (max_load_factor < MINIMUM_MAX_LOAD_FACTOR || - max_load_factor > MAXIMUM_MAX_LOAD_FACTOR) { - TSL_RH_THROW_OR_TERMINATE(std::runtime_error, - "Invalid max_load_factor. Check that the serializer " - "and deserializer support floats correctly as they " - "can be converted implicitly to ints."); + insert(deserialize_value(deserializer)); + } } - this->min_load_factor(min_load_factor); - this->max_load_factor(max_load_factor); + tsl_rh_assert(nb_elements == size()); + } + else { + m_bucket_count = + numeric_cast(bucket_count_ds, "Deserialized bucket_count is too big."); - if (bucket_count_ds == 0) { - tsl_rh_assert(nb_elements == 0); - return; + GrowthPolicy::operator=(GrowthPolicy(m_bucket_count)); + // GrowthPolicy should not modify the bucket count we got from + // deserialization + if (m_bucket_count != bucket_count_ds) { + TSL_RH_THROW_OR_TERMINATE(std::runtime_error, "The GrowthPolicy is not the same even " + "though hash_compatible is true."); } - if (!hash_compatible) { - reserve(numeric_cast(nb_elements, "Deserialized nb_elements is too big.")); - for (slz_size_type ibucket = 0; ibucket < bucket_count_ds; ibucket++) { - const distance_type dist_from_ideal_bucket = - deserialize_value(deserializer); - if (dist_from_ideal_bucket != bucket_entry::EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET) { - if (hash_stored_for_bucket) { - TSL_RH_UNUSED(deserialize_value(deserializer)); - } - - insert(deserialize_value(deserializer)); + m_nb_elements = + numeric_cast(nb_elements, "Deserialized nb_elements is too big."); + m_buckets_data.resize(m_bucket_count); + m_buckets = m_buckets_data.data(); + + for (bucket_entry &bucket : m_buckets_data) { + const distance_type dist_from_ideal_bucket = + deserialize_value(deserializer); + if (dist_from_ideal_bucket != bucket_entry::EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET) { + truncated_hash_type truncated_hash = 0; + if (hash_stored_for_bucket) { + tsl_rh_assert(hash_stored_for_bucket); + truncated_hash = deserialize_value(deserializer); } - } - - tsl_rh_assert(nb_elements == size()); - } - else { - m_bucket_count = - numeric_cast(bucket_count_ds, "Deserialized bucket_count is too big."); - - GrowthPolicy::operator=(GrowthPolicy(m_bucket_count)); - // GrowthPolicy should not modify the bucket count we got from - // deserialization - if (m_bucket_count != bucket_count_ds) { - TSL_RH_THROW_OR_TERMINATE(std::runtime_error, "The GrowthPolicy is not the same even " - "though hash_compatible is true."); - } - m_nb_elements = - numeric_cast(nb_elements, "Deserialized nb_elements is too big."); - m_buckets_data.resize(m_bucket_count); - m_buckets = m_buckets_data.data(); - - for (bucket_entry &bucket : m_buckets_data) { - const distance_type dist_from_ideal_bucket = - deserialize_value(deserializer); - if (dist_from_ideal_bucket != bucket_entry::EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET) { - truncated_hash_type truncated_hash = 0; - if (hash_stored_for_bucket) { - tsl_rh_assert(hash_stored_for_bucket); - truncated_hash = deserialize_value(deserializer); - } - - bucket.set_value_of_empty_bucket(dist_from_ideal_bucket, truncated_hash, - deserialize_value(deserializer)); - } + bucket.set_value_of_empty_bucket(dist_from_ideal_bucket, truncated_hash, + deserialize_value(deserializer)); } + } - if (!m_buckets_data.empty()) { - m_buckets_data.back().set_as_last_bucket(); - } + if (!m_buckets_data.empty()) { + m_buckets_data.back().set_as_last_bucket(); } } + } - public: - static const size_type DEFAULT_INIT_BUCKETS_SIZE = 0; + public: + static const size_type DEFAULT_INIT_BUCKETS_SIZE = 0; - static constexpr float DEFAULT_MAX_LOAD_FACTOR = 0.5f; - static constexpr float MINIMUM_MAX_LOAD_FACTOR = 0.2f; - static constexpr float MAXIMUM_MAX_LOAD_FACTOR = 0.95f; + static constexpr float DEFAULT_MAX_LOAD_FACTOR = 0.5f; + static constexpr float MINIMUM_MAX_LOAD_FACTOR = 0.2f; + static constexpr float MAXIMUM_MAX_LOAD_FACTOR = 0.95f; - static constexpr float DEFAULT_MIN_LOAD_FACTOR = 0.0f; - static constexpr float MINIMUM_MIN_LOAD_FACTOR = 0.0f; - static constexpr float MAXIMUM_MIN_LOAD_FACTOR = 0.15f; + static constexpr float DEFAULT_MIN_LOAD_FACTOR = 0.0f; + static constexpr float MINIMUM_MIN_LOAD_FACTOR = 0.0f; + static constexpr float MAXIMUM_MIN_LOAD_FACTOR = 0.15f; - static_assert(MINIMUM_MAX_LOAD_FACTOR < MAXIMUM_MAX_LOAD_FACTOR, - "MINIMUM_MAX_LOAD_FACTOR should be < MAXIMUM_MAX_LOAD_FACTOR"); - static_assert(MINIMUM_MIN_LOAD_FACTOR < MAXIMUM_MIN_LOAD_FACTOR, - "MINIMUM_MIN_LOAD_FACTOR should be < MAXIMUM_MIN_LOAD_FACTOR"); - static_assert(MAXIMUM_MIN_LOAD_FACTOR < MINIMUM_MAX_LOAD_FACTOR, - "MAXIMUM_MIN_LOAD_FACTOR should be < MINIMUM_MAX_LOAD_FACTOR"); + static_assert(MINIMUM_MAX_LOAD_FACTOR < MAXIMUM_MAX_LOAD_FACTOR, + "MINIMUM_MAX_LOAD_FACTOR should be < MAXIMUM_MAX_LOAD_FACTOR"); + static_assert(MINIMUM_MIN_LOAD_FACTOR < MAXIMUM_MIN_LOAD_FACTOR, + "MINIMUM_MIN_LOAD_FACTOR should be < MAXIMUM_MIN_LOAD_FACTOR"); + static_assert(MAXIMUM_MIN_LOAD_FACTOR < MINIMUM_MAX_LOAD_FACTOR, + "MAXIMUM_MIN_LOAD_FACTOR should be < MINIMUM_MAX_LOAD_FACTOR"); - private: - /** - * Protocol version currenlty used for serialization. - */ - static const slz_size_type SERIALIZATION_PROTOCOL_VERSION = 1; - - /** - * Return an always valid pointer to an static empty bucket_entry with - * last_bucket() == true. - */ - bucket_entry *static_empty_bucket_ptr() noexcept - { - static bucket_entry empty_bucket(true); - tsl_rh_assert(empty_bucket.empty()); - return &empty_bucket; - } + private: + /** + * Protocol version currenlty used for serialization. + */ + static const slz_size_type SERIALIZATION_PROTOCOL_VERSION = 1; - private: - buckets_container_type m_buckets_data; + /** + * Return an always valid pointer to an static empty bucket_entry with + * last_bucket() == true. + */ + bucket_entry *static_empty_bucket_ptr() noexcept + { + static bucket_entry empty_bucket(true); + tsl_rh_assert(empty_bucket.empty()); + return &empty_bucket; + } - /** - * Points to m_buckets_data.data() if !m_buckets_data.empty() otherwise points - * to static_empty_bucket_ptr. This variable is useful to avoid the cost of - * checking if m_buckets_data is empty when trying to find an element. - * - * TODO Remove m_buckets_data and only use a pointer instead of a - * pointer+vector to save some space in the robin_hash object. Manage the - * Allocator manually. - */ - bucket_entry *m_buckets; + private: + buckets_container_type m_buckets_data; - /** - * Used a lot in find, avoid the call to m_buckets_data.size() which is a bit - * slower. - */ - size_type m_bucket_count; + /** + * Points to m_buckets_data.data() if !m_buckets_data.empty() otherwise points + * to static_empty_bucket_ptr. This variable is useful to avoid the cost of + * checking if m_buckets_data is empty when trying to find an element. + * + * TODO Remove m_buckets_data and only use a pointer instead of a + * pointer+vector to save some space in the robin_hash object. Manage the + * Allocator manually. + */ + bucket_entry *m_buckets; - size_type m_nb_elements; + /** + * Used a lot in find, avoid the call to m_buckets_data.size() which is a bit + * slower. + */ + size_type m_bucket_count; - size_type m_load_threshold; + size_type m_nb_elements{0}; - float m_min_load_factor; - float m_max_load_factor; + size_type m_load_threshold{0}; - bool m_grow_on_next_insert; + float m_min_load_factor; + float m_max_load_factor; - /** - * We can't shrink down the map on erase operations as the erase methods need - * to return the next iterator. Shrinking the map would invalidate all the - * iterators and we could not return the next iterator in a meaningful way, On - * erase, we thus just indicate on erase that we should try to shrink the hash - * table on the next insert if we go below the min_load_factor. - */ - bool m_try_shrink_on_next_insert; - }; + bool m_grow_on_next_insert{false}; - } // namespace detail_robin_hash + /** + * We can't shrink down the map on erase operations as the erase methods need + * to return the next iterator. Shrinking the map would invalidate all the + * iterators and we could not return the next iterator in a meaningful way, On + * erase, we thus just indicate on erase that we should try to shrink the hash + * table on the next insert if we go below the min_load_factor. + */ + bool m_try_shrink_on_next_insert{false}; + }; -} // namespace tsl +} // namespace tsl::detail_robin_hash #endif diff --git a/packages/seacas/libraries/ioss/src/text_mesh/Iotm_TextMesh.C b/packages/seacas/libraries/ioss/src/text_mesh/Iotm_TextMesh.C index 32a7cf3a38..7ace2af323 100644 --- a/packages/seacas/libraries/ioss/src/text_mesh/Iotm_TextMesh.C +++ b/packages/seacas/libraries/ioss/src/text_mesh/Iotm_TextMesh.C @@ -148,8 +148,8 @@ namespace Iotm { { int64_t count = 0; - for (auto iter = m_blockPartition.begin(); iter != m_blockPartition.end(); iter++) { - count += iter->second.elemIds.size(); + for (auto part : m_blockPartition) { + count += part.second.elemIds.size(); } return count; @@ -246,6 +246,9 @@ namespace Iotm { class NodeCommunicationMap { public: + NodeCommunicationMap() = delete; + NodeCommunicationMap(const NodeCommunicationMap &) = delete; + NodeCommunicationMap(int myProc, Ioss::Int64Vector &map, std::vector &processors) : m_myProcessor(myProc), m_nodeMap(map), m_processorMap(processors) { @@ -269,9 +272,6 @@ namespace Iotm { } private: - NodeCommunicationMap(); - NodeCommunicationMap(const NodeCommunicationMap &); - void add_comm_map_pair(int64_t id, int proc) { m_nodeMap[m_fillIndex] = id; diff --git a/packages/seacas/libraries/ioss/src/utest/Utst_IofxDatabaseIO.C b/packages/seacas/libraries/ioss/src/utest/Utst_IofxDatabaseIO.C index 00c6a4bc2b..fe543c8046 100644 --- a/packages/seacas/libraries/ioss/src/utest/Utst_IofxDatabaseIO.C +++ b/packages/seacas/libraries/ioss/src/utest/Utst_IofxDatabaseIO.C @@ -276,20 +276,20 @@ namespace { output_region.add(output_node_block); const auto &input_element_blocks = input_region.get_element_blocks(); - for (size_t blk = 0; blk < input_element_blocks.size(); ++blk) { - const Ioss::ElementTopology *topology = input_element_blocks[blk]->topology(); - int block_id = input_element_blocks[blk]->get_property("id").get_int(); + for (const auto &block : input_element_blocks) { + const auto *topology = block->topology(); + int block_id = block->get_property("id").get_int(); - std::string name = input_element_blocks[blk]->name(); + std::string name = block->name(); std::string exotype = topology->name(); - int64_t num_elements = input_element_blocks[blk]->entity_count(); + int64_t num_elements = block->entity_count(); auto *output_element_block = new Ioss::ElementBlock(db_out, name, exotype, num_elements); output_element_block->property_add(Ioss::Property("original_topology_type", exotype)); output_element_block->property_add(Ioss::Property("id", block_id)); output_region.add(output_element_block); - int num_attributes = input_element_blocks[blk]->get_property("attribute_count").get_int(); + int num_attributes = block->get_property("attribute_count").get_int(); for (int j = 0; j < num_attributes; ++j) { output_element_block->field_add(Ioss::Field("attribute", Ioss::Field::REAL, "scalar", Ioss::Field::ATTRIBUTE, num_elements, j + 1)); @@ -297,9 +297,9 @@ namespace { } const auto &nodesets_input = input_region.get_nodesets(); - for (size_t i = 0; i < nodesets_input.size(); ++i) { - std::string nodeset_name = nodesets_input[i]->name(); - int64_t number_nodes_in_nodeset = nodesets_input[i]->entity_count(); + for (const auto &nset : nodesets_input) { + std::string nodeset_name = nset->name(); + int64_t number_nodes_in_nodeset = nset->entity_count(); auto *const nodeset = new Ioss::NodeSet(db_out, nodeset_name, number_nodes_in_nodeset); output_region.add(nodeset); @@ -308,24 +308,24 @@ namespace { } const auto &sidesets_input = input_region.get_sidesets(); - for (size_t i = 0; i < sidesets_input.size(); ++i) { - std::string sideset_name = sidesets_input[i]->name(); + for (const auto &sset : sidesets_input) { + std::string sideset_name = sset->name(); auto *const sideset_output = new Ioss::SideSet(db_out, sideset_name); output_region.add(sideset_output); - const auto &side_blocks = sidesets_input[i]->get_side_blocks(); - for (size_t k = 0; k < side_blocks.size(); ++k) { - const std::string &topo_name = side_blocks[k]->topology()->name(); - int64_t side_count = side_blocks[k]->entity_count(); - const std::string &parent_topo_name = side_blocks[k]->parent_element_topology()->name(); - const std::string &side_block_name = side_blocks[k]->name(); + const auto &side_blocks = sset->get_side_blocks(); + for (const auto &sblock : side_blocks) { + const std::string &topo_name = sblock->topology()->name(); + int64_t side_count = sblock->entity_count(); + const std::string &parent_topo_name = sblock->parent_element_topology()->name(); + const std::string &side_block_name = sblock->name(); auto *side_block = new Ioss::SideBlock(db_out, side_block_name, topo_name, parent_topo_name, side_count); sideset_output->add(side_block); - int nodes_per_side = side_blocks[k]->topology()->number_nodes(); + int nodes_per_side = sblock->topology()->number_nodes(); std::string storage_type = "Real["; storage_type += std::to_string(nodes_per_side); storage_type += "]"; diff --git a/packages/seacas/libraries/suplib_cpp/FileInfo.C b/packages/seacas/libraries/suplib_cpp/FileInfo.C index 47c9929ad8..9afa9bc5a8 100644 --- a/packages/seacas/libraries/suplib_cpp/FileInfo.C +++ b/packages/seacas/libraries/suplib_cpp/FileInfo.C @@ -209,7 +209,7 @@ std::string FileInfo::extension() const return filename_.substr(ind + 1, filename_.size()); } - return std::string(); + return {}; } std::string FileInfo::pathname() const @@ -219,7 +219,7 @@ std::string FileInfo::pathname() const return filename_.substr(0, ind); } - return std::string(); + return {}; } std::string FileInfo::tailname() const diff --git a/packages/seacas/libraries/suplib_cpp/glob.h b/packages/seacas/libraries/suplib_cpp/glob.h index 69e3025f6d..6b76d37c78 100644 --- a/packages/seacas/libraries/suplib_cpp/glob.h +++ b/packages/seacas/libraries/suplib_cpp/glob.h @@ -19,9 +19,9 @@ namespace glob { class Error : public std::exception { public: - Error(const std::string &msg) : msg_{msg} {} + Error(std::string msg) : msg_{std::move(msg)} {} - const char *what() const throw() override { return msg_.c_str(); } + const char *what() const noexcept override { return msg_.c_str(); } private: std::string msg_; @@ -90,7 +90,7 @@ namespace glob { std::tuple Next(const String &, size_t pos) override { - return std::tuple(0, ++pos); + return {0, ++pos}; } }; @@ -103,7 +103,7 @@ namespace glob { std::tuple Next(const String &, size_t pos) override { - return std::tuple(0, ++pos); + return {0, ++pos}; } }; @@ -118,8 +118,8 @@ namespace glob { Automata(Automata &&automata) : states_{std::move(automata.states_)}, match_state_{automata.match_state_}, - fail_state_{exchange(automata.fail_state_, 0)}, start_state_{ - exchange(automata.start_state_, 0)} + fail_state_{exchange(automata.fail_state_, 0)}, + start_state_{exchange(automata.start_state_, 0)} { } @@ -201,15 +201,15 @@ namespace glob { // the string if (comp_end) { if ((state_pos == match_state_) && (str_pos == str.length())) { - return std::tuple(state_pos == match_state_, str_pos); + return {state_pos == match_state_, str_pos}; } - return std::tuple(false, str_pos); + return {false, str_pos}; } else { // if comp_end is false, compare only if the states reached the // match state - return std::tuple(state_pos == match_state_, str_pos); + return {state_pos == match_state_, str_pos}; } } @@ -403,8 +403,7 @@ namespace glob { StateGroup(Automata &states, Type type, std::vector>> &&automatas) - : State(StateType::GROUP, states), type_{type}, automatas_{std::move(automatas)}, - match_one_{false} + : State(StateType::GROUP, states), type_{type}, automatas_{std::move(automatas)} { } @@ -421,11 +420,11 @@ namespace glob { for (auto &automata : automatas_) { std::tie(r, str_pos) = automata->Exec(str_part, false); if (r) { - return std::tuple(r, pos + str_pos); + return {r, pos + str_pos}; } } - return std::tuple(false, pos + str_pos); + return {false, pos + str_pos}; } bool Check(const String &str, size_t pos) override @@ -471,7 +470,7 @@ namespace glob { return NextNeg(str, pos); } } - return std::tuple(0, 0); + return {0, 0}; } std::tuple NextNeg(const String &str, size_t pos) @@ -484,7 +483,7 @@ namespace glob { return std::tuple(GetAutomata().FailState(), new_pos); } - return std::tuple(GetNextStates()[1], pos); + return {GetNextStates()[1], pos}; } std::tuple NextBasic(const String &str, size_t pos) @@ -494,10 +493,10 @@ namespace glob { std::tie(r, new_pos) = BasicCheck(str, pos); if (r) { this->SetMatchedStr(this->MatchedStr() + str.substr(pos, new_pos - pos)); - return std::tuple(GetNextStates()[1], new_pos); + return {GetNextStates()[1], new_pos}; } - return std::tuple(GetAutomata().FailState(), new_pos); + return {GetAutomata().FailState(), new_pos}; } std::tuple NextAny(const String &str, size_t pos) @@ -507,10 +506,10 @@ namespace glob { std::tie(r, new_pos) = BasicCheck(str, pos); if (r) { this->SetMatchedStr(this->MatchedStr() + str.substr(pos, new_pos - pos)); - return std::tuple(GetNextStates()[1], new_pos); + return {GetNextStates()[1], new_pos}; } - return std::tuple(GetNextStates()[1], pos); + return {GetNextStates()[1], pos}; } std::tuple NextStar(const String &str, size_t pos) @@ -522,14 +521,14 @@ namespace glob { this->SetMatchedStr(this->MatchedStr() + str.substr(pos, new_pos - pos)); if (GetAutomata().GetState(GetNextStates()[1]).Type() == StateType::MATCH && new_pos == str.length()) { - return std::tuple(GetNextStates()[1], new_pos); + return {GetNextStates()[1], new_pos}; } else { - return std::tuple(GetNextStates()[0], new_pos); + return {GetNextStates()[0], new_pos}; } } - return std::tuple(GetNextStates()[1], pos); + return {GetNextStates()[1], pos}; } std::tuple NextPlus(const String &str, size_t pos) @@ -545,10 +544,10 @@ namespace glob { // state is the match state, goes to next state to avoid state mistake if (GetAutomata().GetState(GetNextStates()[1]).Type() == StateType::MATCH && new_pos == str.length()) { - return std::tuple(GetNextStates()[1], new_pos); + return {GetNextStates()[1], new_pos}; } else { - return std::tuple(GetNextStates()[0], new_pos); + return {GetNextStates()[0], new_pos}; } } @@ -556,21 +555,21 @@ namespace glob { // one time -> goes to next state bool res = GetAutomata().GetState(GetNextStates()[1]).Check(str, pos); if (res && match_one_) { - return std::tuple(GetNextStates()[1], pos); + return {GetNextStates()[1], pos}; } if (match_one_) { - return std::tuple(GetNextStates()[1], pos); + return {GetNextStates()[1], pos}; } else { - return std::tuple(GetAutomata().FailState(), new_pos); + return {GetAutomata().FailState(), new_pos}; } } private: Type type_{}; std::vector>> automatas_; - bool match_one_; + bool match_one_{false}; }; #define TOKEN(X, Y) X, @@ -632,7 +631,7 @@ namespace glob { public: static const char kEndOfInput = -1; - Lexer(const String &str) : str_(str), pos_{0}, c_{str[0]} {} + Lexer(const String &str) : str_(str), c_{str[0]} {} std::vector> Scanner() { @@ -790,7 +789,7 @@ namespace glob { } String str_; - size_t pos_; + size_t pos_{0}; charT c_; }; @@ -863,7 +862,7 @@ namespace glob { public: CharNode(charT c) : AstNode(AstNode::Type::CHAR), c_{c} {} - virtual void Accept(AstVisitor *visitor) { visitor->VisitCharNode(this); } + void Accept(AstVisitor *visitor) override { visitor->VisitCharNode(this); } char GetValue() const { return c_; } @@ -875,12 +874,12 @@ namespace glob { { public: RangeNode(AstNodePtr &&start, AstNodePtr &&end) - : AstNode(AstNode::Type::RANGE), start_{std::move(start)}, end_{ - std::move(end)} + : AstNode(AstNode::Type::RANGE), start_{std::move(start)}, + end_{std::move(end)} { } - virtual void Accept(AstVisitor *visitor) { visitor->VisitRangeNode(this); } + void Accept(AstVisitor *visitor) override { visitor->VisitRangeNode(this); } AstNode *GetStart() const { return start_.get(); } @@ -899,7 +898,7 @@ namespace glob { { } - virtual void Accept(AstVisitor *visitor) { visitor->VisitSetItemsNode(this); } + void Accept(AstVisitor *visitor) override { visitor->VisitSetItemsNode(this); } std::vector> &GetItems() { return items_; } @@ -915,7 +914,7 @@ namespace glob { { } - virtual void Accept(AstVisitor *visitor) { visitor->VisitPositiveSetNode(this); } + void Accept(AstVisitor *visitor) override { visitor->VisitPositiveSetNode(this); } AstNode *GetSet() { return set_.get(); } @@ -931,7 +930,7 @@ namespace glob { { } - virtual void Accept(AstVisitor *visitor) { visitor->VisitNegativeSetNode(this); } + void Accept(AstVisitor *visitor) override { visitor->VisitNegativeSetNode(this); } AstNode *GetSet() { return set_.get(); } @@ -944,7 +943,7 @@ namespace glob { public: StarNode() : AstNode(AstNode::Type::STAR) {} - virtual void Accept(AstVisitor *visitor) { visitor->VisitStarNode(this); } + void Accept(AstVisitor *visitor) override { visitor->VisitStarNode(this); } }; template class AnyNode : public AstNode @@ -952,7 +951,7 @@ namespace glob { public: AnyNode() : AstNode(AstNode::Type::ANY) {} - virtual void Accept(AstVisitor *visitor) { visitor->VisitAnyNode(this); } + void Accept(AstVisitor *visitor) override { visitor->VisitAnyNode(this); } }; template class GroupNode : public AstNode @@ -961,12 +960,12 @@ namespace glob { enum class GroupType { BASIC, ANY, STAR, PLUS, NEG, AT }; GroupNode(GroupType group_type, AstNodePtr &&glob) - : AstNode(AstNode::Type::GROUP), glob_{std::move(glob)}, group_type_{ - group_type} + : AstNode(AstNode::Type::GROUP), glob_{std::move(glob)}, + group_type_{group_type} { } - virtual void Accept(AstVisitor *visitor) { visitor->VisitGroupNode(this); } + void Accept(AstVisitor *visitor) override { visitor->VisitGroupNode(this); } AstNode *GetGlob() { return glob_.get(); } @@ -985,7 +984,7 @@ namespace glob { { } - virtual void Accept(AstVisitor *visitor) { visitor->VisitConcatNode(this); } + void Accept(AstVisitor *visitor) override { visitor->VisitConcatNode(this); } std::vector> &GetBasicGlobs() { return basic_glob_; } @@ -1001,7 +1000,7 @@ namespace glob { { } - virtual void Accept(AstVisitor *visitor) { visitor->VisitUnionNode(this); } + void Accept(AstVisitor *visitor) override { visitor->VisitUnionNode(this); } std::vector> &GetItems() { return items_; } @@ -1017,7 +1016,7 @@ namespace glob { { } - virtual void Accept(AstVisitor *visitor) { visitor->VisitGlobNode(this); } + void Accept(AstVisitor *visitor) override { visitor->VisitGlobNode(this); } AstNode *GetConcat() { return glob_.get(); } @@ -1258,8 +1257,8 @@ namespace glob { private: void ExecConcat(AstNode *node, Automata &automata) { - ConcatNode *concat_node = static_cast *>(node); - std::vector> &basic_globs = concat_node->GetBasicGlobs(); + auto *concat_node = static_cast *>(node); + auto &basic_globs = concat_node->GetBasicGlobs(); for (auto &basic_glob : basic_globs) { ExecBasicGlob(basic_glob.get(), automata); @@ -1287,8 +1286,8 @@ namespace glob { void ExecChar(AstNode *node, Automata &automata) { - CharNode *char_node = static_cast *>(node); - char c = char_node->GetValue(); + auto *char_node = static_cast *>(node); + char c = char_node->GetValue(); NewState>(automata, c); } @@ -1305,7 +1304,7 @@ namespace glob { void ExecPositiveSet(AstNode *node, Automata &automata) { - PositiveSetNode *pos_set_node = static_cast *>(node); + auto *pos_set_node = static_cast *>(node); auto items = ProcessSetItems(pos_set_node->GetSet()); NewState>(automata, std::move(items)); @@ -1313,7 +1312,7 @@ namespace glob { void ExecNegativeSet(AstNode *node, Automata &automata) { - NegativeSetNode *pos_set_node = static_cast *>(node); + auto *pos_set_node = static_cast *>(node); auto items = ProcessSetItems(pos_set_node->GetSet()); NewState>(automata, std::move(items), /*neg*/ true); @@ -1321,7 +1320,7 @@ namespace glob { std::vector>> ProcessSetItems(AstNode *node) { - SetItemsNode *set_node = static_cast *>(node); + auto *set_node = static_cast *>(node); std::vector>> vec; auto &items = set_node->GetItems(); for (auto &item : items) { @@ -1334,15 +1333,14 @@ namespace glob { std::unique_ptr> ProcessSetItem(AstNode *node) { if (node->GetType() == AstNode::Type::CHAR) { - CharNode *char_node = static_cast *>(node); - char c = char_node->GetValue(); + auto *char_node = static_cast *>(node); + char c = char_node->GetValue(); return std::unique_ptr>(new SetItemChar(c)); } else if (node->GetType() == AstNode::Type::RANGE) { - RangeNode *range_node = static_cast *>(node); - CharNode *start_node = static_cast *>(range_node->GetStart()); - - CharNode *end_node = static_cast *>(range_node->GetEnd()); + auto *range_node = static_cast *>(node); + auto *start_node = static_cast *>(range_node->GetStart()); + auto *end_node = static_cast *>(range_node->GetEnd()); char start_char = start_node->GetValue(); char end_char = end_node->GetValue(); @@ -1355,9 +1353,9 @@ namespace glob { void ExecGroup(AstNode *node, Automata &automata) { - GroupNode *group_node = static_cast *>(node); - AstNode *union_node = group_node->GetGlob(); - std::vector>> automatas = ExecUnion(union_node); + auto *group_node = static_cast *>(node); + auto *union_node = group_node->GetGlob(); + auto automatas = ExecUnion(union_node); typename StateGroup::Type state_group_type{}; switch (group_node->GetGroupType()) { @@ -1386,8 +1384,8 @@ namespace glob { std::vector>> ExecUnion(AstNode *node) { - UnionNode *union_node = static_cast *>(node); - auto &items = union_node->GetItems(); + auto *union_node = static_cast *>(node); + auto &items = union_node->GetItems(); std::vector>> vec_automatas; for (auto &item : items) { std::unique_ptr> automata_ptr(new Automata); diff --git a/packages/seacas/libraries/suplib_cpp/pdqsort.h b/packages/seacas/libraries/suplib_cpp/pdqsort.h index cb48087de1..22b4ce1226 100644 --- a/packages/seacas/libraries/suplib_cpp/pdqsort.h +++ b/packages/seacas/libraries/suplib_cpp/pdqsort.h @@ -1,7 +1,7 @@ /* pdqsort.h - Pattern-defeating quicksort. - Copyright (c) 2021, 2022 Orson Peters + Copyright (c) 2021, 2022, 2023 Orson Peters This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. @@ -177,9 +177,9 @@ namespace pdqsort_detail { template inline T *align_cacheline(T *p) { #if defined(UINTPTR_MAX) && __cplusplus >= 201103L - std::uintptr_t ip = reinterpret_cast(p); + auto ip = reinterpret_cast(p); #else - std::size_t ip = reinterpret_cast(p); + auto ip = reinterpret_cast(p); #endif int icacheline_size = int(cacheline_size); ip = (ip + icacheline_size - 1) & -icacheline_size; diff --git a/packages/seacas/libraries/suplib_cpp/scopeguard.h b/packages/seacas/libraries/suplib_cpp/scopeguard.h index 21604f05c8..b05152ba10 100644 --- a/packages/seacas/libraries/suplib_cpp/scopeguard.h +++ b/packages/seacas/libraries/suplib_cpp/scopeguard.h @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2022 National Technology & Engineering Solutions + * Copyright(C) 1999-2023 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * @@ -18,7 +18,7 @@ template class RefHolder public: explicit RefHolder(T &ref) : ref_(ref) {} - operator T &() const { return ref_; } + operator T &() const { return ref_; } RefHolder &operator=(const RefHolder &) = delete; }; @@ -26,6 +26,7 @@ template inline RefHolder ByRef(T &t) { return RefHolder(t); } class ScopeGuardImplBase { +public: ScopeGuardImplBase &operator=(const ScopeGuardImplBase &) = delete; protected: diff --git a/packages/seacas/libraries/suplib_cpp/smart_assert.C b/packages/seacas/libraries/suplib_cpp/smart_assert.C index be4be93513..eff0fba972 100644 --- a/packages/seacas/libraries/suplib_cpp/smart_assert.C +++ b/packages/seacas/libraries/suplib_cpp/smart_assert.C @@ -87,8 +87,9 @@ namespace smart_assert { typedef assert_context::vals_array ac_vals_array; const ac_vals_array &aVals = context.get_vals_array(); if (!aVals.empty()) { - bool bFirstTime = true; - ac_vals_array::const_iterator first = aVals.begin(), last = aVals.end(); + bool bFirstTime = true; + auto first = aVals.begin(); + auto last = aVals.end(); while (first != last) { if (bFirstTime) { out << "Values: "; diff --git a/packages/seacas/libraries/suplib_cpp/smart_assert.h b/packages/seacas/libraries/suplib_cpp/smart_assert.h index f0558454c1..7f67b8407f 100644 --- a/packages/seacas/libraries/suplib_cpp/smart_assert.h +++ b/packages/seacas/libraries/suplib_cpp/smart_assert.h @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2020, 2022 National Technology & Engineering Solutions +// Copyright(C) 1999-2020, 2022, 2023 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -56,7 +56,7 @@ class assert_context using string = std::string; public: - assert_context() {} + assert_context() = default; // where the assertion failed: file & line void set_file_line(const char *file, int line) @@ -71,13 +71,13 @@ class assert_context void set_expr(const string &str) { expr_ = str; } const string &get_expr() const { return expr_; } - typedef std::pair val_and_str; - using vals_array = std::vector; + using val_and_str = std::pair; + using vals_array = std::vector; // return values array as a vector of pairs: // [Value, corresponding string] const vals_array &get_vals_array() const { return vals_; } // adds one value and its corresponding string - void add_val(const string &val, const string &str) { vals_.push_back(val_and_str(val, str)); } + void add_val(const string &val, const string &str) { vals_.emplace_back(val, str); } // get/set level of assertion void set_level(int nLevel) { level_ = nLevel; } @@ -160,8 +160,7 @@ struct Assert Assert &SMART_ASSERT_A; Assert &SMART_ASSERT_B; - explicit Assert(const char *expr) - : SMART_ASSERT_A(*this), SMART_ASSERT_B(*this), needs_handling_(true) + explicit Assert(const char *expr) : SMART_ASSERT_A(*this), SMART_ASSERT_B(*this) { context_.set_expr(expr); @@ -172,8 +171,7 @@ struct Assert } Assert(const Assert &other) - : SMART_ASSERT_A(*this), SMART_ASSERT_B(*this), context_(other.context_), - needs_handling_(true) + : SMART_ASSERT_A(*this), SMART_ASSERT_B(*this), context_(other.context_) { other.needs_handling_ = false; } @@ -275,8 +273,8 @@ struct Assert } // the handler - typedef std::map handlers_collection; - static handlers_collection &handlers() + using handlers_collection = std::map; + static handlers_collection &handlers() { static handlers_collection inst; return inst; @@ -284,7 +282,7 @@ struct Assert static assert_func get_handler(int nLevel) { - handlers_collection::const_iterator found = handlers().find(nLevel); + auto found = handlers().find(nLevel); if (found != handlers().end()) { return (*found).second; } diff --git a/packages/seacas/libraries/suplib_cpp/time_stamp.C b/packages/seacas/libraries/suplib_cpp/time_stamp.C index 0e285cbeb1..f2ee4dc8b2 100644 --- a/packages/seacas/libraries/suplib_cpp/time_stamp.C +++ b/packages/seacas/libraries/suplib_cpp/time_stamp.C @@ -10,7 +10,7 @@ std::string time_stamp(const std::string &format) { if (format.empty()) { - return std::string(""); + return {""}; } std::time_t t = std::time(nullptr); diff --git a/packages/zoltan/siMPI/pyMPI/siMPI/mpi.h b/packages/zoltan/siMPI/pyMPI/siMPI/mpi.h index 8012dba2c0..06b5313366 100644 --- a/packages/zoltan/siMPI/pyMPI/siMPI/mpi.h +++ b/packages/zoltan/siMPI/pyMPI/siMPI/mpi.h @@ -12,13 +12,14 @@ /* FILE *********** mpi.h ********************/ /******************************************************************/ /* Author : Lisa Alano June 18 2002 */ -/* Copyright (c) 2002 University of California Regents */ +/* Copyright (c) 2002, 2023 University of California Regents */ /******************************************************************/ #ifndef _MPI_H #define _MPI_H #ifdef __cplusplus + // NOLINTBEGIN extern "C" { #endif @@ -294,6 +295,7 @@ SKIP FOR NOW FORTRAN: EXTERNAL MPI_DUP_FN #ifdef __cplusplus + // NOLINTEND } #endif diff --git a/packages/zoltan/siMPI/pyMPI/siMPI/mpi_implementation.h b/packages/zoltan/siMPI/pyMPI/siMPI/mpi_implementation.h index 962bec0a06..157093cbd7 100644 --- a/packages/zoltan/siMPI/pyMPI/siMPI/mpi_implementation.h +++ b/packages/zoltan/siMPI/pyMPI/siMPI/mpi_implementation.h @@ -9,13 +9,14 @@ /* FILE *********** mpi_implementation.h ********************/ /******************************************************************/ /* Author : Lisa Alano June 18 2002 */ -/* Copyright (c) 2002 University of California Regents */ +/* Copyright (c) 2002, 2023 University of California Regents */ /******************************************************************/ #ifndef _MPI_IMPL_H #define _MPI_IMPL_H #ifdef __cplusplus + // NOLINTBEGIN extern "C" { #endif @@ -257,6 +258,7 @@ int _MPI_Find_free (void); #ifdef __cplusplus } + // NOLINTEND #endif #endif diff --git a/packages/zoltan/src/include/zoltan.h b/packages/zoltan/src/include/zoltan.h index 3a077248d8..6bb2712a0c 100644 --- a/packages/zoltan/src/include/zoltan.h +++ b/packages/zoltan/src/include/zoltan.h @@ -4,7 +4,7 @@ * *********************************************************************** * * Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring - * Copyright 2012 Sandia Corporation + * Copyright 2012, 2023 Sandia Corporation * * Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, * the U.S. Government retains certain rights in this software. @@ -63,6 +63,7 @@ typedef void ZOLTAN_VOID_FN(void); #ifdef __cplusplus /* if C++, define the rest of this header file as extern C */ + // NOLINTBEGIN extern "C" { #endif @@ -3431,6 +3432,7 @@ extern int Zoltan_Deserialize( #ifdef __cplusplus } /* closing bracket for extern "C" */ + // NOLINTEND #endif #endif /* !__ZOLTAN_H */ diff --git a/packages/zoltan/src/include/zoltan_cpp.h b/packages/zoltan/src/include/zoltan_cpp.h index 72b049f615..74a65e9f63 100644 --- a/packages/zoltan/src/include/zoltan_cpp.h +++ b/packages/zoltan/src/include/zoltan_cpp.h @@ -4,7 +4,7 @@ * *********************************************************************** * * Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring - * Copyright 2012 Sandia Corporation + * Copyright 2012, 2023 Sandia Corporation * * Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, * the U.S. Government retains certain rights in this software. @@ -275,7 +275,7 @@ class Zoltan { int Set_Fn ( const ZOLTAN_FN_TYPE &fn_type, void (*fn_ptr)(), - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Fn( ZZ_Ptr, fn_type, fn_ptr, data ); } @@ -284,257 +284,257 @@ class Zoltan { ///-------------------------- int Set_Part_Multi_Fn ( ZOLTAN_PART_MULTI_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Part_Multi_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Part_Fn ( ZOLTAN_PART_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Part_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Num_Edges_Multi_Fn ( ZOLTAN_NUM_EDGES_MULTI_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Num_Edges_Multi_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Num_Edges_Fn ( ZOLTAN_NUM_EDGES_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Num_Edges_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Edge_List_Multi_Fn ( ZOLTAN_EDGE_LIST_MULTI_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Edge_List_Multi_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Edge_List_Fn ( ZOLTAN_EDGE_LIST_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Edge_List_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Num_Geom_Fn ( ZOLTAN_NUM_GEOM_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Num_Geom_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Geom_Multi_Fn ( ZOLTAN_GEOM_MULTI_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Geom_Multi_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Geom_Fn ( ZOLTAN_GEOM_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Geom_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Num_Obj_Fn ( ZOLTAN_NUM_OBJ_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Num_Obj_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Obj_List_Fn ( ZOLTAN_OBJ_LIST_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Obj_List_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_First_Obj_Fn ( ZOLTAN_FIRST_OBJ_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_First_Obj_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Next_Obj_Fn ( ZOLTAN_NEXT_OBJ_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Next_Obj_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Num_Coarse_Obj_Fn ( ZOLTAN_NUM_COARSE_OBJ_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Num_Coarse_Obj_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Coarse_Obj_List_Fn ( ZOLTAN_COARSE_OBJ_LIST_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Coarse_Obj_List_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_First_Coarse_Obj_Fn( ZOLTAN_FIRST_COARSE_OBJ_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_First_Coarse_Obj_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Next_Coarse_Obj_Fn ( ZOLTAN_NEXT_COARSE_OBJ_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Next_Coarse_Obj_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Num_Child_Fn ( ZOLTAN_NUM_CHILD_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Num_Child_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Child_List_Fn ( ZOLTAN_CHILD_LIST_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Child_List_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Child_Weight_Fn ( ZOLTAN_CHILD_WEIGHT_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Child_Weight_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_HG_Size_CS_Fn ( ZOLTAN_HG_SIZE_CS_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_HG_Size_CS_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_HG_CS_Fn ( ZOLTAN_HG_CS_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_HG_CS_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_HG_Size_Edge_Wts_Fn ( ZOLTAN_HG_SIZE_EDGE_WTS_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_HG_Size_Edge_Wts_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_HG_Edge_Wts_Fn ( ZOLTAN_HG_EDGE_WTS_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_HG_Edge_Wts_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Hier_Num_Levels_Fn( ZOLTAN_HIER_NUM_LEVELS_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Hier_Num_Levels_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Hier_Part_Fn( ZOLTAN_HIER_PART_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Hier_Part_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Hier_Method_Fn( ZOLTAN_HIER_METHOD_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Hier_Method_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Num_Fixed_Obj_Fn ( ZOLTAN_NUM_FIXED_OBJ_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Num_Fixed_Obj_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Fixed_Obj_List_Fn ( ZOLTAN_FIXED_OBJ_LIST_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Fixed_Obj_List_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Pre_Migrate_PP_Fn ( ZOLTAN_PRE_MIGRATE_PP_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Pre_Migrate_PP_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Mid_Migrate_PP_Fn ( ZOLTAN_MID_MIGRATE_PP_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Mid_Migrate_PP_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Post_Migrate_PP_Fn ( ZOLTAN_POST_MIGRATE_PP_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Post_Migrate_PP_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Obj_Size_Multi_Fn ( ZOLTAN_OBJ_SIZE_MULTI_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Obj_Size_Multi_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Obj_Size_Fn ( ZOLTAN_OBJ_SIZE_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Obj_Size_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Pack_Obj_Multi_Fn ( ZOLTAN_PACK_OBJ_MULTI_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Pack_Obj_Multi_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Pack_Obj_Fn ( ZOLTAN_PACK_OBJ_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Pack_Obj_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Unpack_Obj_Multi_Fn( ZOLTAN_UNPACK_OBJ_MULTI_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Unpack_Obj_Multi_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Unpack_Obj_Fn ( ZOLTAN_UNPACK_OBJ_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Unpack_Obj_Fn( ZZ_Ptr, fn_ptr, data ); } @@ -542,21 +542,21 @@ class Zoltan { /// Backward compatibility with v3.0 ///-------------------------- int Set_Partition_Multi_Fn ( ZOLTAN_PART_MULTI_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Part_Multi_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Partition_Fn ( ZOLTAN_PART_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Part_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Hier_Partition_Fn( ZOLTAN_HIER_PART_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Hier_Part_Fn( ZZ_Ptr, fn_ptr, data ); }