diff options
author | John Hodge <tpg@ucc.asn.au> | 2017-11-21 20:47:17 +0800 |
---|---|---|
committer | John Hodge <tpg@ucc.asn.au> | 2017-11-21 20:47:17 +0800 |
commit | 33bf75d5b26248950757f3b580337d6db271b8b1 (patch) | |
tree | cb654bc893f6f98d3f9ca99b1eebbf32fb5f5583 /src | |
parent | a733ee610f0935867bfee93c03e20b483d249aa4 (diff) | |
download | mrust-33bf75d5b26248950757f3b580337d6db271b8b1.tar.gz |
MIR Gen - Fix use-after-move when partially moved in one arm and optionally moved in another
Diffstat (limited to 'src')
-rw-r--r-- | src/mir/from_hir.hpp | 1 | ||||
-rw-r--r-- | src/mir/mir_builder.cpp | 17 |
2 files changed, 17 insertions, 1 deletions
diff --git a/src/mir/from_hir.hpp b/src/mir/from_hir.hpp index c4be91a2..79e71196 100644 --- a/src/mir/from_hir.hpp +++ b/src/mir/from_hir.hpp @@ -79,6 +79,7 @@ extern ::std::ostream& operator<<(::std::ostream& os, const VarState& x); struct SplitArm { bool has_early_terminated = false; bool always_early_terminated = false; // Populated on completion + //BasicBlockId source_block; ::std::map<unsigned int, VarState> states; ::std::map<unsigned int, VarState> arg_states; }; diff --git a/src/mir/mir_builder.cpp b/src/mir/mir_builder.cpp index 5776ebcf..93c4a10d 100644 --- a/src/mir/mir_builder.cpp +++ b/src/mir/mir_builder.cpp @@ -374,7 +374,7 @@ void MirBuilder::push_stmt_set_dropflag_default(const Span& sp, unsigned int idx void MirBuilder::push_stmt(const Span& sp, ::MIR::Statement stmt) { ASSERT_BUG(sp, m_block_active, "Pushing statement with no active block"); - DEBUG(stmt); + DEBUG("BB" << m_current_block << " += " << stmt); m_output.blocks.at(m_current_block).statements.push_back( mv$(stmt) ); } @@ -1219,11 +1219,26 @@ namespace is_enum = ty.m_data.is_Path() && ty.m_data.as_Path().binding.is_Enum(); }); // Create a Partial filled with copies of the Optional + // TODO: This can lead to contradictions when one field is moved and another not. + // - Need to allocate a new drop flag and handle the case where old_state is the state before the + // split (and hence the default state of this new drop flag has to be the original state) + // > Could store reference to start BB and assign into it? + // > Can't it not be from before the split, because that would be a move when not known-valid? + // > Re-assign and partial drop. { ::std::vector<VarState> inner; inner.reserve( nse.inner_states.size() ); for(size_t i = 0; i < nse.inner_states.size(); i ++) + { +#if 1 + auto new_flag = builder.new_drop_flag(builder.get_drop_flag_default(sp, old_state.as_Optional())); + builder.push_stmt_set_dropflag_other(sp, new_flag, old_state.as_Optional()); + // TODO: Move this assignment to the source block. + inner.push_back(VarState::make_Optional( new_flag )); +#else inner.push_back(old_state.clone()); +#endif + } old_state = VarState::make_Partial({ mv$(inner) }); } auto& ose = old_state.as_Partial(); |