Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -1697,19 +1697,33 @@ cc_test(
deps = [
":enum_array",
":enum_map",
":enum_map_raw_view",
":enum_set",
":enum_set_raw_view",
":enum_utils",
":fixed_bitset",
":fixed_bitset_raw_view",
":fixed_circular_deque",
":fixed_circular_queue",
":fixed_deque",
":fixed_deque_raw_view",
":fixed_doubly_linked_list_raw_view",
":fixed_map",
":fixed_map_raw_view",
":fixed_red_black_tree_view",
":fixed_set",
":fixed_stack",
":fixed_string",
":fixed_unordered_map",
":fixed_unordered_map_raw_view",
":fixed_unordered_set",
":fixed_unordered_set_raw_view",
":fixed_vector",
":map_entry_raw_view",
":pair_view",
":recursive_reflection",
":reflection",
":struct_view",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ class FixedDoublyLinkedListRawView
std::size_t max_elem_count)
: list_ptr_{static_cast<const std::byte*>(list_ptr)}
// the PoolStorage stores unions of `T`, `std::size_t`, so they are always at least that big
, elem_size_bytes_{std::max(elem_size_bytes, sizeof(std::size_t))}
, elem_align_bytes_{std::max(elem_align_bytes, alignof(std::size_t))}
, elem_size_bytes_{(std::max)(elem_size_bytes, sizeof(std::size_t))}
, elem_align_bytes_{(std::max)(elem_align_bytes, alignof(std::size_t))}
, max_elem_count_{max_elem_count}
{
}
Expand Down
2 changes: 1 addition & 1 deletion include/fixed_containers/fixed_map_raw_view.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ class FixedMapRawView
{
// Needed until FixedRedBlackTreeRawView supports types with alignment >= 8.
// Currently, it tacititly presumes alignment will be <= 8 for the keys and values.
assert_or_abort(std::max(value_align_bytes, key_align_bytes) <= 8);
assert_or_abort((std::max)(value_align_bytes, key_align_bytes) <= 8);
}

[[nodiscard]] Iterator begin() const
Expand Down
2 changes: 1 addition & 1 deletion include/fixed_containers/fixed_red_black_tree_view.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ class FixedRedBlackTreeRawView
{
case StorageType::FIXED_INDEX_POOL:
// IndexOrValueStorage is a union containing a size_t (index) or the node itself.
return std::max(sizeof(std::size_t), node_size_bytes);
return (std::max)(sizeof(std::size_t), node_size_bytes);

case StorageType::FIXED_INDEX_CONTIGUOUS:
return node_size_bytes;
Expand Down
4 changes: 2 additions & 2 deletions include/fixed_containers/fixed_string.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ class FixedString
Checking::out_of_range(index, length(), loc);
}

const size_type actual_count = std::min(count, length() - index);
const size_type actual_count = (std::min)(count, length() - index);
return erase(std::next(cbegin(), static_cast<difference_type>(index)),
std::next(cbegin(), static_cast<difference_type>(index + actual_count)),
loc);
Expand Down Expand Up @@ -772,7 +772,7 @@ template <std::size_t MAXIMUM_LENGTH, typename CheckingType>
constexpr FixedString<MAXIMUM_LENGTH, CheckingType>& append_truncating(
FixedString<MAXIMUM_LENGTH, CheckingType>& str, std::string_view view)
{
const std::size_t safe_chars = std::min(view.size(), MAXIMUM_LENGTH - str.length());
const std::size_t safe_chars = (std::min)(view.size(), MAXIMUM_LENGTH - str.length());
str.append(view.substr(0, safe_chars));
return str;
}
Expand Down
4 changes: 2 additions & 2 deletions include/fixed_containers/fixed_unordered_map_raw_view.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class FixedUnorderedMapRawView
std::size_t value_size,
std::size_t value_alignment)
{
const std::size_t struct_alignment = std::max(key_alignment, value_alignment);
const std::size_t struct_alignment = (std::max)(key_alignment, value_alignment);

auto value_offs = static_cast<std::size_t>(
MapEntryRawView::get_value_offs(key_size, key_alignment, value_size, value_alignment));
Expand Down Expand Up @@ -98,7 +98,7 @@ class FixedUnorderedMapRawView
std::size_t value_count)
: list_view_{get_linked_list_ptr(map_ptr),
compute_pair_size(key_size, key_alignment, value_size, value_alignment),
std::max(key_alignment, value_alignment),
(std::max)(key_alignment, value_alignment),
value_count}
, key_size_{key_size}
, key_alignment_{key_alignment}
Expand Down
81 changes: 72 additions & 9 deletions test/macro_countermeasures_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,98 @@
// gtest undefines min/max, include it first
#include <gtest/gtest.h>

// Define mocks of problematic macros
// Can't define min, conflict with the standard <algorithm> header. Use temporarily but don't merge
/*
/usr/bin/../lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/bits/ranges_algo.h:3348:35:
error: expected unqualified-id if (const auto __len = std::min(__d1, __d2))
*/
// #define min(a, b) (((a) < (b)) ? (a) : (b))
// Pre-include every stdlib (and third-party) header fixed_containers transitively uses.
// Once they're in the include-guard cache, the `#define min/max` below cannot
// re-trigger their parse, so stdlib internals that name `min`/`max` as identifiers
// (e.g. <algorithm>'s forward declarations, <random>'s _Gen::max()) are unaffected.
// Only fixed_containers' code is exercised against the poisoned macros.

// NOLINTBEGIN(misc-include-cleaner): intentional pre-include, not direct identifier use.
#include <algorithm>
#include <any>
#include <array>
#include <bit>
#include <bitset>
#include <cassert>
#include <chrono>
#include <climits>
#include <compare>
#include <concepts>
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <initializer_list>
#include <istream>
#include <iterator>
#include <limits>
#include <memory>
#include <numeric>
#include <optional>
#include <random>
#include <ranges>
#include <source_location>
#include <string>
#include <string_view>
#include <tuple>
#include <type_traits>
#include <utility>
#include <variant>
#include <version>

#include <magic_enum/magic_enum.hpp>
// NOLINTEND(misc-include-cleaner)

// Define mocks of problematic macros (skip if the environment, e.g. <windows.h>,
// already supplied them — what matters for this test is that they are macros).
#if !defined(min)
#define min(a, b) (((a) < (b)) ? (a) : (b))
#endif
#if !defined(max)
#define max(a, b) (((a) > (b)) ? (a) : (b))
#endif
#define CONST const
#define CONSTANT const
#define MUTABLE mutable
#define BLACK 0 // NOLINT(modernize-macro-to-enum)
#define RED 1 // NOLINT(modernize-macro-to-enum)

// NOLINTBEGIN(misc-include-cleaner): *_view headers included for macro-pollution coverage,
// not for direct identifier use in this translation unit.
#include "fixed_containers/enum_array.hpp"
#include "fixed_containers/enum_map.hpp"
#include "fixed_containers/enum_map_raw_view.hpp"
#include "fixed_containers/enum_set.hpp"
#include "fixed_containers/enum_set_raw_view.hpp"
#include "fixed_containers/enum_utils.hpp"
#include "fixed_containers/fixed_bitset.hpp"
#include "fixed_containers/fixed_bitset_raw_view.hpp"
#include "fixed_containers/fixed_circular_deque.hpp"
#include "fixed_containers/fixed_circular_queue.hpp"
#include "fixed_containers/fixed_deque.hpp"
#include "fixed_containers/fixed_deque_raw_view.hpp"
#include "fixed_containers/fixed_doubly_linked_list_raw_view.hpp"
#include "fixed_containers/fixed_map.hpp"
#include "fixed_containers/fixed_map_raw_view.hpp"
#include "fixed_containers/fixed_red_black_tree_view.hpp"
#include "fixed_containers/fixed_set.hpp"
#include "fixed_containers/fixed_stack.hpp"
#include "fixed_containers/fixed_string.hpp"
#include "fixed_containers/fixed_unordered_map.hpp"
#include "fixed_containers/fixed_unordered_map_raw_view.hpp"
#include "fixed_containers/fixed_unordered_set.hpp"
#include "fixed_containers/fixed_unordered_set_raw_view.hpp"
#include "fixed_containers/fixed_vector.hpp"
#include "fixed_containers/map_entry_raw_view.hpp"
#include "fixed_containers/pair_view.hpp"

#if defined(__clang__) && __clang_major__ >= 15
#include "fixed_containers/recursive_reflection.hpp"
#include "fixed_containers/reflection.hpp"
#include "fixed_containers/struct_view.hpp"
#endif
// NOLINTEND(misc-include-cleaner)

namespace fixed_containers
{
Expand All @@ -54,8 +117,8 @@ struct ClassWithMutableMember
} // namespace
TEST(MacroCountermeasures, DummyUsagesOfTheMacros)
{
// CONST int min_result = min(3, 5);
// EXPECT_EQ(3, min_result);
CONST int min_result = min(3, 5);
EXPECT_EQ(3, min_result);

CONST int max_result1 = max(3, 5);
EXPECT_EQ(5, max_result1);
Expand Down
Loading