aboutsummaryrefslogtreecommitdiff
path: root/libbuild2
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2020-08-10 13:40:27 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2020-08-10 13:40:27 +0200
commit9d8ba565d1fd454369506a525997fceb5adae349 (patch)
treeda10d155660ff59cfd82ee7bb45d4503e26c198d /libbuild2
parent600da2b97e937b9c96791c291cb5e08cd8526bdd (diff)
Allow holes in group_view array
Diffstat (limited to 'libbuild2')
-rw-r--r--libbuild2/algorithm.cxx10
-rw-r--r--libbuild2/target.hxx8
-rw-r--r--libbuild2/target.ixx35
-rw-r--r--libbuild2/target.txx10
4 files changed, 50 insertions, 13 deletions
diff --git a/libbuild2/algorithm.cxx b/libbuild2/algorithm.cxx
index e1f30e0..75540ff 100644
--- a/libbuild2/algorithm.cxx
+++ b/libbuild2/algorithm.cxx
@@ -2390,8 +2390,16 @@ namespace build2
group_view gv (g.group_members (a));
if (gv.count != 0)
{
- ep = gv.members[0]->as<file> ().path () + ".d";
+ for (size_t i (0); i != gv.count; ++i)
+ {
+ if (const target* m = gv.members[i])
+ {
+ ep = m->as<file> ().path () + ".d";
+ break;
+ }
+ }
+ assert (!ep.empty ());
if (rmfile (ctx, ep, 3))
er = target_state::changed;
}
diff --git a/libbuild2/target.hxx b/libbuild2/target.hxx
index 55b8270..17a99d3 100644
--- a/libbuild2/target.hxx
+++ b/libbuild2/target.hxx
@@ -55,6 +55,14 @@ namespace build2
// A view of target group members.
//
+ // Note that the members array may have "holes" (NULL pointers) and count is
+ // the number of elements in this array (and not necessarily the number of
+ // group members).
+ //
+ // Note that members being NULL and count being 0 have different meaning:
+ // the former means group members are not known while the latter means it's
+ // an empty group.
+ //
struct group_view
{
const target* const* members; // NULL means not yet known.
diff --git a/libbuild2/target.ixx b/libbuild2/target.ixx
index 94c54c0..f9db558 100644
--- a/libbuild2/target.ixx
+++ b/libbuild2/target.ixx
@@ -399,9 +399,14 @@ namespace build2
if (k_ == nullptr && g_.count != 0) // Iterating over a normal group.
{
- if (g_.members == nullptr || // Special case, see leave_group().
- ++j_ > g_.count)
+ if (g_.members == nullptr) // Special case, see leave_group().
g_.count = 0;
+ else
+ {
+ for (++j_; j_ <= g_.count && g_.members[j_ - 1] == nullptr; ++j_) ;
+ if (j_ > g_.count)
+ g_.count = 0;
+ }
}
if (k_ == nullptr && g_.count == 0) // Iterating over the range.
@@ -443,8 +448,11 @@ namespace build2
return false;
}
- if (g_.count != 0) // Group is not empty.
- j_ = 0; // Account for the increment that will follow.
+ // Note: 0-based to account for the increment that will follow.
+ //
+ for (j_ = 0; j_ != g_.count && g_.members[j_] == nullptr; ++j_) ;
+ if (j_ == g_.count)
+ g_.count = 0;
}
return true;
@@ -474,10 +482,21 @@ namespace build2
inline bool prerequisite_members_range<T>::iterator::
group () const
{
- return
- k_ != nullptr ? k_->adhoc_member != nullptr : /* ad hoc */
- g_.count != 0 ? g_.members != nullptr && j_ < g_.count : /* explicit */
- false;
+ // Ad hoc.
+ //
+ if (k_ != nullptr)
+ return k_->adhoc_member;
+
+ // Explicit.
+ //
+ if (g_.count != 0 && g_.members != nullptr)
+ {
+ size_t j (j_ + 1);
+ for (; j <= g_.count && g_.members[j - 1] == nullptr; ++j) ;
+ return j <= g_.count;
+ }
+
+ return false;
}
inline auto
diff --git a/libbuild2/target.txx b/libbuild2/target.txx
index 777653a..d304daa 100644
--- a/libbuild2/target.txx
+++ b/libbuild2/target.txx
@@ -28,11 +28,13 @@ namespace build2
return;
}
- if (g_.count != 0) // Skip empty see through groups.
- {
- j_ = 1; // Start from the first group member.
+ // Skip empty see through groups.
+ //
+ for (j_ = 1; j_ <= g_.count && g_.members[j_ - 1] == nullptr; ++j_) ;
+ if (j_ <= g_.count)
break;
- }
+
+ g_.count = 0;
}
while (++i_ != r_->e_ && i_->type.see_through);
}