aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2017-02-10 17:27:55 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2017-02-13 12:42:42 +0200
commit1821a11704143a89581b26e285d968230b86a8ac (patch)
treebee33a148ec205157195fd55fd8a0d24db4fc3d2
parentdbd30777d1c60bdcdff226b5f97582dba0bba4ba (diff)
Track variable value modifications
-rw-r--r--build2/file.cxx2
-rw-r--r--build2/scope.cxx2
-rw-r--r--build2/target.cxx2
-rw-r--r--build2/test/script/script.cxx2
-rw-r--r--build2/variable18
-rw-r--r--build2/variable.cxx22
6 files changed, 29 insertions, 19 deletions
diff --git a/build2/file.cxx b/build2/file.cxx
index c403eea..06910dc 100644
--- a/build2/file.cxx
+++ b/build2/file.cxx
@@ -339,7 +339,7 @@ namespace build2
temp_scope tmp (s.global ());
p.parse_variable (lex, tmp, var, tt);
- value* v (tmp.vars.find (var));
+ value* v (tmp.vars.find_to_modify (var));
assert (v != nullptr);
// Steal the value, the scope is going away.
diff --git a/build2/scope.cxx b/build2/scope.cxx
index 0b76647..aaa0077 100644
--- a/build2/scope.cxx
+++ b/build2/scope.cxx
@@ -507,7 +507,7 @@ namespace build2
lookup l (find_original (var).first);
if (l.defined () && l.belongs (*this)) // Existing var in this scope.
- return const_cast<value&> (*l); // Ok since this is original.
+ return vars.modify (l); // Ok since this is original.
value& r (assign (var)); // NULL.
diff --git a/build2/target.cxx b/build2/target.cxx
index a6f7ef4..5389ec9 100644
--- a/build2/target.cxx
+++ b/build2/target.cxx
@@ -223,7 +223,7 @@ namespace build2
lookup l (find_original (var).first);
if (l.defined () && l.belongs (*this)) // Existing var in this target.
- return const_cast<value&> (*l); // Ok since this is original.
+ return vars.modify (l); // Ok since this is original.
value& r (assign (var)); // NULL.
diff --git a/build2/test/script/script.cxx b/build2/test/script/script.cxx
index bc816d7..0586377 100644
--- a/build2/test/script/script.cxx
+++ b/build2/test/script/script.cxx
@@ -659,7 +659,7 @@ namespace build2
lookup l (find (var));
if (l.defined () && l.belongs (*this)) // Existing var in this scope.
- return const_cast<value&> (*l);
+ return vars.modify (l);
value& r (assign (var)); // NULL.
diff --git a/build2/variable b/build2/variable
index e78b074..40470fa 100644
--- a/build2/variable
+++ b/build2/variable
@@ -1047,7 +1047,8 @@ namespace build2
{
using value::value;
- size_t generation; // load_generation of this value (global only).
+ size_t version = 0; // Incremented on each modification (override cache).
+ size_t generation; // load_generation of this value (global state only).
};
using map_type = butl::prefix_map<reference_wrapper<const variable>,
@@ -1107,7 +1108,20 @@ namespace build2
find (const variable&, bool typed = true) const;
value_data*
- find (const variable&, bool typed = true);
+ find_to_modify (const variable&, bool typed = true);
+
+ // Convert a lookup pointing to a value belonging to this variable map
+ // to its non-const version. Note that this is only safe on the original
+ // values (see find_original()).
+ //
+ value&
+ modify (const lookup& l)
+ {
+ assert (l.vars == this);
+ value& r (const_cast<value&> (*l.value));
+ static_cast<value_data&> (r).version++;
+ return r;
+ }
// Return a value suitable for assignment. See scope for details.
//
diff --git a/build2/variable.cxx b/build2/variable.cxx
index 48f3345..7e105e6 100644
--- a/build2/variable.cxx
+++ b/build2/variable.cxx
@@ -1146,6 +1146,8 @@ namespace build2
load_generation == 0 ||
v.generation == load_generation);
+ // We assume typification is not modification.
+ //
build2::typify (v, *var.type, &var);
}
@@ -1169,22 +1171,14 @@ namespace build2
}
auto variable_map::
- find (const variable& var, bool typed) -> value_data*
+ find_to_modify (const variable& var, bool typed) -> value_data*
{
- auto i (m_.find (var));
- value_data* r (i != m_.end () ? &i->second : nullptr);
+ auto* r (const_cast<value_data*> (find (var, typed)));
- // First access after being assigned a type?
- //
- if (r != nullptr && typed && var.type != nullptr && r->type != var.type)
- {
- // All values shall be typed during load.
- //
- assert (!global_ || phase == run_phase::load);
- typify (*r, var);
- }
+ if (r != nullptr)
+ r->version++;
- return r;
+ return r;
}
pair<reference_wrapper<value>, bool> variable_map::
@@ -1205,6 +1199,8 @@ namespace build2
typify (r, var);
}
+ r.version++;
+
return make_pair (reference_wrapper<value> (r), p.second);
}