GCC Middle and Back End API Reference
strlen_pass Class Reference
Inheritance diagram for strlen_pass:
Collaboration diagram for strlen_pass:

Public Types

enum  reachability { ALL_BLOCKS , REACHABLE_BLOCKS , REACHABLE_BLOCKS_PRESERVING_FLAGS }
 

Public Member Functions

 strlen_pass (function *fun, cdi_direction direction)
 
 ~strlen_pass ()
 
edge before_dom_children (basic_block) final override
 
void after_dom_children (basic_block) final override
 
bool check_and_optimize_stmt (bool *cleanup_eh)
 
bool check_and_optimize_call (bool *zero_write)
 
bool handle_assign (tree lhs, bool *zero_write)
 
bool handle_store (bool *zero_write)
 
void handle_pointer_plus ()
 
void handle_builtin_strlen ()
 
void handle_builtin_strchr ()
 
void handle_builtin_strcpy (built_in_function)
 
void handle_integral_assign (bool *cleanup_eh)
 
void handle_builtin_stxncpy_strncat (bool append_p)
 
void handle_builtin_memcpy (built_in_function bcode)
 
void handle_builtin_strcat (built_in_function bcode)
 
void handle_builtin_strncat (built_in_function)
 
bool handle_builtin_memset (bool *zero_write)
 
bool handle_builtin_memcmp ()
 
bool handle_builtin_string_cmp ()
 
void handle_alloc_call (built_in_function)
 
void maybe_warn_overflow (gimple *stmt, bool call_lhs, tree len, strinfo *si=NULL, bool plus_one=false, bool rawmem=false)
 
void maybe_warn_overflow (gimple *stmt, bool call_lhs, unsigned HOST_WIDE_INT len, strinfo *si=NULL, bool plus_one=false, bool rawmem=false)
 
void adjust_last_stmt (strinfo *si, gimple *stmt, bool is_strcat)
 
tree strxcmp_eqz_result (gimple *stmt, tree arg1, int idx1, tree arg2, int idx2, unsigned HOST_WIDE_INT bound, unsigned HOST_WIDE_INT len[2], unsigned HOST_WIDE_INT *psize)
 
bool count_nonzero_bytes (tree expr_or_type, gimple *stmt, unsigned lenrange[3], bool *nulterm, bool *allnul, bool *allnonnul)
 
bool count_nonzero_bytes (tree exp, tree vuse, gimple *stmt, unsigned HOST_WIDE_INT offset, unsigned HOST_WIDE_INT nbytes, unsigned lenrange[3], bool *nulterm, bool *allnul, bool *allnonnul, ssa_name_limit_t &snlim)
 
bool count_nonzero_bytes_addr (tree exp, tree vuse, gimple *stmt, unsigned HOST_WIDE_INT offset, unsigned HOST_WIDE_INT nbytes, unsigned lenrange[3], bool *nulterm, bool *allnul, bool *allnonnul, ssa_name_limit_t &snlim)
 
bool get_len_or_size (gimple *stmt, tree arg, int idx, unsigned HOST_WIDE_INT lenrng[2], unsigned HOST_WIDE_INT *size, bool *nulterm)
 
void walk (basic_block)
 

Data Fields

pointer_query ptr_qry
 
gimple_stmt_iterator m_gsi
 
bool m_cleanup_cfg
 

Static Public Attributes

static const edge STOP = (edge)-1
 

Private Member Functions

bool bb_reachable (struct function *, basic_block)
 
void propagate_unreachable_to_edges (basic_block, FILE *, dump_flags_t)
 

Private Attributes

enum cdi_direction m_dom_direction: 2
 
enum reachability m_reachability: 2
 
bool m_user_bb_to_rpo
 
basic_block m_unreachable_dom
 
int * m_bb_to_rpo
 

Member Enumeration Documentation

◆ reachability

enum dom_walker::reachability
inherited
Enumerator
ALL_BLOCKS 
REACHABLE_BLOCKS 
REACHABLE_BLOCKS_PRESERVING_FLAGS 

Constructor & Destructor Documentation

◆ strlen_pass()

strlen_pass::strlen_pass ( function * fun,
cdi_direction direction )
inline

◆ ~strlen_pass()

strlen_pass::~strlen_pass ( )
Release pointer_query cache.   

References pointer_query::flush_cache(), and ptr_qry.

Member Function Documentation

◆ adjust_last_stmt()

◆ after_dom_children()

void strlen_pass::after_dom_children ( basic_block bb)
finaloverridevirtual
Callback for walk_dominator_tree.  Free strinfo vector if it is
owned by the current bb, clear bb->aux.   

Reimplemented from dom_walker.

References basic_block_def::aux, free_strinfo(), i, NULL, si, stridx_to_strinfo, vec_free(), vec_safe_iterate(), and vec_safe_length().

◆ bb_reachable()

bool dom_walker::bb_reachable ( struct function * fun,
basic_block bb )
privateinherited

◆ before_dom_children()

◆ check_and_optimize_call()

◆ check_and_optimize_stmt()

bool strlen_pass::check_and_optimize_stmt ( bool * cleanup_eh)
Attempt to check for validity of the performed access a single statement
at *GSI using string length knowledge, and to optimize it.
If the given basic block needs clean-up of EH, CLEANUP_EH is set to
true.  Return true to let the caller advance *GSI to the next statement
in the basic block and false otherwise.   

References check_and_optimize_call(), dyn_cast(), fold_strstr_to_strncmp(), get_stridx(), gimple_assign_cast_p(), gimple_assign_lhs(), gimple_assign_rhs1(), gimple_assign_rhs_code(), gimple_assign_single_p(), gimple_clobber_p(), gimple_cond_code(), gimple_cond_lhs(), gimple_cond_rhs(), gimple_vdef(), gsi_stmt(), handle_assign(), handle_integral_assign(), handle_pointer_plus(), INTEGRAL_TYPE_P, is_gimple_assign(), is_gimple_call(), m_gsi, maybe_invalidate(), POINTER_TYPE_P, SSA_NAME_VERSION, ssa_ver_to_stridx, strlen_optimize, TREE_CODE, TREE_SIDE_EFFECTS, and TREE_TYPE.

Referenced by before_dom_children().

◆ count_nonzero_bytes() [1/2]

bool strlen_pass::count_nonzero_bytes ( tree exp,
tree vuse,
gimple * stmt,
unsigned HOST_WIDE_INT offset,
unsigned HOST_WIDE_INT nbytes,
unsigned lenrange[3],
bool * nulterm,
bool * allnul,
bool * allnonnul,
ssa_name_limit_t & snlim )
Recursively determine the minimum and maximum number of leading nonzero
bytes in the representation of EXP at memory state VUSE and set
LENRANGE[0] and LENRANGE[1] to each.
Sets LENRANGE[2] to the total size of the access (which may be less
than LENRANGE[1] when what's being referenced by EXP is a pointer
rather than an array).
Sets *NULTERM if the representation contains a zero byte, sets *ALLNUL
if all the bytes are zero, and *ALLNONNUL is all are nonzero.
OFFSET and NBYTES are the offset into the representation and
the size of the access to it determined from an ADDR_EXPR (i.e.,
a pointer) or MEM_REF or zero for other expressions.
Uses RVALS to determine range information.
Avoids recursing deeper than the limits in SNLIM allow.
Returns true on success and false otherwise.   

References build_int_cst(), CHAR_BIT, char_type_node, CONSTRUCTOR_ELT, CONSTRUCTOR_ELTS, CONSTRUCTOR_NELTS, count_nonzero_bytes(), count_nonzero_bytes_addr(), ctor_for_folding(), DECL_P, error_mark_node, exp(), FOR_EACH_CONSTRUCTOR_ELT, g, gimple_assign_rhs1(), gimple_assign_single_p(), gimple_phi_arg_def(), gimple_phi_num_args(), i, INT_MAX, int_size_in_bytes(), native_encode_expr(), ssa_name_limit_t::next_phi(), nonzero_bytes_for_type(), NULL, offset, SSA_NAME_DEF_STMT, TREE_CODE, tree_expr_nonzero_p(), tree_fits_uhwi_p(), TREE_OPERAND, TREE_STRING_LENGTH, TREE_STRING_POINTER, tree_to_uhwi(), TREE_TYPE, TYPE_MODE, TYPE_PRECISION, TYPE_SIZE_UNIT, VAR_P, and VECTOR_TYPE_P.

◆ count_nonzero_bytes() [2/2]

bool strlen_pass::count_nonzero_bytes ( tree expr_or_type,
gimple * stmt,
unsigned lenrange[3],
bool * nulterm,
bool * allnul,
bool * allnonnul )
Same as above except with an implicit SSA_NAME limit.  When EXPR_OR_TYPE
is a type rather than an expression use its size to compute the range.
RVALS is used to determine ranges of dynamically computed string lengths
(the results of strlen).   

References count_nonzero_bytes(), gimple_vuse(), nonzero_bytes_for_type(), and TYPE_P.

Referenced by count_nonzero_bytes(), count_nonzero_bytes(), count_nonzero_bytes_addr(), handle_integral_assign(), and handle_store().

◆ count_nonzero_bytes_addr()

bool strlen_pass::count_nonzero_bytes_addr ( tree exp,
tree vuse,
gimple * stmt,
unsigned HOST_WIDE_INT offset,
unsigned HOST_WIDE_INT nbytes,
unsigned lenrange[3],
bool * nulterm,
bool * allnul,
bool * allnonnul,
ssa_name_limit_t & snlim )

◆ get_len_or_size()

bool strlen_pass::get_len_or_size ( gimple * stmt,
tree arg,
int idx,
unsigned HOST_WIDE_INT lenrng[2],
unsigned HOST_WIDE_INT * size,
bool * nulterm )
Given strinfo IDX for ARG, sets LENRNG[] to the range of lengths
of the string(s) referenced by ARG if it can be determined.
If the length cannot be determined, sets *SIZE to the size of
the array the string is stored in, if any.  If no such array is
known, sets *SIZE to -1.  When the strings are nul-terminated sets
*NULTERM to true, otherwise to false.  When nonnull uses RVALS to
determine range information. Returns true on success.   

References cfun, get_range_query(), get_range_strlen_dynamic(), get_strinfo(), HOST_WIDE_INT_M1U, HOST_WIDE_INT_MAX, integer_all_onesp(), max_object_size(), c_strlen_data::maxbound, c_strlen_data::maxlen, c_strlen_data::minlen, NULL, ptr_qry, r, si, TREE_CODE, tree_fits_uhwi_p(), and tree_to_uhwi().

Referenced by handle_builtin_string_cmp(), and strxcmp_eqz_result().

◆ handle_alloc_call()

void strlen_pass::handle_alloc_call ( built_in_function bcode)
Handle a call to an allocation function like alloca, malloc or calloc,
or an ordinary allocation function declared with attribute alloc_size.   

References build_int_cst(), gcc_assert, get_stridx(), gimple_call_lhs(), gsi_stmt(), m_gsi, new_stridx(), new_strinfo(), NULL_TREE, set_strinfo(), si, and size_type_node.

Referenced by check_and_optimize_call().

◆ handle_assign()

bool strlen_pass::handle_assign ( tree lhs,
bool * zero_write )
Handle assignment statement at *GSI to LHS.  Set *ZERO_WRITE if
the assignment stores all zero bytes.   

References handle_store(), i, is_char_type(), TREE_CODE, TREE_OPERAND, and TREE_TYPE.

Referenced by check_and_optimize_call(), and check_and_optimize_stmt().

◆ handle_builtin_memcmp()

◆ handle_builtin_memcpy()

◆ handle_builtin_memset()

◆ handle_builtin_strcat()

◆ handle_builtin_strchr()

◆ handle_builtin_strcpy()

void strlen_pass::handle_builtin_strcpy ( built_in_function bcode)

◆ handle_builtin_string_cmp()

bool strlen_pass::handle_builtin_string_cmp ( )
Optimize a call to strcmp or strncmp either by folding it to a constant
when possible or by transforming the latter to the former.  Warn about
calls where the length of one argument is greater than the size of
the array to which the other argument points if the latter's length
is not known.  Return true when the call has been transformed into
another and false otherwise.   

References as_a(), build_int_cst(), builtin_decl_implicit(), check_nul_terminated_array(), get_len_or_size(), get_stridx(), gimple_call_arg(), gimple_call_lhs(), gimple_call_num_args(), gsi_stmt(), HOST_WIDE_INT_M1U, HOST_WIDE_INT_MAX, integer_zero_node, integer_zerop(), m_gsi, maybe_warn_pointless_strcmp(), MIN, NULL_TREE, replace_call_with_value(), irange::set_nonzero(), set_range_info(), size_type_node, strxcmp_eqz_result(), tree_fits_shwi_p(), tree_to_shwi(), TREE_TYPE, update_gimple_call(), and use_in_zero_equality().

Referenced by check_and_optimize_call().

◆ handle_builtin_strlen()

◆ handle_builtin_strncat()

void strlen_pass::handle_builtin_strncat ( built_in_function )
Check the size argument to the built-in forms of stpncpy and strncpy
for out-of-bounds offsets or overlapping access, and to see if the
size argument is derived from a call to strlen() on the source argument,
and if so, issue an appropriate warning.   

References handle_builtin_stxncpy_strncat().

Referenced by check_and_optimize_call().

◆ handle_builtin_stxncpy_strncat()

void strlen_pass::handle_builtin_stxncpy_strncat ( bool append_p)
Check the arguments to the built-in forms of stpncpy, strncpy, and
strncat, for out-of-bounds offsets or overlapping access, and to see
if the size is derived from calling strlen() on the source argument,
and if so, issue the appropriate warning.
APPEND_P is true for strncat.   

References build_int_cst(), check_bounds_or_overlap(), fold_build2, strinfo::full_string_p, get_stridx(), get_strinfo(), gimple_call_alloc_size(), gimple_call_arg(), gimple_call_fndecl(), gimple_or_expr_nonartificial_location(), gsi_stmt(), inform(), is_strlen_related_p(), m_gsi, maybe_diag_stxncpy_trunc(), no_warning, strinfo::nonzero_chars, NULL, NULL_TREE, strinfo::ptr, SSA_NAME_DEF_STMT, strlen_to_stridx, suppress_warning(), TREE_CODE, TREE_TYPE, UNKNOWN_LOCATION, and warning_at().

Referenced by check_and_optimize_call(), and handle_builtin_strncat().

◆ handle_integral_assign()

◆ handle_pointer_plus()

void strlen_pass::handle_pointer_plus ( )

◆ handle_store()

◆ maybe_warn_overflow() [1/2]

void strlen_pass::maybe_warn_overflow ( gimple * stmt,
bool call_lhs,
tree len,
strinfo * si = NULL,
bool plus_one = false,
bool rawmem = false )
Diagnose buffer overflow by a STMT writing LEN + PLUS_ONE bytes,
either into a region allocated for the object SI when non-null,
or into an object designated by the LHS of STMT otherwise.
For a call STMT, when CALL_LHS is set use its left hand side
as the destination, otherwise use argument zero.
When nonnull uses RVALS to determine range information.
RAWMEM may be set by memcpy and other raw memory functions
to allow accesses across subobject boundaries.   

References access_write_only, BUILT_IN_NORMAL, compute_objsize(), gcc_assert, get_range(), gimple_assign_lhs(), gimple_call_arg(), gimple_call_builtin_p(), gimple_call_fndecl(), gimple_call_lhs(), gimple_or_expr_nonartificial_location(), access_ref::inform_access(), is_gimple_assign(), is_gimple_call(), is_strlen_related_p(), wi::leu_p(), max_object_size(), NULL_TREE, access_ref::offrng, ptr_qry, pointer_query::rvals, si, SIGNED, access_ref::size_remaining(), access_ref::sizrng, suppress_warning(), wi::to_offset(), UNSIGNED, warning_at(), warning_n(), and warning_suppressed_p().

Referenced by handle_builtin_memcpy(), handle_builtin_memset(), handle_builtin_strcpy(), handle_store(), and maybe_warn_overflow().

◆ maybe_warn_overflow() [2/2]

void strlen_pass::maybe_warn_overflow ( gimple * stmt,
bool call_lhs,
unsigned HOST_WIDE_INT len,
strinfo * si = NULL,
bool plus_one = false,
bool rawmem = false )
Convenience wrapper for the above.   

References build_int_cst(), maybe_warn_overflow(), si, and size_type_node.

◆ propagate_unreachable_to_edges()

void dom_walker::propagate_unreachable_to_edges ( basic_block bb,
FILE * dump_file,
dump_flags_t dump_flags )
privateinherited
BB has been determined to be unreachable.  Propagate that property
to incoming and outgoing edges of BB as appropriate.   

References CDI_DOMINATORS, dominated_by_p(), dump_file, dump_flags, FOR_EACH_EDGE, basic_block_def::index, dom_walker::m_unreachable_dom, basic_block_def::preds, basic_block_def::succs, and TDF_DETAILS.

Referenced by dom_walker::walk().

◆ strxcmp_eqz_result()

tree strlen_pass::strxcmp_eqz_result ( gimple * stmt,
tree arg1,
int idx1,
tree arg2,
int idx2,
unsigned HOST_WIDE_INT bound,
unsigned HOST_WIDE_INT len[2],
unsigned HOST_WIDE_INT * psize )
If IDX1 and IDX2 refer to strings A and B of unequal lengths, return
the result of 0 == strncmp (A, B, BOUND) (which is the same as strcmp
for a sufficiently large BOUND).  If the result is based on the length
of one string being greater than the longest string that would fit in
the array pointer to by the argument, set *PLEN and *PSIZE to
the corresponding length (or its complement when the string is known
to be at least as long and need not be nul-terminated) and size.
Otherwise return null.   

References get_len_or_size(), HOST_WIDE_INT_M1U, HOST_WIDE_INT_MAX, integer_one_node, integer_zero_node, and NULL_TREE.

Referenced by handle_builtin_string_cmp().

◆ walk()

Field Documentation

◆ m_bb_to_rpo

int* dom_walker::m_bb_to_rpo
privateinherited

◆ m_cleanup_cfg

bool strlen_pass::m_cleanup_cfg

Referenced by before_dom_children().

◆ m_dom_direction

enum cdi_direction dom_walker::m_dom_direction
privateinherited

Referenced by dom_walker::walk().

◆ m_gsi

◆ m_reachability

enum reachability dom_walker::m_reachability
privateinherited

◆ m_unreachable_dom

basic_block dom_walker::m_unreachable_dom
privateinherited

◆ m_user_bb_to_rpo

bool dom_walker::m_user_bb_to_rpo
privateinherited

◆ ptr_qry

◆ STOP

const edge dom_walker::STOP = (edge)-1
staticinherited

The documentation for this class was generated from the following file: