https://gcc.gnu.org/bugzilla/show_bug.cgi?id=123880

            Bug ID: 123880
           Summary: [16 Regression] ICE with -fanalyzer in
                    ana::exploded_node::on_throw
           Product: gcc
           Version: 16.0
            Status: UNCONFIRMED
          Keywords: ice-on-valid-code
          Severity: normal
          Priority: P3
         Component: analyzer
          Assignee: dmalcolm at gcc dot gnu.org
          Reporter: dmalcolm at gcc dot gnu.org
  Target Milestone: ---

(reported downstream at https://bugzilla.redhat.com/show_bug.cgi?id=2435317)

This C++ code crashes -fanalyzer:

// this is the source code...

#include <generator>
#include <iostream>

template<typename T> struct Tree
{
    T value;
    Tree *left{}, *right{};

    std::generator<const T &> traverse_preorder() const
    {
        co_yield value;
        if (left)
            co_yield std::ranges::elements_of(left->traverse_preorder());
        if (right)
            co_yield std::ranges::elements_of(right->traverse_preorder());
    }
};

int main()
{
    Tree<char> tree[]
    {
                                    {'D', tree + 1, tree + 2},
        //                            │
        //            ┌───────────────┴────────────────┐
        //            │                                │
                    {'B', tree + 3, tree + 4},       {'F', tree + 5, tree + 6},
        //            │                                │
        //  ┌─────────┴─────────────┐      ┌───────────┴─────────────┐
        //  │                       │      │                         │
          {'A'},                  {'C'}, {'E'},                    {'G'}
    };

    std::cout << " Preorder: ";
    for (char x : tree->traverse_preorder())
        std::cout << x << ' ';
    std::cout << '\n';
}

Crashes with trunk with: -fanalyzer -std=c++23: https://godbolt.org/z/Ez7xnbddf

(gdb) bt
#0  fancy_abort (file=0x2f47ec8 "../../src/gcc/analyzer/engine.cc", line=1814,
function=0x2f4858e "on_throw")
    at ../../src/gcc/diagnostics/context.cc:1779
#1  0x0000000001c9e893 in ana::exploded_node::on_throw
(this=<ana::exploded_node 0x67b5360 (EN 6478)>, eg=..., 
    throw_call=..., after_throw_point=..., new_state=0x7fffffff7cf0,
is_rethrow=true, ctxt=0x7fffffff7c80)
    at ../../src/gcc/analyzer/engine.cc:1814
#2  0x0000000001d09f15 in ana::cxa_throw_op::execute (this=0x42ee0b0,
op_ctxt=...)
    at ../../src/gcc/analyzer/ops.cc:1205
#3  0x0000000001ca4162 in ana::exploded_graph::process_node
(this=0x7fffffff8140, 
    node=<ana::exploded_node 0x67b5360 (EN 6478)>) at
../../src/gcc/analyzer/engine.cc:3768
#4  0x0000000001ca2e76 in ana::exploded_graph::process_worklist
(this=0x7fffffff8140)
    at ../../src/gcc/analyzer/engine.cc:3397
#5  0x0000000001ca7482 in ana::impl_run_checkers (logger=0x0) at
../../src/gcc/analyzer/engine.cc:5257
#6  0x0000000001ca78ce in ana::run_checkers () at
../../src/gcc/analyzer/engine.cc:5348
#7  0x0000000001c9b207 in (anonymous namespace)::pass_analyzer::execute
(this=0x3e6d1b0)
    at ../../src/gcc/analyzer/analyzer-pass.cc:81
#8  0x00000000016f8b29 in execute_one_pass (pass=<opt_pass* 0x3e6d1b0
"analyzer"(93)>)
    at ../../src/gcc/passes.cc:2656
#9  0x0000000001702105 in execute_ipa_pass_list (pass=<opt_pass* 0x3e6d1b0
"analyzer"(93)>)
    at ../../src/gcc/passes.cc:3118
#10 0x000000000129b510 in ipa_passes () at ../../src/gcc/cgraphunit.cc:2299
#11 symbol_table::compile (this=0x7fffea648000) at
../../src/gcc/cgraphunit.cc:2364
#12 symbol_table::compile (this=0x7fffea648000) at
../../src/gcc/cgraphunit.cc:2340
#13 0x000000000129e505 in symbol_table::finalize_compilation_unit
(this=0x7fffea648000)
    at ../../src/gcc/cgraphunit.cc:2623
#14 0x000000000182c104 in compile_file () at ../../src/gcc/toplev.cc:482
#15 0x0000000000dfb447 in do_compile () at ../../src/gcc/toplev.cc:2225
#16 toplev::main (this=this@entry=0x7fffffffdb7e, argc=<optimized out>,
argc@entry=29, argv=<optimized out>, 
    argv@entry=0x7fffffffdc88) at ../../src/gcc/toplev.cc:2390
#17 0x0000000000dfd5b5 in main (argc=29, argv=0x7fffffffdc88) at
../../src/gcc/main.cc:39

where this assertion is failing:

 * rhbz#2435317 ("error interno del compilador: en on_throw, en
analyzer/engine.cc:1814")
#1  0x0000000001c9e893 in ana::exploded_node::on_throw
(this=<ana::exploded_node 0x67b5360 (EN 6478)>, eg=..., 
    throw_call=..., after_throw_point=..., new_state=0x7fffffff7cf0,
is_rethrow=true, ctxt=0x7fffffff7c80)
    at ../../src/gcc/analyzer/engine.cc:1814
li1814        gcc_assert (eh_node);
(gdb) list
1809      /* Create an enode and eedge for the "throw".  */
1810      tree type = NULL_TREE;
1811      if (is_rethrow)
1812        {
1813          const exception_node *eh_node =
model->get_current_caught_exception ();
1814          gcc_assert (eh_node);
1815          type = eh_node->maybe_get_type ();
1816        }
1817      else
1818        {

(gdb) p eh_node
$1 = (const ana::exception_node *) 0x0

(gdb) call model->dump()
Region Model
├─ Current Frame: frame: ‘std::__gen::_Promise_erased<const
char&>::unhandled_exception’@1
├─ Store
│  ├─ m_called_unknown_fn: false
│  ╰─ root region
│     ╰─ (*INIT_VAL(this_3(D))):  (ESCAPED)
╰─ Constraints
   ├─ Equivalence class ec0
   │  ╰─ &CAST_REG(‘const struct _Subyield_state’,
(*INIT_VAL(this_3(D))).std::__gen::_Promise_erased<const
char&>::_Subyield_state std::__gen::_Promise_erased<const
char&>::_M_nest).std::variant<std::__gen::_Promise_erased<const
char&>::_Subyield_state::_Bottom_frame, std::__gen::_Promise_erased<const
char&>::_Subyield_state::_Frame> std::__gen::_Promise_erased<const
char&>::_Subyield_state::_M_stack
   ├─ Equivalence class ec1
   │  ╰─ &(*INIT_VAL(this_3(D))).std::__gen::_Promise_erased<const
char&>::_Subyield_state std::__gen::_Promise_erased<const char&>::_M_nest
   ├─ Equivalence class ec2
   │  ├─ (void *)0B
   │  ╰─ ‘0B’
   ├─ Equivalence class ec3
   │  ╰─ INIT_VAL(this_3(D))
   ├─ ec0: {&CAST_REG(‘const struct _Subyield_state’,
(*INIT_VAL(this_3(D))).std::__gen::_Promise_erased<const
char&>::_Subyield_state std::__gen::_Promise_erased<const
char&>::_M_nest).std::variant<std::__gen::_Promise_erased<const
char&>::_Subyield_state::_Bottom_frame, std::__gen::_Promise_erased<const
char&>::_Subyield_state::_Frame> std::__gen::_Promise_erased<const
char&>::_Subyield_state::_M_stack} != ec2: {(void *)0B == [m_constant]‘0B’}
   ├─ ec1: {&(*INIT_VAL(this_3(D))).std::__gen::_Promise_erased<const
char&>::_Subyield_state std::__gen::_Promise_erased<const char&>::_M_nest} !=
ec2: {(void *)0B == [m_constant]‘0B’}
   ╰─ ec3: {INIT_VAL(this_3(D))} != ec2: {(void *)0B == [m_constant]‘0B’}

Reply via email to