Rework MSVC warning suppression

Previously, MSVC warning C4996 was suppressed unconditionally in the
entire code base which made it difficult identifying and fixing specific
problems, particularly those in the public interface.

Prefer now to disable warnings at the specific location they occur. This
approach, however, reveals an inconsistency in how Ceres handles POSIX
functions which are declared deprecated by MSVC. Specifically, Bessel
functions use the underscore form whereas the read function does not. To
simplify the logic, we revert to POSIX compatible functions.

C++23 also deprecates std::numeric_limits<T>::has_denorm which MSVC
warns about. Here, we disable the deprecation warning locally to avoid
the warning leaking into the user code.

Fixes #1013

Change-Id: Ida8457cc8dd8770b4384a7c49d16f213b02cdec4
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 91cf6b1..5f17d88 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -521,18 +521,20 @@
   # that _USE_MATH_DEFINES is defined before the first inclusion of <cmath>.
   #
   # [1] https://msdn.microsoft.com/en-us/library/4hwaceh6.aspx
-  add_definitions("-D_USE_MATH_DEFINES")
+  add_compile_definitions(_USE_MATH_DEFINES)
+  # Insecure standard library functions
+  add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
+  # std::numeric_limits<T>::has_denorm is deprecated in C++23
+  add_compile_definitions($<$<COMPILE_LANGUAGE:CXX>:_SILENCE_CXX23_DENORM_DEPRECATION_WARNING>)
+  # std::aligned_storage is deprecated in C++23
+  add_compile_definitions($<$<COMPILE_LANGUAGE:CXX>:_SILENCE_CXX23_ALIGNED_STORAGE_DEPRECATION_WARNING>)
   # Disable signed/unsigned int conversion warnings.
   add_compile_options($<$<COMPILE_LANGUAGE:CXX>:/wd4018>)
   add_compile_options($<$<COMPILE_LANGUAGE:CXX>:/wd4267>)
   # Disable warning about using struct/class for the same symbol.
   add_compile_options($<$<COMPILE_LANGUAGE:CXX>:/wd4099>)
-  # Disable warning about the insecurity of using "std::copy".
-  add_compile_options($<$<COMPILE_LANGUAGE:CXX>:/wd4996>)
   # Disable performance warning about int-to-bool conversion.
   add_compile_options($<$<COMPILE_LANGUAGE:CXX>:/wd4800>)
-  # Disable performance warning about fopen insecurity.
-  add_compile_options($<$<COMPILE_LANGUAGE:CXX>:/wd4996>)
   # Disable warning about int64 to int32 conversion. Disabling
   # this warning may not be correct; needs investigation.
   # TODO(keir): Investigate these warnings in more detail.
@@ -556,14 +558,6 @@
 
   # Tuple sizes of 10 are used by Gtest.
   add_definitions("-D_VARIADIC_MAX=10")
-
-  include(CheckIfUnderscorePrefixedBesselFunctionsExist)
-  check_if_underscore_prefixed_bessel_functions_exist(
-    HAVE_UNDERSCORE_PREFIXED_BESSEL_FUNCTIONS)
-  if (HAVE_UNDERSCORE_PREFIXED_BESSEL_FUNCTIONS)
-    list(APPEND CERES_COMPILE_OPTIONS
-      CERES_MSVC_USE_UNDERSCORE_PREFIXED_BESSEL_FUNCTIONS)
-  endif()
 endif (MSVC)
 
 if (UNIX)
diff --git a/cmake/CheckIfUnderscorePrefixedBesselFunctionsExist.cmake b/cmake/CheckIfUnderscorePrefixedBesselFunctionsExist.cmake
deleted file mode 100644
index c004cb8..0000000
--- a/cmake/CheckIfUnderscorePrefixedBesselFunctionsExist.cmake
+++ /dev/null
@@ -1,54 +0,0 @@
-# Ceres Solver - A fast non-linear least squares minimizer
-# Copyright 2023 Google Inc. All rights reserved.
-# http://ceres-solver.org/
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#
-# * Redistributions of source code must retain the above copyright notice,
-#   this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above copyright notice,
-#   this list of conditions and the following disclaimer in the documentation
-#   and/or other materials provided with the distribution.
-# * Neither the name of Google Inc. nor the names of its contributors may be
-#   used to endorse or promote products derived from this software without
-#   specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-# Author: alexs.mac@gmail.com (Alex Stewart)
-
-# Microsoft deprecated the POSIX Bessel functions: j[0,1,n]() in favour
-# of _j[0,1,n](), it appears since at least MSVC 2005 [1].  This function
-# checks if the underscore prefixed versions of the Bessel functions are
-# defined, and sets ${HAVE_UNDERSCORE_PREFIXED_BESSEL_FUNCTIONS_VAR} to
-# TRUE if they do.
-#
-# [1] https://msdn.microsoft.com/en-us/library/ms235384(v=vs.100).aspx
-function(check_if_underscore_prefixed_bessel_functions_exist
-    HAVE_UNDERSCORE_PREFIXED_BESSEL_FUNCTIONS_VAR)
-  include(CheckCXXSourceCompiles)
-  check_cxx_source_compiles(
-    "#include <math.h>
-     int main(int argc, char * argv[]) {
-       double result;
-       result = _j0(1.2345);
-       result = _j1(1.2345);
-       result = _jn(2, 1.2345);
-       return 0;
-     }"
-     HAVE_UNDERSCORE_PREFIXED_BESSEL_FUNCTIONS)
-   set(${HAVE_UNDERSCORE_PREFIXED_BESSEL_FUNCTIONS_VAR}
-     ${HAVE_UNDERSCORE_PREFIXED_BESSEL_FUNCTIONS}
-     PARENT_SCOPE)
-endfunction()
diff --git a/examples/libmv_bundle_adjuster.cc b/examples/libmv_bundle_adjuster.cc
index 2f68793..9315ed7 100644
--- a/examples/libmv_bundle_adjuster.cc
+++ b/examples/libmv_bundle_adjuster.cc
@@ -301,7 +301,9 @@
   template <typename T>
   T Read() const {
     T value;
+    CERES_DISABLE_DEPRECATED_WARNING
     CHECK_GT(read(file_descriptor_, &value, sizeof(value)), 0);
+    CERES_RESTORE_DEPRECATED_WARNING
     // Switch endian type if file contains data in different type
     // that current machine.
     if (file_endian_type_ != host_endian_type_) {
diff --git a/include/ceres/internal/port.h b/include/ceres/internal/port.h
index e61ef52..b8cb0ff 100644
--- a/include/ceres/internal/port.h
+++ b/include/ceres/internal/port.h
@@ -77,4 +77,15 @@
 //
 #define CERES_PREVENT_MACRO_SUBSTITUTION  // Yes, it's empty
 
+// CERES_DISABLE_DEPRECATED_WARNING and CERES_RESTORE_DEPRECATED_WARNING allow
+// to temporarily disable deprecation warnings
+#if defined(_MSC_VER)
+#define CERES_DISABLE_DEPRECATED_WARNING \
+  _Pragma("warning(push)") _Pragma("warning(disable : 4996)")
+#define CERES_RESTORE_DEPRECATED_WARNING _Pragma("warning(pop)")
+#else  // defined(_MSC_VER)
+#define CERES_DISABLE_DEPRECATED_WARNING
+#define CERES_RESTORE_DEPRECATED_WARNING
+#endif  // defined(_MSC_VER)
+
 #endif  // CERES_PUBLIC_INTERNAL_PORT_H_
diff --git a/include/ceres/jet.h b/include/ceres/jet.h
index 768f04a..f279ba3 100644
--- a/include/ceres/jet.h
+++ b/include/ceres/jet.h
@@ -874,25 +874,19 @@
 // function errors in client code (the specific warning is suppressed when
 // Ceres itself is built).
 inline double BesselJ0(double x) {
-#if defined(CERES_MSVC_USE_UNDERSCORE_PREFIXED_BESSEL_FUNCTIONS)
-  return _j0(x);
-#else
+  CERES_DISABLE_DEPRECATED_WARNING
   return j0(x);
-#endif
+  CERES_RESTORE_DEPRECATED_WARNING
 }
 inline double BesselJ1(double x) {
-#if defined(CERES_MSVC_USE_UNDERSCORE_PREFIXED_BESSEL_FUNCTIONS)
-  return _j1(x);
-#else
+  CERES_DISABLE_DEPRECATED_WARNING
   return j1(x);
-#endif
+  CERES_RESTORE_DEPRECATED_WARNING
 }
 inline double BesselJn(int n, double x) {
-#if defined(CERES_MSVC_USE_UNDERSCORE_PREFIXED_BESSEL_FUNCTIONS)
-  return _jn(n, x);
-#else
+  CERES_DISABLE_DEPRECATED_WARNING
   return jn(n, x);
-#endif
+  CERES_RESTORE_DEPRECATED_WARNING
 }
 
 // For the formulae of the derivatives of the Bessel functions see the book:
@@ -1310,8 +1304,13 @@
   static constexpr bool is_bounded = std::numeric_limits<T>::is_bounded;
   static constexpr bool is_modulo = std::numeric_limits<T>::is_modulo;
 
+  // has_denorm (and has_denorm_loss, not defined for Jet) has been deprecated
+  // in C++23. However, without an intent to remove the declaration. Disable
+  // deprecation warnings temporarily just for the corresponding symbols.
+  CERES_DISABLE_DEPRECATED_WARNING
   static constexpr std::float_denorm_style has_denorm =
       std::numeric_limits<T>::has_denorm;
+  CERES_RESTORE_DEPRECATED_WARNING
   static constexpr std::float_round_style round_style =
       std::numeric_limits<T>::round_style;