@@ -511,7 +511,10 @@ bool generate_ansi_c_start_function(
511511
512512 record_function_outputs (symbol, init_code, symbol_table);
513513
514- // now call destructor functions (a GCC extension)
514+ // now call destructor functions (a GCC extension); compute required order
515+ // first
516+ std::map<mp_integer, std::list<std::reference_wrapper<const symbolt>>>
517+ destructors_by_priority;
515518
516519 for (const auto &symbol_table_entry : symbol_table.symbols )
517520 {
@@ -525,8 +528,39 @@ bool generate_ansi_c_start_function(
525528 code_type.return_type ().id () == ID_destructor &&
526529 code_type.parameters ().empty ())
527530 {
528- code_function_callt destructor_call (symbol.symbol_expr ());
529- destructor_call.add_source_location () = symbol.location ;
531+ const exprt &priorty = static_cast <const exprt &>(
532+ code_type.return_type ().find (ID_destructor_priority));
533+ if (priorty.id () == ID_default)
534+ destructors_by_priority[1 ].push_back (symbol);
535+ else
536+ {
537+ std::optional<mp_integer> priority = numeric_cast<mp_integer>(priority);
538+ DATA_INVARIANT (
539+ priority.has_value () && *priority >= 0 ,
540+ " destructor priority expected to be non-negative integer" );
541+ destructors_by_priority[-*priority].push_back (symbol);
542+ }
543+ }
544+ }
545+
546+ // append all destructors with priority "default" to the otherwise
547+ // lowest-priority destructor list
548+ if (
549+ destructors_by_priority.size () > 1 &&
550+ std::prev (destructors_by_priority.end ())->first == 1 )
551+ {
552+ auto &dest_list = destructors_by_priority.begin ()->second ;
553+ dest_list.splice (
554+ dest_list.begin (), std::prev (destructors_by_priority.end ())->second );
555+ }
556+
557+ for (const auto &priority_pair : destructors_by_priority)
558+ {
559+ for (const auto &sym_ref : priority_pair.second )
560+ {
561+ const code_typet &code_type = to_code_type (sym_ref.get ().type );
562+ code_function_callt destructor_call{sym_ref.get ().symbol_expr ()};
563+ destructor_call.add_source_location () = sym_ref.get ().location ;
530564 init_code.add (std::move (destructor_call));
531565 }
532566 }
0 commit comments