From 1821a11704143a89581b26e285d968230b86a8ac Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 10 Feb 2017 17:27:55 +0200 Subject: Track variable value modifications --- build2/file.cxx | 2 +- build2/scope.cxx | 2 +- build2/target.cxx | 2 +- build2/test/script/script.cxx | 2 +- build2/variable | 18 ++++++++++++++++-- build2/variable.cxx | 22 +++++++++------------- 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 (*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 (*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 (*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, @@ -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 (*l.value)); + static_cast (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 (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, bool> variable_map:: @@ -1205,6 +1199,8 @@ namespace build2 typify (r, var); } + r.version++; + return make_pair (reference_wrapper (r), p.second); } -- cgit v1.1