From db2a696f810e41189bcdf5524696ff3d0cfbe5a9 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 7 Feb 2017 11:40:07 +0200 Subject: Use target:as<> instead of static_cast for target casting --- build2/algorithm.ixx | 4 ++-- build2/bin/rule.cxx | 6 +++--- build2/cc/common.cxx | 4 ++-- build2/cc/compile.cxx | 12 ++++++------ build2/cc/link.cxx | 26 +++++++++++++------------- build2/cc/msvc.cxx | 6 +++--- build2/cc/windows-rpath.cxx | 3 +-- build2/cli/rule | 2 ++ build2/cli/rule.cxx | 6 +++--- build2/install/rule.cxx | 11 +++++------ build2/target | 43 +++++++++++++++++++++++++------------------ build2/test/rule.cxx | 4 ++-- 12 files changed, 67 insertions(+), 60 deletions(-) diff --git a/build2/algorithm.ixx b/build2/algorithm.ixx index 0c171fd..b8c33d4 100644 --- a/build2/algorithm.ixx +++ b/build2/algorithm.ixx @@ -56,8 +56,8 @@ namespace build2 const string* ext, const scope* scope) { - return static_cast ( - search (T::static_type, dir, out, name, ext, scope)); + return search ( + T::static_type, dir, out, name, ext, scope).template as (); } pair diff --git a/build2/bin/rule.cxx b/build2/bin/rule.cxx index a73ad3d..9adb692 100644 --- a/build2/bin/rule.cxx +++ b/build2/bin/rule.cxx @@ -48,7 +48,7 @@ namespace build2 match_result lib_rule:: match (slock& ml, action act, target& xt, const string&) const { - lib& t (static_cast (xt)); + lib& t (xt.as ()); // @@ We have to re-query it on each match_only()! @@ -104,7 +104,7 @@ namespace build2 recipe lib_rule:: apply (slock& ml, action act, target& xt) const { - lib& t (static_cast (xt)); + lib& t (xt.as ()); const match_data& md (t.data ()); const string& type (md.type); @@ -126,7 +126,7 @@ namespace build2 target_state lib_rule:: perform (action act, const target& xt) { - const lib& t (static_cast (xt)); + const lib& t (xt.as ()); const match_data& md (t.data ()); const string& type (md.type); diff --git a/build2/cc/common.cxx b/build2/cc/common.cxx index 654ff53..7b8499c 100644 --- a/build2/cc/common.cxx +++ b/build2/cc/common.cxx @@ -439,7 +439,7 @@ namespace build2 if (const lib* l = xt->is_a ()) xt = &link_member (*l, lo); // Pick liba{} or libs{}. - return static_cast (*xt); + return xt->as (); } // Note that pk's scope should not be NULL (even if dir is absolute). If @@ -563,7 +563,7 @@ namespace build2 trace)); assert (!exist || !p.second); - r = static_cast (&p.first); + r = &p.first.template as (); }; auto search =[&a, &s, diff --git a/build2/cc/compile.cxx b/build2/cc/compile.cxx index 98d1218..5090f11 100644 --- a/build2/cc/compile.cxx +++ b/build2/cc/compile.cxx @@ -115,7 +115,7 @@ namespace build2 continue; process_libraries (bs, lo, sys_lib_dirs, - static_cast (*pt), a, + pt->as (), a, nullptr, nullptr, optf); } } @@ -155,7 +155,7 @@ namespace build2 continue; process_libraries (bs, lo, sys_lib_dirs, - static_cast (*pt), a, + pt->as (), a, nullptr, nullptr, optf); } } @@ -198,7 +198,7 @@ namespace build2 continue; process_libraries (bs, lo, sys_lib_dirs, - static_cast (*pt), a, + pt->as (), a, nullptr, nullptr, optf); } } @@ -208,7 +208,7 @@ namespace build2 { tracer trace (x, "compile::apply"); - file& t (static_cast (xt)); + file& t (xt.as ()); const match_data& md (t.data ()); const scope& bs (t.base_scope ()); @@ -1405,7 +1405,7 @@ namespace build2 target_state compile:: perform_update (action a, const target& xt) const { - const file& t (static_cast (xt)); + const file& t (xt.as ()); // Update prerequisites and determine if any relevant ones render us // out-of-date. Note that currently we treat all the prerequisites @@ -1632,7 +1632,7 @@ namespace build2 target_state compile:: perform_clean (action a, const target& xt) const { - const file& t (static_cast (xt)); + const file& t (xt.as ()); if (cid == "msvc") return clean_extra (a, t, {".d", ".idb", ".pdb"}); diff --git a/build2/cc/link.cxx b/build2/cc/link.cxx index 6c17037..2bdf8c1 100644 --- a/build2/cc/link.cxx +++ b/build2/cc/link.cxx @@ -297,7 +297,7 @@ namespace build2 lk = b; append_ext (lk); - libi& li (static_cast (*ls.member)); + libi& li (ls.member->as ()); lk = li.derive_path (move (lk), tsys == "mingw32" ? "a" : "lib"); } else if (!v.empty ()) @@ -322,7 +322,7 @@ namespace build2 tracer trace (x, "link::apply"); - file& t (static_cast (xt)); + file& t (xt.as ()); const scope& bs (t.base_scope ()); const scope& rs (*bs.root_scope ()); @@ -341,7 +341,7 @@ namespace build2 else t.member = &search (tt, t.dir, t.out, t.name, nullptr, nullptr); - file& r (static_cast (*t.member)); + file& r (t.member->as ()); r.recipe (a, group_recipe); return r; }; @@ -541,7 +541,7 @@ namespace build2 // if (group) { - obj& o (static_cast (ot)); + obj& o (ot.as ()); switch (lt) { @@ -680,7 +680,7 @@ namespace build2 // (see search_library() for details). // if (win && f->member != nullptr && f->is_a ()) - f = static_cast (f->member.get ()); + f = &f->member->as (); args.push_back (relative (f->path ()).string ()); } @@ -727,7 +727,7 @@ namespace build2 // (see search_library() for details). // if (win && f->member != nullptr && f->is_a ()) - f = static_cast (f->member.get ()); + f = &f->member->as (); cs.append (f->path ().string ()); } @@ -893,11 +893,11 @@ namespace build2 { tracer trace (x, "link::perform_update"); + const file& t (xt.as ()); + auto oop (a.outer_operation ()); bool for_install (oop == install_id || oop == uninstall_id); - const file& t (static_cast (xt)); - const scope& bs (t.base_scope ()); const scope& rs (*bs.root_scope ()); @@ -1369,7 +1369,7 @@ namespace build2 // derived from the import library by changing the extension. // Lucky for us -- there is no option to name it. // - auto& imp (static_cast (*t.member)); + auto& imp (t.member->as ()); out2 = "/IMPLIB:" + relative (imp.path ()).string (); args.push_back (out2.c_str ()); } @@ -1379,9 +1379,9 @@ namespace build2 // if (find_option ("/DEBUG", args, true)) { + auto& pdb ( - static_cast ( - lt == otype::e ? *t.member : *t.member->member)); + (lt == otype::e ? t.member : t.member->member)->as ()); out1 = "/PDB:" + relative (pdb.path ()).string (); args.push_back (out1.c_str ()); } @@ -1415,7 +1415,7 @@ namespace build2 // On Windows libs{} is the DLL and its first ad hoc group // member is the import library. // - auto& imp (static_cast (*t.member)); + auto& imp (t.member->as ()); out = "-Wl,--out-implib=" + relative (imp.path ()).string (); args.push_back (out.c_str ()); } @@ -1629,7 +1629,7 @@ namespace build2 target_state link:: perform_clean (action a, const target& xt) const { - const file& t (static_cast (xt)); + const file& t (xt.as ()); switch (link_type (t)) { diff --git a/build2/cc/msvc.cxx b/build2/cc/msvc.cxx index 86a7d38..94064ca 100644 --- a/build2/cc/msvc.cxx +++ b/build2/cc/msvc.cxx @@ -69,7 +69,7 @@ namespace build2 // if (lt == otype::s && l.compare (0, 3, " ") == 0) { - path imp (static_cast (*t.member).path ().leaf ()); + path imp (t.member->as ().path ().leaf ()); if (l.find (imp.string ()) != string::npos && l.find (imp.base ().string () + ".exp") != string::npos) @@ -276,7 +276,7 @@ namespace build2 true, // Implied. trace)); assert (!exist || !p.second); - T& t (static_cast (p.first)); + T& t (p.first.template as ()); if (t.path ().empty ()) t.path (move (f)); @@ -340,7 +340,7 @@ namespace build2 true, // Implied. trace)); assert (!exist || !p.second); - r = static_cast (&p.first); + r = &p.first.as (); if (r->member == nullptr) { diff --git a/build2/cc/windows-rpath.cxx b/build2/cc/windows-rpath.cxx index 94b1145..46a3d3a 100644 --- a/build2/cc/windows-rpath.cxx +++ b/build2/cc/windows-rpath.cxx @@ -137,8 +137,7 @@ namespace build2 // const string* pdb ( l->member != nullptr && l->member->member != nullptr - ? &static_cast ( - *l->member->member).path ().string () + ? &l->member->member->as ().path ().string () : nullptr); r.insert (windows_dll {f, pdb, string ()}); diff --git a/build2/cli/rule b/build2/cli/rule index 1fbbde4..03fd471 100644 --- a/build2/cli/rule +++ b/build2/cli/rule @@ -14,6 +14,8 @@ namespace build2 { namespace cli { + // @@ Redo as two separate rules? + // class compile: public rule { public: diff --git a/build2/cli/rule.cxx b/build2/cli/rule.cxx index 5dcec99..7928c5c 100644 --- a/build2/cli/rule.cxx +++ b/build2/cli/rule.cxx @@ -199,7 +199,7 @@ namespace build2 } else { - cli_cxx& g (static_cast (*xt.group)); + cli_cxx& g (xt.group->as ()); build2::match (ml, a, g); return group_recipe; // Execute the group's recipe. } @@ -230,7 +230,7 @@ namespace build2 target_state compile:: perform_update (action a, const target& xt) { - const cli_cxx& t (static_cast (xt)); + const cli_cxx& t (xt.as ()); // Update prerequisites and determine if any relevant ones render us // out-of-date. Note that currently we treat all the prerequisites @@ -322,7 +322,7 @@ namespace build2 target_state compile:: perform_clean (action a, const target& xt) { - const cli_cxx& t (static_cast (xt)); + const cli_cxx& t (xt.as ()); // The reverse order of update: first delete the files, then clean // prerequisites. Also update timestamp in case there are operations diff --git a/build2/install/rule.cxx b/build2/install/rule.cxx index 3be7eef..3a5bd3d 100644 --- a/build2/install/rule.cxx +++ b/build2/install/rule.cxx @@ -614,7 +614,7 @@ namespace build2 target_state file_rule:: perform_install (action a, const target& xt) const { - const file& t (static_cast (xt)); + const file& t (xt.as ()); assert (!t.path ().empty ()); // Should have been assigned by update. auto install_target = [this] (const file& t, const path& p, bool verbose) @@ -663,7 +663,7 @@ namespace build2 for (const target* m (t.member); m != nullptr; m = m->member) { if (const path* p = lookup_install (*m, "install")) - install_target (static_cast (*m), *p, false); + install_target (m->as (), *p, false); } // Finally install the target itself (since we got here we know the @@ -872,7 +872,7 @@ namespace build2 target_state file_rule:: perform_uninstall (action a, const target& xt) const { - const file& t (static_cast (xt)); + const file& t (xt.as ()); assert (!t.path ().empty ()); // Should have been assigned by update. auto uninstall_target = [this] ( @@ -930,9 +930,8 @@ namespace build2 for (const target* m (t.member); m != nullptr; m = m->member) { if (const path* p = lookup_install (*m, "install")) - r |= uninstall_target (static_cast (*m), - *p, - r != target_state::changed); + r |= uninstall_target ( + m->as (), *p, r != target_state::changed); } // Finally handle installable prerequisites. diff --git a/build2/target b/build2/target index 2eb6a2c..48c80e7 100644 --- a/build2/target +++ b/build2/target @@ -112,8 +112,6 @@ namespace build2 optional* ext_; // Reference to value in target_key. public: - using action_type = build2::action; - // For targets that are in the src tree of a project we also keep the // corresponding out directory. As a result we may end up with multiple // targets for the same file if we are building multiple configurations of @@ -240,6 +238,8 @@ namespace build2 } public: + using action_type = build2::action; + // Reset the target before matching it to a rule. The default // implementation clears the auxilary data and prerequisite_targets. // @@ -540,9 +540,12 @@ namespace build2 private: recipe_type recipe_; - // Target type info. + // Target type info and casting. // public: + bool + is_a (const target_type& tt) const {return type ().is_a (tt);} + template T* is_a () {return dynamic_cast (this);} @@ -551,8 +554,15 @@ namespace build2 const T* is_a () const {return dynamic_cast (this);} - bool - is_a (const target_type& tt) const {return type ().is_a (tt);} + // Unchecked cast. + // + template + T& + as () {return static_cast (*this);} + + template + const T& + as () const {return static_cast (*this);} // Dynamic derivation to support define. // @@ -1074,14 +1084,13 @@ namespace build2 optional ext, tracer& t) { - return static_cast ( - insert (tt, - move (dir), - move (out), - move (name), - move (ext), - true, - t).first); + return insert (tt, + move (dir), + move (out), + move (name), + move (ext), + true, + t).first.template as (); } template @@ -1092,8 +1101,7 @@ namespace build2 const optional& ext, tracer& t) { - return static_cast ( - insert (T::static_type, dir, out, name, ext, true, t).first); + return insert (T::static_type, dir, out, name, ext, t); } template @@ -1103,8 +1111,7 @@ namespace build2 const string& name, tracer& t) { - return static_cast ( - insert (T::static_type, dir, out, name, nullopt, true, t).first); + return insert (dir, out, name, nullopt, t); } // Note: not MT-safe so can only be used during serial execution. @@ -1149,7 +1156,7 @@ namespace build2 mtime (bool load = true) const { const mtime_target& t (state_ == target_state::group - ? static_cast (*group) + ? group->as () : *this); if (load && t.mtime_ == timestamp_unknown) diff --git a/build2/test/rule.cxx b/build2/test/rule.cxx index 38c24f9..35302e1 100644 --- a/build2/test/rule.cxx +++ b/build2/test/rule.cxx @@ -640,7 +640,7 @@ namespace build2 auto& pts (tt.prerequisite_targets); if (pts.size () != 0 && pts[0] != nullptr) { - const file& it (static_cast (*pts[0])); + const file& it (pts[0]->as ()); assert (!it.path ().empty ()); // Should have been assigned by update. args.push_back (it.path ().string ().c_str ()); } @@ -660,7 +660,7 @@ namespace build2 process_path dpp; if (pts.size () != 0 && pts[1] != nullptr) { - const file& ot (static_cast (*pts[1])); + const file& ot (pts[1]->as ()); assert (!ot.path ().empty ()); // Should have been assigned by update. dpp = run_search (dp, true); -- cgit v1.1