On Tue, 2023-07-04 at 18:25 +0200, [email protected] wrote:
> From: benjamin priour <[email protected]>
>
> Script contrib/check_GNU_style.sh complains about there being a space
> before a left square bracket ("operator new []").
> Though, it is actually within a literal string, and the spaceĀ
> is required to correctly detect the function.
>
> Succesfully regstrapped on x86_64-linux-gnu against trunk
> 3c776fdf1a8.
> Is it OK for trunk ?
Thanks for the patch.
Overall, looks almost ready, but some nitpicks below,,,
[..snip...]
> diff --git a/gcc/analyzer/kf-lang-cp.cc b/gcc/analyzer/kf-lang-cp.cc
> index 393b4f25e79..258d92919d7 100644
> --- a/gcc/analyzer/kf-lang-cp.cc
> +++ b/gcc/analyzer/kf-lang-cp.cc
> @@ -35,6 +35,34 @@ along with GCC; see the file COPYING3. If not see
>
> #if ENABLE_ANALYZER
>
> +/* Return TRUE if CALL is non-allocating operator new or operator
> new[]*/
> +
> +bool is_placement_new_p (const gcall *call)
Please can you extend the leading comment, giving the expected
signatures of the functions, and a link to cppreference.org.
In particular, there's some special-casing here of "nothrow_t" which
would make more sense with a comment up here.
> +{
> + gcc_assert (call);
> +
> + tree fndecl = gimple_call_fndecl (call);
> + if (!fndecl)
> + return false;
> +
> + if (!is_named_call_p (fndecl, "operator new", call, 2)
> + && !is_named_call_p (fndecl, "operator new []", call, 2))
> + return false;
> + tree arg1 = gimple_call_arg (call, 1);
> +
> + if (!POINTER_TYPE_P (TREE_TYPE (arg1)))
> + return false;
> +
> + /* Sadly, for non-throwing new, the second argument type
> + is not REFERENCE_TYPE but also POINTER_TYPE
> + so a simple check is out of the way. */
> + tree identifier = TYPE_IDENTIFIER (TREE_TYPE (TREE_TYPE (arg1)));
> + if (!identifier)
> + return true;
> + const char *name = IDENTIFIER_POINTER (identifier);
> + return 0 != strcmp (name, "nothrow_t");
> +}
> +
> namespace ana {
>
> /* Implementations of specific functions. */
> @@ -46,7 +74,7 @@ class kf_operator_new : public known_function
> public:
> bool matches_call_types_p (const call_details &cd) const final
> override
> {
> - return cd.num_args () == 1;
> + return cd.num_args () == 1 || cd.num_args () == 2;
Looks like we should also check that arg 0 is of integral type, and
that arg 1 is of pointer type.
> }
>
> void impl_call_pre (const call_details &cd) const final override
> @@ -54,13 +82,60 @@ public:
> region_model *model = cd.get_model ();
> region_model_manager *mgr = cd.get_manager ();
> const svalue *size_sval = cd.get_arg_svalue (0);
> - const region *new_reg
> - = model->get_or_create_region_for_heap_alloc (size_sval,
> cd.get_ctxt ());
> - if (cd.get_lhs_type ())
> + region_model_context *ctxt = cd.get_ctxt ();
> + const gcall *call = cd.get_call_stmt ();
> +
> + /* If the call is an allocating new, then create a heap
> allocated
> + region. */
> + if (!is_placement_new_p (call))
> + {
You have:
if (!condition)
suite_a;
else
suite_b; // this is implicitly a double negative
Please change it to:
if (condition)
suite_b;
else
suite_a;
to avoid the implicit double negative.
> + const region *new_reg
> + = model->get_or_create_region_for_heap_alloc (size_sval, ctxt);
> + if (cd.get_lhs_type ())
> + {
> + const svalue *ptr_sval
> + = mgr->get_ptr_svalue (cd.get_lhs_type (), new_reg);
> + cd.maybe_set_lhs (ptr_sval);
> + }
> + }
> + /* If the call was actually a placement new, check that
> accessing
> + the buffer lhs is placed into does not result in out-of-bounds.
> */
> + else
> {
> + const region *ptr_reg = cd.maybe_get_arg_region (1);
> + if (ptr_reg && cd.get_lhs_type ())
> + {
> + const region *base_reg = ptr_reg->get_base_region ();
> + const svalue *num_bytes_sval = cd.get_arg_svalue (0);
> + const region *sized_new_reg = mgr->get_sized_region (base_reg,
> + cd.get_lhs_type (),
> + num_bytes_sval);
> + model->check_region_for_write (sized_new_reg,
> + nullptr,
> + ctxt);
> const svalue *ptr_sval
> - = mgr->get_ptr_svalue (cd.get_lhs_type (), new_reg);
> + = mgr->get_ptr_svalue (cd.get_lhs_type (), sized_new_reg);
> cd.maybe_set_lhs (ptr_sval);
> + }
> + }
> + }
[...snip...]
> diff --git a/gcc/testsuite/g++.dg/analyzer/new-2.C
> b/gcc/testsuite/g++.dg/analyzer/new-2.C
> new file mode 100644
> index 00000000000..4e696040a54
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/analyzer/new-2.C
> @@ -0,0 +1,50 @@
> +// { dg-additional-options "-O0" }
> +
> +struct A
> +{
> + int x;
> + int y;
> +};
We've run into issues with bounds-checking testcases when using types
like "int" that have target-specific sizes.
Please use <stdint.h> in these test cases, and types with explicit
sizes, such as int32_t, to avoid the behavior of the test cases being
affected by sizeof the various types.
[..snip...]
Other than those issues, looks good
Thanks again
Dave