From 71ed303c27254b6a9f56e99fea9c1ed9d47a048a Mon Sep 17 00:00:00 2001 From: Kp Date: Sat, 4 Sep 2021 12:17:14 +0000 Subject: [PATCH] Fix clang editor medwall build The existing code checks that w.m_ptr is not nullptr before using it. clang's flow analysis is unable to prove that w.m_ptr does not become nullptr after it was first checked, even though `w` is const. This causes clang to include calls to null_pointer_exception::report, which is not instantiated for wall. That in turn causes a link error. Rewrite the code to let clang see that the value tested is the value used, and that no nullptr dereference can happen here. --- similar/editor/medwall.cpp | 71 ++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 34 deletions(-) diff --git a/similar/editor/medwall.cpp b/similar/editor/medwall.cpp index 2a3944bb9..a5dee52d0 100644 --- a/similar/editor/medwall.cpp +++ b/similar/editor/medwall.cpp @@ -495,7 +495,6 @@ window_event_result wall_dialog::callback_handler(const d_event &event) default: break; } - sbyte type; fix DeltaTime; fix64 Temp; int keypress = 0; @@ -519,42 +518,45 @@ window_event_result wall_dialog::callback_handler(const d_event &event) // If we change walls, we need to reset the ui code for all // of the checkboxes that control the wall flags. //------------------------------------------------------------ - if (old_wall_num != w) + if (w) { - if (w) + if (old_wall_num != w) { - ui_checkbox_check(doorFlag[0].get(), w->flags & WALL_DOOR_LOCKED); - ui_checkbox_check(doorFlag[1].get(), w->flags & WALL_DOOR_AUTO); - ui_checkbox_check(doorFlag[2].get(), w->flags & WALL_ILLUSION_OFF); + auto ¤t_wall = w.get_checked_reference(); + const auto wall_flags = current_wall.flags; + const auto wall_keys = current_wall.keys; + ui_checkbox_check(doorFlag[0].get(), wall_flags & WALL_DOOR_LOCKED); + ui_checkbox_check(doorFlag[1].get(), wall_flags & WALL_DOOR_AUTO); + ui_checkbox_check(doorFlag[2].get(), wall_flags & WALL_ILLUSION_OFF); - ui_radio_set_value(*keyFlag[0], w->keys & wall_key::none); - ui_radio_set_value(*keyFlag[1], w->keys & wall_key::blue); - ui_radio_set_value(*keyFlag[2], w->keys & wall_key::red); - ui_radio_set_value(*keyFlag[3], w->keys & wall_key::gold); + ui_radio_set_value(*keyFlag[0], wall_keys & wall_key::none); + ui_radio_set_value(*keyFlag[1], wall_keys & wall_key::blue); + ui_radio_set_value(*keyFlag[2], wall_keys & wall_key::red); + ui_radio_set_value(*keyFlag[3], wall_keys & wall_key::gold); } } - + //------------------------------------------------------------ // If any of the checkboxes that control the wallflags are set, then // update the corresponding wall flag. //------------------------------------------------------------ - if (w && w->type == WALL_DOOR) + if (const auto wp = w.get_unchecked_pointer(); wp && wp->type == WALL_DOOR) { if (GADGET_PRESSED(doorFlag[0].get())) { if (doorFlag[0]->flag == 1) - w->flags |= WALL_DOOR_LOCKED; + wp->flags |= WALL_DOOR_LOCKED; else - w->flags &= ~WALL_DOOR_LOCKED; + wp->flags &= ~WALL_DOOR_LOCKED; rval = window_event_result::handled; } else if (GADGET_PRESSED(doorFlag[1].get())) { if (doorFlag[1]->flag == 1) - w->flags |= WALL_DOOR_AUTO; + wp->flags |= WALL_DOOR_AUTO; else - w->flags &= ~WALL_DOOR_AUTO; + wp->flags &= ~WALL_DOOR_AUTO; rval = window_event_result::handled; } @@ -565,7 +567,7 @@ window_event_result wall_dialog::callback_handler(const d_event &event) range_for (const int i, xrange(4u)) { if (GADGET_PRESSED(keyFlag[i].get())) { - w->keys = static_cast(1 << i); + wp->keys = static_cast(1 << i); rval = window_event_result::handled; } } @@ -576,21 +578,19 @@ window_event_result wall_dialog::callback_handler(const d_event &event) ui_radio_set_value(*i, 0); } - if (w && w->type == WALL_ILLUSION) { + if (const auto wp = w.get_unchecked_pointer(); wp && wp->type == WALL_ILLUSION) + { if (GADGET_PRESSED(doorFlag[2].get())) { + auto &wf = wp->flags; if (doorFlag[2]->flag == 1) - w->flags |= WALL_ILLUSION_OFF; + wf |= WALL_ILLUSION_OFF; else - w->flags &= ~WALL_ILLUSION_OFF; + wf &= ~WALL_ILLUSION_OFF; rval = window_event_result::handled; } } else - for ( int i=2; i < 3; i++ ) - if (doorFlag[i]->flag == 1) - { - doorFlag[i]->flag = 0; // Tells ui that this button isn't checked - } + doorFlag[2]->flag = 0; // Tells ui that this button isn't checked //------------------------------------------------------------ // Draw the wall in the little 64x64 box @@ -602,14 +602,15 @@ window_event_result wall_dialog::callback_handler(const d_event &event) DeltaTime = Temp - time; gr_set_current_canvas(wallViewBox->canvas); - if (w) { - type = w->type; + if (const auto wp = w.get_unchecked_pointer()) + { + const auto type = wp->type; if ((type == WALL_DOOR) || (type == WALL_BLASTABLE)) { if (DeltaTime > ((F1_0*200)/1000)) { framenum++; time = Temp; } - auto &wa = WallAnims[w->clip_num]; + auto &wa = WallAnims[wp->clip_num]; if (framenum >= wa.num_frames) framenum=0; const auto frame = wa.frames[framenum]; @@ -641,9 +642,11 @@ window_event_result wall_dialog::callback_handler(const d_event &event) //------------------------------------------------------------ if (event.type == EVENT_UI_DIALOG_DRAW) { - if (w) { + if (const auto wp = w.get_unchecked_pointer()) + { ui_dprintf_at( MainWindow, 12, 6, "Wall: %hu ", underlying_value(wallnum_t{w})); - switch (w->type) { + switch (wp->type) + { case WALL_NORMAL: ui_dprintf_at( MainWindow, 12, 23, " Type: Normal " ); break; @@ -652,7 +655,7 @@ window_event_result wall_dialog::callback_handler(const d_event &event) break; case WALL_DOOR: ui_dprintf_at( MainWindow, 12, 23, " Type: Door " ); - ui_dputs_at( MainWindow, 223, 6, &WallAnims[w->clip_num].filename[0]); + ui_dputs_at( MainWindow, 223, 6, &WallAnims[wp->clip_num].filename[0]); break; case WALL_ILLUSION: ui_dprintf_at( MainWindow, 12, 23, " Type: Illusion " ); @@ -667,11 +670,11 @@ window_event_result wall_dialog::callback_handler(const d_event &event) ui_dprintf_at( MainWindow, 12, 23, " Type: Unknown " ); break; } - if (w->type != WALL_DOOR) + if (wp->type != WALL_DOOR) ui_dprintf_at( MainWindow, 223, 6, " " ); - ui_dprintf_at( MainWindow, 12, 40, " Clip: %d ", w->clip_num ); - ui_dprintf_at(MainWindow, 12, 57, " Trigger: %d ", underlying_value(w->trigger)); + ui_dprintf_at( MainWindow, 12, 40, " Clip: %d ", wp->clip_num ); + ui_dprintf_at(MainWindow, 12, 57, " Trigger: %d ", underlying_value(wp->trigger)); } else { ui_dprintf_at( MainWindow, 12, 6, "Wall: none "); ui_dprintf_at( MainWindow, 12, 23, " Type: none ");