|
ESBMC
Efficient SMT-based Context-Bounded Model Checker
|
Closed-world numeric type-id registry for symbolic exception dispatch (issue #5075). More...
#include <exception_typeid.h>
Public Member Functions | |
| exception_typeidt ()=default | |
| Empty registry (populate with register_chain). | |
| exception_typeidt (const namespacet &ns) | |
Seed the table from every type symbol's "bases" metadata reachable through ns; register_chain then adds throw-list ancestry on top. | |
| void | register_chain (const std::vector< irep_idt > &chain) |
| Ingest an exception type's ancestry from a THROW's exception_list (front = dynamic type, rest = its flattened transitive bases). | |
| unsigned | id_of (const irep_idt &name) |
Stable id for name. | |
| bool | is_registered (const irep_idt &name) const |
True iff name is an actual program type seen in a throw list (not a primitive #cpp_type, opaque, or lazily-minted name). | |
| bool | is_subtype (const irep_idt &thrown, const irep_idt &caught) const |
Reflexive-transitive subtype test: true iff thrown equals caught or derives from it transitively through the bases graph. | |
| std::set< unsigned > | concrete_subtype_ids (const irep_idt &caught) const |
| { id_of(T) : T <: caught } over all registered program types — the right-hand side of the catch-match guard. | |
| std::vector< std::pair< irep_idt, unsigned > > | concrete_subtypes (const irep_idt &caught) const |
| { (T, id_of(T)) : T <: caught } over all registered program types. | |
| std::size_t | size () const |
| Number of registered program types (excludes lazily-added unknowns). | |
Static Public Attributes | |
| static constexpr unsigned | no_type = 0 |
| Reserved id meaning "no in-flight exception type". | |
Closed-world numeric type-id registry for symbolic exception dispatch (issue #5075).
ESBMC sees the whole program, so the set of exception types and the subtype ("is-a") relation between them are fixed once the GOTO program is built. The relation is populated from two sources: the symbol table's "bases" metadata (the namespacet constructor) and THROW exception_lists (register_chain). C++ throw lists carry a type's full flattened ancestry, so register_chain alone suffices for them; Python lists stop short (e.g. at Exception), so the symbol-table bases supply the rest (Exception -> BaseException). The typeid the dispatch guards compare against is always a thrown dynamic type.
The match guard for catch (C) becomes the finite disjunction __ESBMC_exc_typeid in concrete_subtype_ids(C) over a symbolic thrown type-id; catch (...) is just thrown == true. The relation is static (closed-world) while the thrown type stays symbolic, which is exactly what makes GOTO-level dispatch fully symbolic.
|
default |
Empty registry (populate with register_chain).
|
explicit |
Seed the table from every type symbol's "bases" metadata reachable through ns; register_chain then adds throw-list ancestry on top.
| std::set< unsigned > exception_typeidt::concrete_subtype_ids | ( | const irep_idt & | caught | ) | const |
{ id_of(T) : T <: caught } over all registered program types — the right-hand side of the catch-match guard.
| std::vector< std::pair< irep_idt, unsigned > > exception_typeidt::concrete_subtypes | ( | const irep_idt & | caught | ) | const |
{ (T, id_of(T)) : T <: caught } over all registered program types.
Like concrete_subtype_ids but keeps the names, so a caller can recover each dynamic type's struct (e.g. to compute a base-subobject offset for catch-by-base binding).
| unsigned exception_typeidt::id_of | ( | const irep_idt & | name | ) |
Stable id for name.
Names use the unprefixed convention of code_cpp_throw2t::exception_list (e.g. "std::bad_cast", never "tag-std::bad_cast"). A name absent from the program is assigned a fresh id on first request, so opaque/library types remain dispatchable.
True iff name is an actual program type seen in a throw list (not a primitive #cpp_type, opaque, or lazily-minted name).
The lowering pass only matches over registered types, so this gates whether a throw/catch can be lowered at all.
Reflexive-transitive subtype test: true iff thrown equals caught or derives from it transitively through the bases graph.
Reproduces the semantics of goto_symext::is_python_exception_subtype.
| void exception_typeidt::register_chain | ( | const std::vector< irep_idt > & | chain | ) |
Ingest an exception type's ancestry from a THROW's exception_list (front = dynamic type, rest = its flattened transitive bases).
Only the front is a subtype of the rest; the tail are independent bases, so they are not chained (struct D : A, B throws as [D, A, B], NOT A <: B). Idempotent; unions into any existing bases.
|
inline |
Number of registered program types (excludes lazily-added unknowns).
|
staticconstexpr |
Reserved id meaning "no in-flight exception type".