From 2dd1f9fa5a7427096b74aa85258ec2feeb93c104 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 1 Jun 2023 12:22:26 +0200 Subject: Diagnose null include, operation-specific variable values While assigning null directly is unlikely, it's fairly easy via a variable expansion. Real-world example: ./: exe{tensor}: include = $config.Eigen.unsupported --- libbuild2/target.cxx | 74 ++++++++++++++++++++++++++++++++-------------------- libbuild2/target.hxx | 4 +-- 2 files changed, 47 insertions(+), 31 deletions(-) diff --git a/libbuild2/target.cxx b/libbuild2/target.cxx index 6b2c702..4634688 100644 --- a/libbuild2/target.cxx +++ b/libbuild2/target.cxx @@ -566,16 +566,25 @@ namespace build2 context& ctx (t.ctx); include_type r (include_type::normal); - - if (const string* v = cast_null (p.vars[ctx.var_include])) { - if (*v == "false") r = include_type::excluded; - else if (*v == "true") r = include_type::normal; - else if (*v == "adhoc") r = include_type::adhoc; - else if (*v == "posthoc") r = include_type::posthoc; - else - fail << "invalid " << *ctx.var_include << " variable value " - << "'" << *v << "' specified for prerequisite " << p; + lookup l (p.vars[ctx.var_include]); + + if (l.defined ()) + { + if (l->null) + fail << "null " << *ctx.var_include << " variable value specified " + << "for prerequisite " << p; + + const string& v (cast (*l)); + + if (v == "false") r = include_type::excluded; + else if (v == "true") r = include_type::normal; + else if (v == "adhoc") r = include_type::adhoc; + else if (v == "posthoc") r = include_type::posthoc; + else + fail << "invalid " << *ctx.var_include << " variable value '" + << v << "' specified for prerequisite " << p; + } } // Handle operation-specific override (see var_include documentation @@ -601,31 +610,40 @@ namespace build2 ? ctx.current_outer_oif : ctx.current_inner_oif)->id].ovar; - if (ovar != nullptr && (l = p.vars[*ovar])) + if (ovar != nullptr) { - // Maybe we should optimize this for the common cases (bool, path, - // name)? But then again we don't expect many such overrides. Plus - // will complicate the diagnostics below. - // - ns = reverse (*l, storage, true /* reduce */); + l = p.vars[*ovar]; - if (ns.size () == 1) + if (l.defined ()) { - const name& n (ns[0]); + if (l->null) + fail << "null " << *ovar << " variable value specified for " + << "prerequisite " << p; + + // Maybe we should optimize this for the common cases (bool, path, + // name)? But then again we don't expect many such overrides. Plus + // will complicate the diagnostics below. + // + ns = reverse (*l, storage, true /* reduce */); - if (n.simple ()) + if (ns.size () == 1) { - const string& v (n.value); + const name& n (ns[0]); - if (v == "false") - r1 = false; - else if (v == "true") - r1 = true; + if (n.simple ()) + { + const string& v (n.value); + + if (v == "false") + r1 = false; + else if (v == "true") + r1 = true; + } } - } - if (r1 && !*r1) - r = include_type::excluded; + if (r1 && !*r1) + r = include_type::excluded; + } } } @@ -646,8 +664,8 @@ namespace build2 // Note: we have to delay this until the meta-operation callback above // had a chance to override it. // - fail << "unrecognized " << *ovar << " variable value " - << "'" << ns << "' specified for prerequisite " << p; + fail << "unrecognized " << *ovar << " variable value '" << ns + << "' specified for prerequisite " << p; } } diff --git a/libbuild2/target.hxx b/libbuild2/target.hxx index d01e8b7..d4ad780 100644 --- a/libbuild2/target.hxx +++ b/libbuild2/target.hxx @@ -1472,9 +1472,7 @@ namespace build2 } include_type - include (action, const target&, - const prerequisite_member&, - lookup* = nullptr); + include (action, const target&, const prerequisite_member&, lookup* = nullptr); // A "range" that presents a sequence of prerequisites (e.g., from // group_prerequisites()) as a sequence of prerequisite_member's. For each -- cgit v1.1