@@ -559,8 +559,6 @@ std::optional<std::string> find_disallowed_array_of_tables(
559559 return std::nullopt ;
560560}
561561
562- } // namespace
563-
564562// [c-abi.absent] — the facilities a C library does not supply (design
565563// 2026-09-20 §5.7.5). The set of names it DOES supply is not enumerable in a
566564// manifest; the exceptions are, and enumerating an exception is what lets a CI
@@ -577,36 +575,43 @@ std::optional<std::string> find_disallowed_array_of_tables(
577575// the other two are departures from it, named so that a departure is something
578576// that can be counted.
579577//
580- // A FREE FUNCTION AND NOT A BLOCK INSIDE `parse_string`, FOR A MEASURED
581- // REASON. Written inline it crashed clang 20.1.7 on Windows during LLVM IR
582- // generation of `parse_string` (exception 0xC0000005, the frame naming this
583- // block's compound statement); every other host compiled it. This codebase has
584- // met the shape before — a construct that is fine in a function and not in a
585- // large one inside a module interface unit — and the answer is the same: give
586- // it its own function.
587- inline std::expected<std::vector<mcpp::targetside::CAbiAbsentEntry>, std::string>
588- parse_c_abi_absent (const t::Value& v) {
589- std::vector<mcpp::targetside::CAbiAbsentEntry> out;
578+ // THE SHAPE OF THIS FUNCTION IS MEASURED RATHER THAN STYLISTIC. Written as a
579+ // block inside `parse_string` it crashed clang 20.1.7 on Windows during LLVM
580+ // IR generation (exception 0xC0000005); moved out to a free function returning
581+ // `std::expected<std::vector<CAbiAbsentEntry>, std::string>` the crash moved
582+ // with it, now naming this function. Every other host and every other compiler
583+ // compiled all three spellings. What it takes is the plainest form available:
584+ // an out parameter and an optional error, with no `expected` over a vector of
585+ // structs carrying strings. The note is here so that a later tidy-up does not
586+ // restore a shorter spelling and rediscover this on a Windows runner.
587+ //
588+ // It also belongs in this anonymous namespace and not in the module's exported
589+ // purview, where the first two spellings were written. An inline function in
590+ // the purview is emitted into every importer of the module; this one is an
591+ // implementation detail of `parse_string` and has no reader outside it.
592+ inline std::optional<std::string>
593+ parse_c_abi_absent (const t::Value& v,
594+ std::vector<mcpp::targetside::CAbiAbsentEntry>& out) {
590595 if (!v.is_table ())
591- return std::unexpected (std::string (
596+ return std::optional<std::string> (std::string (
592597 " [c-abi.absent] must be a table of facility names, each with a "
593598 " `form`: fork = { form = \" link\" }" ));
594599 for (auto const & kv : v.as_table ()) {
595600 const std::string& name = kv.first ;
596601 const t::Value& ent = kv.second ;
597602 if (!ent.is_table ())
598- return std::unexpected (std::format (
603+ return std::optional<std::string> (std::format (
599604 " [c-abi.absent].{} must be a table with a `form`: "
600605 " {} = {{ form = \" link\" }}" , name, name));
601606 const auto & et = ent.as_table ();
602607 for (auto const & m : et)
603608 if (m.first != " form" && m.first != " note" )
604- return std::unexpected (std::format (
609+ return std::optional<std::string> (std::format (
605610 " [c-abi.absent].{} has no member '{}'; the members are: "
606611 " form, note" , name, m.first ));
607612 auto fit = et.find (" form" );
608613 if (fit == et.end () || !fit->second .is_string ())
609- return std::unexpected (std::format (
614+ return std::optional<std::string> (std::format (
610615 " [c-abi.absent].{} is missing `form`. An absence with no "
611616 " named shape is one nothing can assert against; the shapes "
612617 " are \" link\" (the definition is absent), \" enosys\" (it "
@@ -615,7 +620,7 @@ parse_c_abi_absent(const t::Value& v) {
615620 " it asked for is not done)." , name));
616621 auto form = mcpp::targetside::parse_c_abi_absent_form (fit->second .as_string ());
617622 if (!form)
618- return std::unexpected (std::format (
623+ return std::optional<std::string> (std::format (
619624 " [c-abi.absent].{}.form = \" {}\" names no known shape. The "
620625 " shapes are \" link\" , \" enosys\" and \" accepted-no-effect\" ." ,
621626 name, fit->second .as_string ()));
@@ -626,10 +631,23 @@ parse_c_abi_absent(const t::Value& v) {
626631 e.note = nit->second .as_string ();
627632 out.push_back (std::move (e));
628633 }
629- std::ranges::sort (out, {}, &mcpp::targetside::CAbiAbsentEntry::name);
630- return out;
634+ // A PLAIN COMPARATOR AND NOT A PROJECTION. `std::ranges::sort(out, {},
635+ // &CAbiAbsentEntry::name)` says the same thing and crashed clang 20.1.7 on
636+ // Windows while generating code for this function (0xC0000005). A
637+ // pointer-to-member used as a projection is a shape this codebase has met
638+ // before on that front end; the note is here so the shorter spelling is
639+ // not restored as a tidy-up.
640+ std::sort (out.begin (), out.end (),
641+ [](const mcpp::targetside::CAbiAbsentEntry& a,
642+ const mcpp::targetside::CAbiAbsentEntry& b) {
643+ return a.name < b.name ;
644+ });
645+ return std::nullopt ;
631646}
632647
648+ } // namespace
649+
650+
633651std::expected<Manifest, ManifestError> parse_string (std::string_view content,
634652 const std::filesystem::path& origin,
635653 LoadContext ctx) {
@@ -1155,9 +1173,8 @@ std::expected<Manifest, ManifestError> parse_string(std::string_view content,
11551173 " builtins, data-model, presents, wchar" , key)));
11561174 }
11571175 if (auto ait = ct->find (" absent" ); ait != ct->end ()) {
1158- auto absent = parse_c_abi_absent (ait->second );
1159- if (!absent) return std::unexpected (error (origin, absent.error ()));
1160- decl.absent = std::move (*absent);
1176+ if (auto why = parse_c_abi_absent (ait->second , decl.absent ))
1177+ return std::unexpected (error (origin, *why));
11611178 }
11621179 if (auto pit = ct->find (" presents" ); pit != ct->end ()) {
11631180 if (!pit->second .is_string ())
0 commit comments