Address review: fix all compiler warnings across GCC, Clang, and MSVC

Requested by @lefticus in PR #687 review.

Fix warnings-as-errors failures on all three compiler families:

- GCC Release: replace strncpy with memcpy in mystrdup (stringop-truncation)
- GCC ASAN+UBSAN Release: add bounds check in Operator() before indexing
  m_operators array — the recursive call could exceed the array size of 12,
  which is an actual out-of-bounds bug, not just a warning
- GCC: downgrade maybe-uninitialized to warning (false positive in libstdc++
  std::regex under sanitizers + optimizations)
- AppleClang: add default cases to all switch statements on Common_Types in
  boxed_number.hpp (Wswitch-default)
- AppleClang: mark Dispatch_Engine move ctor/assignment as deleted since
  shared_mutex is non-movable (Wdefaulted-function-deleted)
- AppleClang on macOS: suppress Wpoison-system-directories for /usr/local/include
- MSVC Release: suppress C4702 (unreachable code) around if-constexpr in
  proxy_functions_detail.hpp
- Fix unused variable warnings in emscripten_eval_test.cpp when asserts are
  disabled in Release mode

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
leftibot 2026-04-14 12:06:25 -06:00
parent 7f63b5dbd1
commit 88d3124272
7 changed files with 35 additions and 18 deletions

View File

@ -180,11 +180,11 @@ else()
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang") if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang")
add_definitions(-Weverything -Wno-c++98-compat-pedantic -Wno-c++98-compat -Wno-documentation -Wno-switch-enum -Wno-weak-vtables -Wno-missing-prototypes -Wno-padded -Wno-missing-noreturn -Wno-exit-time-destructors -Wno-documentation-unknown-command -Wno-unused-template -Wno-undef -Wno-double-promotion) add_definitions(-Weverything -Wno-c++98-compat-pedantic -Wno-c++98-compat -Wno-documentation -Wno-switch-enum -Wno-weak-vtables -Wno-missing-prototypes -Wno-padded -Wno-missing-noreturn -Wno-exit-time-destructors -Wno-documentation-unknown-command -Wno-unused-template -Wno-undef -Wno-double-promotion)
else() else()
add_definitions(-Wnoexcept) add_definitions(-Wnoexcept -Wno-error=maybe-uninitialized)
endif() endif()
if(APPLE) if(APPLE)
add_definitions(-Wno-sign-compare) add_definitions(-Wno-sign-compare -Wno-poison-system-directories)
endif() endif()
endif() endif()

View File

@ -272,6 +272,8 @@ namespace chaiscript {
return callable(*static_cast<const float *>(bv.get_const_ptr())); return callable(*static_cast<const float *>(bv.get_const_ptr()));
case Common_Types::t_long_double: case Common_Types::t_long_double:
return callable(*static_cast<const long double *>(bv.get_const_ptr())); return callable(*static_cast<const long double *>(bv.get_const_ptr()));
default:
throw chaiscript::detail::exception::bad_any_cast();
} }
throw chaiscript::detail::exception::bad_any_cast(); throw chaiscript::detail::exception::bad_any_cast();
} }
@ -479,6 +481,8 @@ namespace chaiscript {
case Common_Types::t_long_double: case Common_Types::t_long_double:
check_type<long double, Target>(); check_type<long double, Target>();
return get_as_aux<Target, long double>(bv); return get_as_aux<Target, long double>(bv);
default:
throw chaiscript::detail::exception::bad_any_cast();
} }
throw chaiscript::detail::exception::bad_any_cast(); throw chaiscript::detail::exception::bad_any_cast();
@ -509,6 +513,8 @@ namespace chaiscript {
return get_as_aux<Target, float>(bv); return get_as_aux<Target, float>(bv);
case Common_Types::t_long_double: case Common_Types::t_long_double:
return get_as_aux<Target, long double>(bv); return get_as_aux<Target, long double>(bv);
default:
throw chaiscript::detail::exception::bad_any_cast();
} }
throw chaiscript::detail::exception::bad_any_cast(); throw chaiscript::detail::exception::bad_any_cast();
@ -538,6 +544,8 @@ namespace chaiscript {
return to_string_aux<float>(bv); return to_string_aux<float>(bv);
case Common_Types::t_long_double: case Common_Types::t_long_double:
return to_string_aux<long double>(bv); return to_string_aux<long double>(bv);
default:
throw chaiscript::detail::exception::bad_any_cast();
} }
throw chaiscript::detail::exception::bad_any_cast(); throw chaiscript::detail::exception::bad_any_cast();

View File

@ -377,8 +377,8 @@ namespace chaiscript {
Dispatch_Engine(const Dispatch_Engine &) = delete; Dispatch_Engine(const Dispatch_Engine &) = delete;
Dispatch_Engine &operator=(const Dispatch_Engine &) = delete; Dispatch_Engine &operator=(const Dispatch_Engine &) = delete;
Dispatch_Engine(Dispatch_Engine &&) = default; Dispatch_Engine(Dispatch_Engine &&) = delete;
Dispatch_Engine &operator=(Dispatch_Engine &&) = default; Dispatch_Engine &operator=(Dispatch_Engine &&) = delete;
#ifndef CHAISCRIPT_NO_THREADS #ifndef CHAISCRIPT_NO_THREADS
/// Track an async thread so it can be joined during destruction /// Track an async thread so it can be joined during destruction

View File

@ -92,6 +92,10 @@ namespace chaiscript {
/// The function attempts to unbox each parameter to the expected type. /// The function attempts to unbox each parameter to the expected type.
/// if any unboxing fails the execution of the function fails and /// if any unboxing fails the execution of the function fails and
/// the bad_boxed_cast is passed up to the caller. /// the bad_boxed_cast is passed up to the caller.
#ifdef CHAISCRIPT_MSVC
#pragma warning(push)
#pragma warning(disable : 4702)
#endif
template<typename Callable, typename Ret, typename... Params> template<typename Callable, typename Ret, typename... Params>
Boxed_Value Boxed_Value
call_func(Ret (*sig)(Params...), const Callable &f, const chaiscript::Function_Params &params, const Type_Conversions_State &t_conversions) { call_func(Ret (*sig)(Params...), const Callable &f, const chaiscript::Function_Params &params, const Type_Conversions_State &t_conversions) {
@ -102,6 +106,9 @@ namespace chaiscript {
return Handle_Return<Ret>::handle(call_func(sig, std::index_sequence_for<Params...>{}, f, params, t_conversions)); return Handle_Return<Ret>::handle(call_func(sig, std::index_sequence_for<Params...>{}, f, params, t_conversions));
} }
} }
#ifdef CHAISCRIPT_MSVC
#pragma warning(pop)
#endif
} // namespace detail } // namespace detail
} // namespace dispatch } // namespace dispatch

View File

@ -2570,6 +2570,10 @@ namespace chaiscript {
bool retval = false; bool retval = false;
const auto prev_stack_top = m_match_stack.size(); const auto prev_stack_top = m_match_stack.size();
if (t_precedence >= m_operators.size()) {
return Value();
}
if (m_operators[t_precedence] != Operator_Precedence::Prefix) { if (m_operators[t_precedence] != Operator_Precedence::Prefix) {
if (Operator(t_precedence + 1)) { if (Operator(t_precedence + 1)) {
retval = true; retval = true;

View File

@ -34,7 +34,7 @@ char *mystrdup(const char *s) {
#ifdef CHAISCRIPT_MSVC #ifdef CHAISCRIPT_MSVC
strcpy_s(d, len + 1, s); // Copy the characters strcpy_s(d, len + 1, s); // Copy the characters
#else #else
strncpy(d, s, len); // Copy the characters memcpy(d, s, len);
#endif #endif
d[len] = '\0'; d[len] = '\0';
return d; // Return the new string return d; // Return the new string

View File

@ -16,36 +16,34 @@
#include <string> #include <string>
int main() { int main() {
// Test eval (void return) - same as Emscripten eval()
chaiscript_eval("var x = 42"); chaiscript_eval("var x = 42");
// Test evalString - same as Emscripten evalString() const std::string s = chaiscript_eval_string("to_string(x)");
std::string s = chaiscript_eval_string("to_string(x)");
assert(s == "42"); assert(s == "42");
static_cast<void>(s);
// Test evalInt - same as Emscripten evalInt() const int i = chaiscript_eval_int("1 + 2");
int i = chaiscript_eval_int("1 + 2");
assert(i == 3); assert(i == 3);
static_cast<void>(i);
// Test evalBool - same as Emscripten evalBool()
bool b = chaiscript_eval_bool("true"); bool b = chaiscript_eval_bool("true");
assert(b == true); assert(b == true);
b = chaiscript_eval_bool("false"); b = chaiscript_eval_bool("false");
assert(b == false); assert(b == false);
static_cast<void>(b);
// Test evalFloat - same as Emscripten evalFloat() const float f = chaiscript_eval_float("1.5f");
float f = chaiscript_eval_float("1.5f");
assert(std::abs(f - 1.5f) < 0.001f); assert(std::abs(f - 1.5f) < 0.001f);
static_cast<void>(f);
// Test evalDouble - same as Emscripten evalDouble() const double d = chaiscript_eval_double("3.14");
double d = chaiscript_eval_double("3.14");
assert(std::abs(d - 3.14) < 0.001); assert(std::abs(d - 3.14) < 0.001);
static_cast<void>(d);
// Test a more complex expression
chaiscript_eval("def square(n) { return n * n; }"); chaiscript_eval("def square(n) { return n * n; }");
int sq = chaiscript_eval_int("square(7)"); const int sq = chaiscript_eval_int("square(7)");
assert(sq == 49); assert(sq == 49);
static_cast<void>(sq);
return 0; return 0;
} }