ESBMC
Efficient SMT-based Context-Bounded Model Checker
Loading...
Searching...
No Matches
clang_c_adjust_irep2.cpp File Reference
Include dependency graph for clang_c_adjust_irep2.cpp:

Macros

#define ARM(member)
 Name and member from one token, so the string the ordering test matches on and the member it names cannot drift apart.

Functions

static locationt statement_location (const expr2tc &expr)
 The source location of expr when it is a statement that can hold a call in a sub-expression, empty otherwise.
static bool is_width_suffixed (const std::string &name, const std::string &stem)
 One of a family of spellings differing only by the argument's width: __builtin_popcount, ...l, ...ll and the type-generic ...g.
static void fold_comparison_builtin (const std::string &name, const expr2tc &l, const expr2tc &r, expr2tc &expr)
 The ordered-comparison builtins, which differ from the plain operators only in being defined when an operand is NaN.
static void fold_unary_builtin (const std::string &name, const expr2tc &arg, expr2tc &expr)
 The one-argument builtins that lower to a single IREP2 node.
static bool fold_pointer_intrinsic (const std::string &name, const std::vector< expr2tc > &args, expr2tc &expr)
 The three pointer intrinsics do_special_functions matches by their __ESBMC_ name rather than a __builtin_ prefix.
static bool fold_float_constant (expr2tc &expr, const irep_idt &name, bool &handled)
 The lowerings do_special_functions selects by base name rather than by a reserved __builtin_ prefix.
static bool lower_float_library_call (expr2tc &expr, const irep_idt &name, const std::vector< expr2tc > &args)
 C17 7.12.10.2: remainder() is IEEE 754 remainder, exactly SMT-LIB's fp.rem.
static bool is_shift_assignment (const irep_idt &op)
 The shift spellings clang_c_adjust returns early on: it promotes only the right operand there, which the corpus shows is already the migrated shape.
static bool binds_by_reference (const expr2tc &callee, const expr2tc &arg, const type2tc &param, std::size_t i, const contextt &context, const namespacet &ns, pointer_ref_kindt &rk)
 True when arg is bound to parameter i of callee rather than converted to its type – va_start(ap, n) hands the callee &ap.
static bool contains_sideeffect (const expr2tc &expr)
void adjust_comma_at_dispatch (exprt &expr, const namespacet &ns)
 Shape-2 probe (scope-clang-c-irep2.md §57): run the IREP2 comma rewrite at the point the legacy pass dispatches it, rather than in a second whole- program pass.

Macro Definition Documentation

◆ ARM

#define ARM ( member)
Value:
#member, +[](clang_c_adjust_irep2 &self, expr2tc &expr) { self.member(expr); }

Name and member from one token, so the string the ordering test matches on and the member it names cannot drift apart.

Function Documentation

◆ adjust_comma_at_dispatch()

void adjust_comma_at_dispatch ( exprt & expr,
const namespacet & ns )

Shape-2 probe (scope-clang-c-irep2.md §57): run the IREP2 comma rewrite at the point the legacy pass dispatches it, rather than in a second whole- program pass.

§55.4 attributes the comma arm's divergences to that ordering alone; this is the experiment that decides it.

◆ binds_by_reference()

bool binds_by_reference ( const expr2tc & callee,
const expr2tc & arg,
const type2tc & param,
std::size_t i,
const contextt & context,
const namespacet & ns,
pointer_ref_kindt & rk )
static

True when arg is bound to parameter i of callee rather than converted to its type – va_start(ap, n) hands the callee &ap.

pointer_type2t has no field for the #reference bit clang_c_convertert::get_type sets, so migrate_type drops it and the rule c_typecastt::implicit_typecast_followed applies on the legacy path cannot be stated against the IREP2 types. It survives on the symbol's legacy typet, which is what this reads – the same route the implicit-callee arm above already takes to recover a base name. The rest of the conjunction is legacy's own precondition, kept whole so the two paths decide alike.

Whether a parameter is a reference is a property of the target, not of the callee's name: clang's A builtin-type code is an lvalue reference where __builtin_va_list is a pointer or a struct, and an already-decayed pointer where it is an array (x86-64 Linux). Reading the bit follows the target; a name test would take the address on both. rk receives the reference kind the legacy declaration spells, which the IREP2 parameter type need not carry – that asymmetry is why the check below reads the declaration at all.

◆ contains_sideeffect()

bool contains_sideeffect ( const expr2tc & expr)
static

◆ fold_comparison_builtin()

void fold_comparison_builtin ( const std::string & name,
const expr2tc & l,
const expr2tc & r,
expr2tc & expr )
static

The ordered-comparison builtins, which differ from the plain operators only in being defined when an operand is NaN.

◆ fold_float_constant()

bool fold_float_constant ( expr2tc & expr,
const irep_idt & name,
bool & handled )
static

The lowerings do_special_functions selects by base name rather than by a reserved __builtin_ prefix.

Returns true when expr was rewritten.

sqrt's legacy arm additionally skips a py:-prefixed callee; this pass is constructed only from clang_c_languaget::typecheck, so no Python symbol can reach it and the guard has nothing to test. The argument-less float constants. handled distinguishes "not one of these" from "one of these, but declined".

◆ fold_pointer_intrinsic()

bool fold_pointer_intrinsic ( const std::string & name,
const std::vector< expr2tc > & args,
expr2tc & expr )
static

The three pointer intrinsics do_special_functions matches by their __ESBMC_ name rather than a __builtin_ prefix.

Each lowers to a node the backend evaluates in place; left as a call the symbol is bodyless and goto_check's "non-intrinsic prefixed with __ESBMC" rejects the program. Returns true when expr was rewritten.

◆ fold_unary_builtin()

void fold_unary_builtin ( const std::string & name,
const expr2tc & arg,
expr2tc & expr )
static

The one-argument builtins that lower to a single IREP2 node.

◆ is_shift_assignment()

bool is_shift_assignment ( const irep_idt & op)
static

The shift spellings clang_c_adjust returns early on: it promotes only the right operand there, which the corpus shows is already the migrated shape.

◆ is_width_suffixed()

bool is_width_suffixed ( const std::string & name,
const std::string & stem )
static

One of a family of spellings differing only by the argument's width: __builtin_popcount, ...l, ...ll and the type-generic ...g.

The lowering is the same node for all of them, so the suffix carries no information here.

◆ lower_float_library_call()

bool lower_float_library_call ( expr2tc & expr,
const irep_idt & name,
const std::vector< expr2tc > & args )
static

C17 7.12.10.2: remainder() is IEEE 754 remainder, exactly SMT-LIB's fp.rem.

Lower only when the call is shaped like the C library function.

Legacy exempts the model build from the shape test, where its own remainder() calls are what put ieee_rem into the model. That is not ported: clang-c-irep2-adjust-only is not one of c2goto's options (src/c2goto/c2goto.cpp), so this pass never runs under building-c-library.

◆ statement_location()

locationt statement_location ( const expr2tc & expr)
static

The source location of expr when it is a statement that can hold a call in a sub-expression, empty otherwise.

sideeffect2t carries none of its own, so a call in one takes the enclosing statement's – which is what clang_c_adjust reads off the side_effect_expr_function_callt it is handed (§130.3). Every kind whose operands can be an expression is listed: a condition is as much a call site as an assignment's right-hand side, and omitting one leaves the counterexample with no file and line 0.