diff --git a/Makefile b/Makefile
index a2884812..08c40d2f 100644
--- a/Makefile
+++ b/Makefile
@@ -102,7 +102,8 @@ doctest:
 # -Wno-switch-enum -Wno-covered-switch-default: pedantic/contradicting warnings about switches
 # -Wno-weak-vtables: exception class is defined inline, but has virtual method
 pedantic_clang:
-	$(MAKE) json_unit CXX=c++ CXXFLAGS=" \
+	rm -fr build_pedantic
+	CXXFLAGS=" \
 		-std=c++11 -Wno-c++98-compat -Wno-c++98-compat-pedantic \
 		-Werror \
 		-Weverything \
@@ -115,11 +116,13 @@ pedantic_clang:
 		-Wno-padded \
 		-Wno-range-loop-analysis \
 		-Wno-switch-enum -Wno-covered-switch-default \
-		-Wno-weak-vtables"
+		-Wno-weak-vtables" cmake -S . -B build_pedantic -GNinja -DCMAKE_BUILD_TYPE=Debug -DJSON_MultipleHeaders=ON
+	cmake --build build_pedantic
 
 # calling GCC with most warnings
 pedantic_gcc:
-	$(MAKE) json_unit CXX=/usr/local/bin/g++-9 CXXFLAGS=" \
+	rm -fr build_pedantic
+	CXXFLAGS=" \
 		-std=c++11 \
 		-Waddress \
 		-Waddress-of-packed-member \
@@ -233,7 +236,7 @@ pedantic_gcc:
 		-Wno-system-headers \
 		-Wno-templates \
 		-Wno-undef \
-		-Wnoexcept \
+		-Wno-noexcept \
 		-Wnoexcept-type \
 		-Wnon-template-friend \
 		-Wnon-virtual-dtor \
@@ -340,7 +343,8 @@ pedantic_gcc:
 		-Wvolatile-register-var \
 		-Wwrite-strings \
 		-Wzero-as-null-pointer-constant \
-		"
+		" cmake -S . -B build_pedantic -GNinja -DCMAKE_BUILD_TYPE=Debug -DJSON_MultipleHeaders=ON
+	cmake --build build_pedantic
 
 ##########################################################################
 # benchmarks
diff --git a/include/nlohmann/detail/boolean_operators.hpp b/include/nlohmann/detail/boolean_operators.hpp
new file mode 100644
index 00000000..06335866
--- /dev/null
+++ b/include/nlohmann/detail/boolean_operators.hpp
@@ -0,0 +1,8 @@
+#pragma once
+
+// Header <ciso646> is removed in C++20.
+// See <https://github.com/nlohmann/json/issues/2089> for more information.
+
+#if __cplusplus <= 201703L
+    #include <ciso646> // and, not, or
+#endif
diff --git a/include/nlohmann/detail/conversions/from_json.hpp b/include/nlohmann/detail/conversions/from_json.hpp
index 53eb40e3..b6105b05 100644
--- a/include/nlohmann/detail/conversions/from_json.hpp
+++ b/include/nlohmann/detail/conversions/from_json.hpp
@@ -2,7 +2,6 @@
 
 #include <algorithm> // transform
 #include <array> // array
-#include <ciso646> // and, not
 #include <forward_list> // forward_list
 #include <iterator> // inserter, front_inserter, end
 #include <map> // map
@@ -13,6 +12,7 @@
 #include <utility> // pair, declval
 #include <valarray> // valarray
 
+#include <nlohmann/detail/boolean_operators.hpp>
 #include <nlohmann/detail/exceptions.hpp>
 #include <nlohmann/detail/macro_scope.hpp>
 #include <nlohmann/detail/meta/cpp_future.hpp>
diff --git a/include/nlohmann/detail/conversions/to_chars.hpp b/include/nlohmann/detail/conversions/to_chars.hpp
index aed587cc..5851fd0a 100644
--- a/include/nlohmann/detail/conversions/to_chars.hpp
+++ b/include/nlohmann/detail/conversions/to_chars.hpp
@@ -2,12 +2,13 @@
 
 #include <array> // array
 #include <cassert> // assert
-#include <ciso646> // or, and, not
 #include <cmath>   // signbit, isfinite
 #include <cstdint> // intN_t, uintN_t
 #include <cstring> // memcpy, memmove
 #include <limits> // numeric_limits
 #include <type_traits> // conditional
+
+#include <nlohmann/detail/boolean_operators.hpp>
 #include <nlohmann/detail/macro_scope.hpp>
 
 namespace nlohmann
diff --git a/include/nlohmann/detail/conversions/to_json.hpp b/include/nlohmann/detail/conversions/to_json.hpp
index 0a087c22..16b40bf9 100644
--- a/include/nlohmann/detail/conversions/to_json.hpp
+++ b/include/nlohmann/detail/conversions/to_json.hpp
@@ -1,7 +1,6 @@
 #pragma once
 
 #include <algorithm> // copy
-#include <ciso646> // or, and, not
 #include <iterator> // begin, end
 #include <string> // string
 #include <tuple> // tuple, get
@@ -10,6 +9,7 @@
 #include <valarray> // valarray
 #include <vector> // vector
 
+#include <nlohmann/detail/boolean_operators.hpp>
 #include <nlohmann/detail/iterators/iteration_proxy.hpp>
 #include <nlohmann/detail/meta/cpp_future.hpp>
 #include <nlohmann/detail/meta/type_traits.hpp>
diff --git a/include/nlohmann/detail/input/binary_reader.hpp b/include/nlohmann/detail/input/binary_reader.hpp
index 8955ee7a..e03f95fb 100644
--- a/include/nlohmann/detail/input/binary_reader.hpp
+++ b/include/nlohmann/detail/input/binary_reader.hpp
@@ -32,7 +32,7 @@ namespace detail
 
 @note from https://stackoverflow.com/a/1001328/266378
 */
-static bool little_endianess(int num = 1) noexcept
+static inline bool little_endianess(int num = 1) noexcept
 {
     return *reinterpret_cast<char*>(&num) == 1;
 }
diff --git a/include/nlohmann/detail/iterators/iter_impl.hpp b/include/nlohmann/detail/iterators/iter_impl.hpp
index 3a362971..0b79202a 100644
--- a/include/nlohmann/detail/iterators/iter_impl.hpp
+++ b/include/nlohmann/detail/iterators/iter_impl.hpp
@@ -1,9 +1,9 @@
 #pragma once
 
-#include <ciso646> // not
 #include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
 #include <type_traits> // conditional, is_const, remove_const
 
+#include <nlohmann/detail/boolean_operators.hpp>
 #include <nlohmann/detail/exceptions.hpp>
 #include <nlohmann/detail/iterators/internal_iterator.hpp>
 #include <nlohmann/detail/iterators/primitive_iterator.hpp>
diff --git a/include/nlohmann/detail/meta/cpp_future.hpp b/include/nlohmann/detail/meta/cpp_future.hpp
index 948cd4fb..11f88acc 100644
--- a/include/nlohmann/detail/meta/cpp_future.hpp
+++ b/include/nlohmann/detail/meta/cpp_future.hpp
@@ -1,9 +1,10 @@
 #pragma once
 
-#include <ciso646> // not
 #include <cstddef> // size_t
 #include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
 
+#include <nlohmann/detail/boolean_operators.hpp>
+
 namespace nlohmann
 {
 namespace detail
diff --git a/include/nlohmann/detail/meta/type_traits.hpp b/include/nlohmann/detail/meta/type_traits.hpp
index 13e92cb4..3b93fa8b 100644
--- a/include/nlohmann/detail/meta/type_traits.hpp
+++ b/include/nlohmann/detail/meta/type_traits.hpp
@@ -1,10 +1,10 @@
 #pragma once
 
-#include <ciso646> // not
 #include <limits> // numeric_limits
 #include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
 #include <utility> // declval
 
+#include <nlohmann/detail/boolean_operators.hpp>
 #include <nlohmann/detail/iterators/iterator_traits.hpp>
 #include <nlohmann/detail/macro_scope.hpp>
 #include <nlohmann/detail/meta/cpp_future.hpp>
diff --git a/include/nlohmann/detail/output/binary_writer.hpp b/include/nlohmann/detail/output/binary_writer.hpp
index 69ed259d..cd826f09 100644
--- a/include/nlohmann/detail/output/binary_writer.hpp
+++ b/include/nlohmann/detail/output/binary_writer.hpp
@@ -194,9 +194,9 @@ class binary_writer
                 }
                 else
                 {
-                    if (j.m_value.number_float >= std::numeric_limits<float>::lowest() and
-                            j.m_value.number_float <= std::numeric_limits<float>::max() and
-                            static_cast<double>(static_cast<float>(j.m_value.number_float)) == j.m_value.number_float)
+                    if (static_cast<double>(j.m_value.number_float) >= static_cast<double>(std::numeric_limits<float>::lowest()) and
+                            static_cast<double>(j.m_value.number_float) <= static_cast<double>(std::numeric_limits<float>::max()) and
+                            static_cast<double>(static_cast<float>(j.m_value.number_float)) == static_cast<double>(j.m_value.number_float))
                     {
                         oa->write_character(get_cbor_float_prefix(static_cast<float>(j.m_value.number_float)));
                         write_number(static_cast<float>(j.m_value.number_float));
diff --git a/include/nlohmann/detail/output/serializer.hpp b/include/nlohmann/detail/output/serializer.hpp
index da544fad..75ce6783 100644
--- a/include/nlohmann/detail/output/serializer.hpp
+++ b/include/nlohmann/detail/output/serializer.hpp
@@ -3,7 +3,6 @@
 #include <algorithm> // reverse, remove, fill, find, none_of
 #include <array> // array
 #include <cassert> // assert
-#include <ciso646> // and, or
 #include <clocale> // localeconv, lconv
 #include <cmath> // labs, isfinite, isnan, signbit
 #include <cstddef> // size_t, ptrdiff_t
@@ -14,6 +13,7 @@
 #include <type_traits> // is_same
 #include <utility> // move
 
+#include <nlohmann/detail/boolean_operators.hpp>
 #include <nlohmann/detail/conversions/to_chars.hpp>
 #include <nlohmann/detail/exceptions.hpp>
 #include <nlohmann/detail/macro_scope.hpp>
diff --git a/include/nlohmann/detail/value_t.hpp b/include/nlohmann/detail/value_t.hpp
index 86b4630b..7580d856 100644
--- a/include/nlohmann/detail/value_t.hpp
+++ b/include/nlohmann/detail/value_t.hpp
@@ -1,11 +1,12 @@
 #pragma once
 
 #include <array> // array
-#include <ciso646> // and
 #include <cstddef> // size_t
 #include <cstdint> // uint8_t
 #include <string> // string
 
+#include <nlohmann/detail/boolean_operators.hpp>
+
 namespace nlohmann
 {
 namespace detail
diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp
index e5ac0bc1..270c2787 100644
--- a/include/nlohmann/json.hpp
+++ b/include/nlohmann/json.hpp
@@ -36,7 +36,6 @@ SOFTWARE.
 
 #include <algorithm> // all_of, find, for_each
 #include <cassert> // assert
-#include <ciso646> // and, not, or
 #include <cstddef> // nullptr_t, ptrdiff_t, size_t
 #include <functional> // hash, less
 #include <initializer_list> // initializer_list
@@ -49,6 +48,7 @@ SOFTWARE.
 #include <vector> // vector
 
 #include <nlohmann/adl_serializer.hpp>
+#include <nlohmann/detail/boolean_operators.hpp>
 #include <nlohmann/detail/conversions/from_json.hpp>
 #include <nlohmann/detail/conversions/to_json.hpp>
 #include <nlohmann/detail/exceptions.hpp>
diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp
index 3dbd2df0..395be7c8 100644
--- a/single_include/nlohmann/json.hpp
+++ b/single_include/nlohmann/json.hpp
@@ -36,7 +36,6 @@ SOFTWARE.
 
 #include <algorithm> // all_of, find, for_each
 #include <cassert> // assert
-#include <ciso646> // and, not, or
 #include <cstddef> // nullptr_t, ptrdiff_t, size_t
 #include <functional> // hash, less
 #include <initializer_list> // initializer_list
@@ -58,7 +57,6 @@ SOFTWARE.
 
 #include <algorithm> // transform
 #include <array> // array
-#include <ciso646> // and, not
 #include <forward_list> // forward_list
 #include <iterator> // inserter, front_inserter, end
 #include <map> // map
@@ -69,6 +67,16 @@ SOFTWARE.
 #include <utility> // pair, declval
 #include <valarray> // valarray
 
+// #include <nlohmann/detail/boolean_operators.hpp>
+
+
+// Header <ciso646> is removed in C++20.
+// See <https://github.com/nlohmann/json/issues/2089> for more information.
+
+#if __cplusplus <= 201703L
+    #include <ciso646> // and, not, or
+#endif
+
 // #include <nlohmann/detail/exceptions.hpp>
 
 
@@ -2495,10 +2503,12 @@ class other_error : public exception
 // #include <nlohmann/detail/meta/cpp_future.hpp>
 
 
-#include <ciso646> // not
 #include <cstddef> // size_t
 #include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
 
+// #include <nlohmann/detail/boolean_operators.hpp>
+
+
 namespace nlohmann
 {
 namespace detail
@@ -2560,11 +2570,12 @@ constexpr T static_const<T>::value;
 // #include <nlohmann/detail/meta/type_traits.hpp>
 
 
-#include <ciso646> // not
 #include <limits> // numeric_limits
 #include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
 #include <utility> // declval
 
+// #include <nlohmann/detail/boolean_operators.hpp>
+
 // #include <nlohmann/detail/iterators/iterator_traits.hpp>
 
 
@@ -3145,11 +3156,13 @@ struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<std::is_con
 
 
 #include <array> // array
-#include <ciso646> // and
 #include <cstddef> // size_t
 #include <cstdint> // uint8_t
 #include <string> // string
 
+// #include <nlohmann/detail/boolean_operators.hpp>
+
+
 namespace nlohmann
 {
 namespace detail
@@ -3610,7 +3623,6 @@ constexpr const auto& from_json = detail::static_const<detail::from_json_fn>::va
 
 
 #include <algorithm> // copy
-#include <ciso646> // or, and, not
 #include <iterator> // begin, end
 #include <string> // string
 #include <tuple> // tuple, get
@@ -3619,6 +3631,8 @@ constexpr const auto& from_json = detail::static_const<detail::from_json_fn>::va
 #include <valarray> // valarray
 #include <vector> // vector
 
+// #include <nlohmann/detail/boolean_operators.hpp>
+
 // #include <nlohmann/detail/iterators/iteration_proxy.hpp>
 
 
@@ -4209,6 +4223,8 @@ struct adl_serializer
 
 }  // namespace nlohmann
 
+// #include <nlohmann/detail/boolean_operators.hpp>
+
 // #include <nlohmann/detail/conversions/from_json.hpp>
 
 // #include <nlohmann/detail/conversions/to_json.hpp>
@@ -5609,7 +5625,7 @@ namespace detail
 
 @note from https://stackoverflow.com/a/1001328/266378
 */
-static bool little_endianess(int num = 1) noexcept
+static inline bool little_endianess(int num = 1) noexcept
 {
     return *reinterpret_cast<char*>(&num) == 1;
 }
@@ -10054,10 +10070,11 @@ template<typename BasicJsonType> struct internal_iterator
 // #include <nlohmann/detail/iterators/iter_impl.hpp>
 
 
-#include <ciso646> // not
 #include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
 #include <type_traits> // conditional, is_const, remove_const
 
+// #include <nlohmann/detail/boolean_operators.hpp>
+
 // #include <nlohmann/detail/exceptions.hpp>
 
 // #include <nlohmann/detail/iterators/internal_iterator.hpp>
@@ -12201,9 +12218,9 @@ class binary_writer
                 }
                 else
                 {
-                    if (j.m_value.number_float >= std::numeric_limits<float>::lowest() and
-                            j.m_value.number_float <= std::numeric_limits<float>::max() and
-                            static_cast<double>(static_cast<float>(j.m_value.number_float)) == j.m_value.number_float)
+                    if (static_cast<double>(j.m_value.number_float) >= static_cast<double>(std::numeric_limits<float>::lowest()) and
+                            static_cast<double>(j.m_value.number_float) <= static_cast<double>(std::numeric_limits<float>::max()) and
+                            static_cast<double>(static_cast<float>(j.m_value.number_float)) == static_cast<double>(j.m_value.number_float))
                     {
                         oa->write_character(get_cbor_float_prefix(static_cast<float>(j.m_value.number_float)));
                         write_number(static_cast<float>(j.m_value.number_float));
@@ -13584,7 +13601,6 @@ class binary_writer
 #include <algorithm> // reverse, remove, fill, find, none_of
 #include <array> // array
 #include <cassert> // assert
-#include <ciso646> // and, or
 #include <clocale> // localeconv, lconv
 #include <cmath> // labs, isfinite, isnan, signbit
 #include <cstddef> // size_t, ptrdiff_t
@@ -13595,17 +13611,21 @@ class binary_writer
 #include <type_traits> // is_same
 #include <utility> // move
 
+// #include <nlohmann/detail/boolean_operators.hpp>
+
 // #include <nlohmann/detail/conversions/to_chars.hpp>
 
 
 #include <array> // array
 #include <cassert> // assert
-#include <ciso646> // or, and, not
 #include <cmath>   // signbit, isfinite
 #include <cstdint> // intN_t, uintN_t
 #include <cstring> // memcpy, memmove
 #include <limits> // numeric_limits
 #include <type_traits> // conditional
+
+// #include <nlohmann/detail/boolean_operators.hpp>
+
 // #include <nlohmann/detail/macro_scope.hpp>
 
 
diff --git a/test/src/unit-cbor.cpp b/test/src/unit-cbor.cpp
index 28003258..2a53bb52 100644
--- a/test/src/unit-cbor.cpp
+++ b/test/src/unit-cbor.cpp
@@ -939,7 +939,7 @@ TEST_CASE("CBOR")
                 }
                 SECTION("-3.40282e+38(lowest float)")
                 {
-                    double v = std::numeric_limits<float>::lowest();
+                    double v = static_cast<double>(std::numeric_limits<float>::lowest());
                     json j = v;
                     std::vector<uint8_t> expected =
                     {
@@ -953,7 +953,7 @@ TEST_CASE("CBOR")
                 }
                 SECTION("1 + 3.40282e+38(more than max float)")
                 {
-                    double v = std::numeric_limits<float>::max() + 0.1e+34;
+                    double v = static_cast<double>(std::numeric_limits<float>::max()) + 0.1e+34;
                     json j = v;
                     std::vector<uint8_t> expected =
                     {
@@ -968,7 +968,7 @@ TEST_CASE("CBOR")
                 }
                 SECTION("-1 - 3.40282e+38(less than lowest float)")
                 {
-                    double v = std::numeric_limits<float>::lowest() - 1;
+                    double v = static_cast<double>(std::numeric_limits<float>::lowest()) - 1.0;
                     json j = v;
                     std::vector<uint8_t> expected =
                     {
@@ -1582,7 +1582,7 @@ TEST_CASE("CBOR")
                 auto j = json::from_cbor(input);
                 CHECK(j.is_binary());
                 auto k = json::binary_array({0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x99});
-                CAPTURE(j.dump(0, ' ', false, json::error_handler_t::strict, true));
+                CAPTURE(j.dump(0, ' ', false, json::error_handler_t::strict, true))
                 CHECK(j == k);
             }
 
diff --git a/test/src/unit-noexcept.cpp b/test/src/unit-noexcept.cpp
index 8fbe9f91..6952c0ee 100644
--- a/test/src/unit-noexcept.cpp
+++ b/test/src/unit-noexcept.cpp
@@ -46,7 +46,12 @@ void to_json(json&, pod) noexcept;
 void to_json(json&, pod_bis);
 void from_json(const json&, pod) noexcept;
 void from_json(const json&, pod_bis);
-static json* j;
+void to_json(json&, pod) noexcept {}
+void to_json(json&, pod_bis) {}
+void from_json(const json&, pod) noexcept {}
+void from_json(const json&, pod_bis) {}
+
+static json* j = nullptr;
 
 static_assert(noexcept(json{}), "");
 static_assert(noexcept(nlohmann::to_json(*j, 2)), "");
@@ -79,4 +84,14 @@ TEST_CASE("runtime checks")
         CHECK(std::is_nothrow_copy_constructible<json::out_of_range>::value == std::is_nothrow_copy_constructible<std::runtime_error>::value);
         CHECK(std::is_nothrow_copy_constructible<json::other_error>::value == std::is_nothrow_copy_constructible<std::runtime_error>::value);
     }
+
+    SECTION("silence -Wunneeded-internal-declaration errors")
+    {
+        j = nullptr;
+        json j2;
+        to_json(j2, pod());
+        to_json(j2, pod_bis());
+        from_json(j2, pod());
+        from_json(j2, pod_bis());
+    }
 }
diff --git a/test/src/unit-udt.cpp b/test/src/unit-udt.cpp
index b1da8c37..cd9ce69f 100644
--- a/test/src/unit-udt.cpp
+++ b/test/src/unit-udt.cpp
@@ -120,6 +120,8 @@ static void to_json(BasicJsonType& j, country c)
         case country::russia:
             j = u8"Российская Федерация";
             return;
+        default:
+            break;
     }
 }
 
@@ -803,7 +805,9 @@ class Evil
   public:
     Evil() = default;
     template <typename T>
-    Evil(T) {}
+    Evil(T t) : m_i(sizeof(t)) {}
+
+    int m_i = 0;
 };
 
 void from_json(const json&, Evil&) {}
@@ -816,6 +820,10 @@ TEST_CASE("Issue #924")
 
     CHECK_NOTHROW(j.get<Evil>());
     CHECK_NOTHROW(j.get<std::vector<Evil>>());
+
+    // silence Wunused-template warnings
+    Evil e(1);
+    CHECK(e.m_i >= 0);
 }
 
 TEST_CASE("Issue #1237")
diff --git a/test/thirdparty/doctest/doctest.h b/test/thirdparty/doctest/doctest.h
index 4f3a0e33..2f0ff213 100755
--- a/test/thirdparty/doctest/doctest.h
+++ b/test/thirdparty/doctest/doctest.h
@@ -2913,7 +2913,7 @@ typedef timer_large_integer::type ticks_t;
         //unsigned int getElapsedMilliseconds() const {
         //    return static_cast<unsigned int>(getElapsedMicroseconds() / 1000);
         //}
-        double getElapsedSeconds() const { return (getCurrentTicks() - m_ticks) / 1000000.0; }
+        double getElapsedSeconds() const { return static_cast<double>((getCurrentTicks() - m_ticks)) / 1000000.0; }
 
     private:
         ticks_t m_ticks = 0;