ESBMC
Efficient SMT-based Context-Bounded Model Checker
Loading...
Searching...
No Matches
preprocessor.path_dependent_attributes Namespace Reference

Classes

class  _Uses
class  _Rewrite

Functions

 _scopes (module)
 _bindings (module, name)
 _builtin_lacks (base, attr)
 _class_lacks (classes, name, attr)
 _store_target (node)
 _call_attribute (node)
 _supported_call (node)
 _uses_by_attribute (module)
 _set (name, value, at)
 _insert_after (module, stmt, extra)
 _lower (module, use, binding, has, value)
 _mentioned (module)
 _reachable_otherwise (module, mentioned)
 _binding (module, use, scopes)
 lower_path_dependent_attributes (module)

Variables

dict _HOOKS
tuple _SCOPES
 keywords
 bases

Detailed Description

Answer `getattr` with a default and `hasattr` on an attribute that a scope
adds to its own instance on only some paths (#8964).

The converter refuses such a store: the instance's struct cannot tell a path
that set the attribute from one that did not. When the attribute is stored
and read nowhere else, and only through `getattr` with a default or
`hasattr`, its value and whether it is set are two local variables instead:

    b = B()                      b = B()
                                 esbmc_has_b_code = False
    if c:                        if c:
        b.code = 1                   esbmc_b_code = 1
                                     esbmc_has_b_code = True
    getattr(b, "code", 0)        esbmc_b_code if esbmc_has_b_code else 0
    hasattr(b, "code")           esbmc_has_b_code

The receiver must be a name bound once, by constructing a class of the
module, in the one scope holding every use of the attribute. Anything that
could reach the attribute another way (a hook, an import, a dynamic name)
leaves the program unchanged.

Function Documentation

◆ _binding()

preprocessor.path_dependent_attributes._binding ( module,
use,
scopes )
protected
The statement binding the one receiver of `use`, when one statement
binds it, in the function or module scope of every use, and a store of
the attribute sits in a block nested in that scope.

◆ _bindings()

preprocessor.path_dependent_attributes._bindings ( module,
name )
protected
The nodes of `module` that bind `name`.

◆ _builtin_lacks()

preprocessor.path_dependent_attributes._builtin_lacks ( base,
attr )
protected

◆ _call_attribute()

preprocessor.path_dependent_attributes._call_attribute ( node)
protected
The attribute a `getattr` or `hasattr` call names: None when `node` is
no such call, "" when the call does not name it by a string literal.

◆ _class_lacks()

preprocessor.path_dependent_attributes._class_lacks ( classes,
name,
attr )
protected
Whether class `name` of the module, and each class it derives from,
leaves `attr` to its instances.

◆ _insert_after()

preprocessor.path_dependent_attributes._insert_after ( module,
stmt,
extra )
protected

◆ _lower()

preprocessor.path_dependent_attributes._lower ( module,
use,
binding,
has,
value )
protected

◆ _mentioned()

preprocessor.path_dependent_attributes._mentioned ( module)
protected
Every name and attribute name `module` mentions.

◆ _reachable_otherwise()

preprocessor.path_dependent_attributes._reachable_otherwise ( module,
mentioned )
protected
Whether something other than the nodes this pass rewrites may reach an
attribute: another module, a hook, a class pattern, or a rebound getattr
or hasattr.

◆ _scopes()

preprocessor.path_dependent_attributes._scopes ( module)
protected
The innermost scope of every node in `module`, by node id.

◆ _set()

preprocessor.path_dependent_attributes._set ( name,
value,
at )
protected

◆ _store_target()

preprocessor.path_dependent_attributes._store_target ( node)
protected
The attribute a plain `obj.attr = value` statement stores, or None.

◆ _supported_call()

preprocessor.path_dependent_attributes._supported_call ( node)
protected
Whether `node` is `getattr(obj, name, default)` with a default that
cannot fail to evaluate, or `hasattr(obj, name)`.

◆ _uses_by_attribute()

preprocessor.path_dependent_attributes._uses_by_attribute ( module)
protected
Each attribute name's uses, or None when a use names it dynamically.

◆ lower_path_dependent_attributes()

preprocessor.path_dependent_attributes.lower_path_dependent_attributes ( module)
Rewrite each attribute that qualifies, as the module docstring shows.

Variable Documentation

◆ _HOOKS

dict preprocessor.path_dependent_attributes._HOOKS
protected
Initial value:
1= {
2 "setattr", "delattr", "vars", "dir", "globals", "locals", "eval", "exec", "__dict__",
3 "__class__", "__slots__", "__getattr__", "__getattribute__", "__setattr__", "__delattr__"
4}

◆ _SCOPES

tuple preprocessor.path_dependent_attributes._SCOPES
protected
Initial value:
1= (ast.Module, ast.FunctionDef, ast.AsyncFunctionDef, ast.Lambda, ast.ClassDef,
2 ast.ListComp, ast.SetComp, ast.DictComp, ast.GeneratorExp)

◆ bases

preprocessor.path_dependent_attributes.bases

◆ keywords

preprocessor.path_dependent_attributes.keywords