Skip to content

Commit 6193d62

Browse files
committed
fix: the new lookups use a predicate, not a projection by pointer-to-member
A `std::ranges` projection spelled as a pointer-to-member into a type the module imports makes clang 20.1.7 crash in code generation, and the report names an unrelated function: first `mcpp::pack::interface_set_digest`, then `mcpp::doctor::why_report`, both on windows-2022. Every lookup this branch added over the decision record now passes a predicate, which reads the same and compiles on every host.
1 parent e28609f commit 6193d62

3 files changed

Lines changed: 25 additions & 10 deletions

File tree

‎src/build/prepare/sources.cpp‎

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,15 @@ void record_source(PrepareState& state, SourceDecision d) {
111111
mcpp::ui::source("Using", std::format("{} ← {}", what, d.value),
112112
source_tag(d, root), d.cls == SourceClass::Host);
113113
}
114-
auto it = std::ranges::find(state.sources, d.subject, &SourceDecision::subject);
114+
// A PREDICATE, NOT A PROJECTION BY POINTER-TO-MEMBER. The latter into a
115+
// type this module imports makes clang 20.1.7 crash while generating code,
116+
// and the report names an unrelated function (measured on windows-2022,
117+
// 2026-10-01; `mcpp.toolchain.model`'s `ToolOverride` records the same
118+
// hazard for an exported `std::pair`).
119+
auto by_subject = [](std::string_view subject) {
120+
return [subject](const SourceDecision& o) { return o.subject == subject; };
121+
};
122+
auto it = std::ranges::find_if(state.sources, by_subject(d.subject));
115123
if (it == state.sources.end()) state.sources.push_back(std::move(d));
116124
else *it = std::move(d);
117125
}
@@ -446,7 +454,9 @@ answer_payload_requests(PrepareState& state, mcpp::manifest::Manifest& m,
446454
state.requestedPayloads.insert(keys[i]);
447455
state.xlingsDeferred.erase(keys[i]);
448456
state.xlingsSkipped.erase(addresses[i]);
449-
auto it = std::ranges::find(state.sources, "payload:" + keys[i], &SourceDecision::subject);
457+
const auto subject = "payload:" + keys[i];
458+
auto it = std::ranges::find_if(state.sources, [&](const SourceDecision& o) {
459+
return o.subject == subject; });
450460
if (it != state.sources.end()) {
451461
it->considered.clear();
452462
it->considered.push_back(std::format("installed on request of `{}`", who));
@@ -518,8 +528,9 @@ void record_tool_decisions(PrepareState& state) {
518528
const auto payload = f.size() > 5 ? f[5] : std::string{};
519529
d.payload = payload;
520530
d.announce = false;
521-
auto it = std::ranges::find(state.sources, "payload:" + payload,
522-
&SourceDecision::subject);
531+
const auto psubject = "payload:" + payload;
532+
auto it = std::ranges::find_if(state.sources, [&](const SourceDecision& o) {
533+
return o.subject == psubject; });
523534
if (it != state.sources.end()) {
524535
d.cls = it->cls; d.originKind = it->originKind;
525536
d.originFile = it->originFile; d.originLine = it->originLine;
@@ -539,8 +550,9 @@ void record_tool_decisions(PrepareState& state) {
539550
d.announce = false;
540551
if (f.size() > 5) {
541552
d.payload = f[5];
542-
auto it = std::ranges::find(state.sources, "payload:" + f[5],
543-
&SourceDecision::subject);
553+
const auto psubject = "payload:" + f[5];
554+
auto it = std::ranges::find_if(state.sources, [&](const SourceDecision& o) {
555+
return o.subject == psubject; });
544556
if (it != state.sources.end()) d.cls = it->cls;
545557
}
546558
}
@@ -558,7 +570,7 @@ std::expected<void, std::string> step13_sources(PrepareState& state, BuildContex
558570
// managed payload, and how it was chosen. A toolchain named by path or by
559571
// the build program was recorded where it was resolved, and announced
560572
// there, next to the `Resolving toolchain` line.
561-
if (std::ranges::none_of(state.sources, [](auto const& d) {
573+
if (std::ranges::none_of(state.sources, [](const SourceDecision& d) {
562574
return d.subject == "toolchain.build"; })) {
563575
SourceDecision d;
564576
d.subject = "toolchain.build";

‎src/build/progress.cppm‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1378,7 +1378,9 @@ void note_sources(const std::filesystem::path& buildDir) {
13781378
auto colon = group.find(": ");
13791379
if (colon == std::string::npos) continue;
13801380
auto cls = group.substr(0, colon);
1381-
auto it = std::ranges::find(r.sources, cls, &decltype(r.sources)::value_type::first);
1381+
auto it = std::ranges::find_if(r.sources,
1382+
[&](const std::pair<std::string, std::vector<std::string>>& e) {
1383+
return e.first == cls; });
13821384
if (it == r.sources.end()) { r.sources.emplace_back(cls, std::vector<std::string>{}); it = r.sources.end() - 1; }
13831385
std::size_t n = colon + 2;
13841386
while (n < group.size()) {

‎src/doctor.cppm‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1318,8 +1318,9 @@ export int why_report(const std::string& topic, const std::string& features,
13181318
prof.libc, prof.cxxStdlib, prof.arch, prof.os, tc.targetTriple);
13191319
// The reason the decision record states (mcpp#755), not a sentence
13201320
// describing every way a toolchain can be chosen.
1321-
if (auto it = std::ranges::find(ctx->sources, std::string("toolchain.build"),
1322-
&mcpp::build::SourceDecision::subject);
1321+
if (auto it = std::ranges::find_if(ctx->sources,
1322+
[](const mcpp::build::SourceDecision& d) {
1323+
return d.subject == "toolchain.build"; });
13231324
it != ctx->sources.end())
13241325
std::println(" source: {}", mcpp::build::source_tag(*it, ctx->projectRoot));
13251326
if (!ctx->compilerChoice.origin.empty())

0 commit comments

Comments
 (0)