From f0c0312e8d9260caf1ec9c71202ef72e16f24efb Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Sun, 26 Jul 2026 19:37:11 +1000 Subject: [PATCH] Fix Windows (MSVC) and WASM (Emscripten) build failures Both surfaced on the first Windows/WASM CI run of this branch: - XmlSerializer.cpp: the IfcPropertySetDefinitionSet block used a C-style cast to convert the set to std::vector. GCC invokes the non-explicit conversion operator; MSVC rejects the cast to a template type (C2440/C3536/C2661). Use copy-initialisation instead, which invokes the same implicit conversion portably. (This block was dead until the SCHEMAS_->SCHEMA_HAS_ typo fix enabled it, so it had never hit MSVC.) - parse.cpp: the floating-point parse path falls back to strtod_l because libc++ =deletes the float from_chars overload. That fallback was guarded for __APPLE__ only; Emscripten uses the same libc++, so WASM hit the deleted from_chars. Extend the guard to __EMSCRIPTEN__ (its musl provides strtod_l/newlocale, treating all locales as C). Co-Authored-By: Claude Opus 4.8 --- src/ifcparse/parse.cpp | 6 +++--- src/serializers/schema_dependent/XmlSerializer.cpp | 6 +++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/ifcparse/parse.cpp b/src/ifcparse/parse.cpp index 3a21b61cc4..912638b90d 100644 --- a/src/ifcparse/parse.cpp +++ b/src/ifcparse/parse.cpp @@ -134,7 +134,7 @@ std::string& spf_lexer::get_temp_string() const { namespace { -#if defined(__APPLE__) +#if defined(__APPLE__) || defined(__EMSCRIPTEN__) double parse_double_c(const char* start, char** end) { static const locale_t loc = newlocale(LC_NUMERIC_MASK, "C", (locale_t)0); return strtod_l(start, end, loc); @@ -154,11 +154,11 @@ bool parse_num_(const char* pStart, size_t size, T& val) { } } if constexpr (std::is_floating_point_v) { -#if defined(__APPLE__) +#if defined(__APPLE__) || defined(__EMSCRIPTEN__) // pStart is NUL-terminated at pStart + size (callers pass c_str()), so // strtod_l stops exactly at the end of a well-formed number. from_chars // is not instantiated for double here — its float overload is =deleted - // in Apple's libc++. + // in libc++ (Apple's and Emscripten's). char* pEnd = nullptr; const double result = parse_double_c(pStart, &pEnd); if (pEnd != pStart + size) { diff --git a/src/serializers/schema_dependent/XmlSerializer.cpp b/src/serializers/schema_dependent/XmlSerializer.cpp index 0fcde6d86b..a9528791db 100644 --- a/src/serializers/schema_dependent/XmlSerializer.cpp +++ b/src/serializers/schema_dependent/XmlSerializer.cpp @@ -300,7 +300,11 @@ ptree* descend(::logger& log, ifcopenshell::geometry::abstract_mapping* mapping, (log, object, &IfcSchema::IfcObject::IsDefinedBy, &IfcSchema::IfcRelDefinesByProperties::RelatingPropertyDefinition); for (auto& s : property_set_sets) { - auto set_sets_value = (decltype(property_sets))s; + // Copy-initialise (not a C-style cast) so the implicit + // IfcPropertySetDefinitionSet -> std::vector + // conversion operator is used. MSVC rejects the equivalent cast to a + // template type (C2440), whereas copy-initialisation is portable. + decltype(property_sets) set_sets_value = s; property_sets.insert(property_sets.end(), set_sets_value.begin(), set_sets_value.end()); } #endif