On Tue, 2022-07-19 at 21:36 +0530, Immad Mir wrote:

[...snip...]

Thanks for the patch.

It's nearly ready for trunk; I have some review comments below, mostly
nits, but a couple of other issues...

> gcc/ChangeLog:
>       * doc/extend.texi: Add fd_arg, fd_arg_read and fd_arg_write under
>       "Common Function Attributes" section.

As well as these additions, please can you also update doc/invoke.texi.
Specifically, please update the description of the three warnings that
are affected by these attributes so that they refer to the new
attributes, rather than just to "read" and "write", so that as well as
the docs for the attributes referring to the warnings, the docs for the
warnings refer to the attributes.

> gcc/testsuite/ChangeLog:
>       * gcc.dg/analyzer/fd-5.c: New test.
>       * c-c++-common/attr-fd.c: New test.
> 
> Signed-off-by: Immad Mir <mirim...@outlook.com>

[...snip...]

>  /* Base diagnostic class relative to fd_state_machine. */
>  class fd_diagnostic : public pending_diagnostic
>  {
> -public:
> +public:

There's what looks like an accidental change here, adding a couple of
stray spaces after the trailing colon (I think); please fix, to avoid
adding noise to the git history.

[...snip...]

> +  void
> +  inform_filedescriptor_attribute (access_directions fd_dir)
> +  {
> +
> +    if (m_attr)
> +      switch (fd_dir)
> +        {
> +        case DIRS_READ_WRITE:
> +          inform (DECL_SOURCE_LOCATION (m_callee_fndecl),
> +                  "argument %d of %qD must be an open file descriptor",
> +                  m_arg_idx + 1, m_callee_fndecl);
> +          break;
> +        case DIRS_WRITE:
> +          inform (DECL_SOURCE_LOCATION (m_callee_fndecl),
> +                  "argument %d of %qD must be a read-only file descriptor",
> +                  m_arg_idx + 1, m_callee_fndecl);
> +          break;
> +        case DIRS_READ:
> +          inform (DECL_SOURCE_LOCATION (m_callee_fndecl),
> +                  "argument %d of %qD must be a write-only file descriptor",
> +                  m_arg_idx + 1, m_callee_fndecl);
> +          break;
> +        }
> +  }

I don't like the wording of the direction-based messages; if I'm
following the code correctly, it's not so much that the argument must
be, say, a read-only file descriptor, as that the argument must be a
*readable* file descriptor.

For example in fd-5.c test_2 you have:

void g (int fd) __attribute__((fd_arg_read(1))); /* { dg-message "argument 1 of 
'g' must be a read-only file descriptor" } */
void
test_2 (const char *path)
{
  int fd = open (path, O_WRONLY);
  if (fd != -1)
  {
    g (fd); /* { dg-warning "'g' on 'write-only' file descriptor 'fd'" } */
  }
  close (fd);
}

so presumably with the patch as posted it emits:

  warning: 'g' on 'write-only' file descriptor 'fd'
  note: argument 1 of 'g' must be a read-only file descriptor

whereas I think we really mean:

  warning: 'g' on write-only file descriptor 'fd'
  note: argument 1 of 'g' must be a readable file descriptor

Also, it will be easier for the user to understand why these warnings
are appearing if they refer to the attribute by name.

So please add something like:

  "due to %<__attribute__((fd_arg(%d)))%>",
  m_arg_idx + 1

to the format strings and arguments.

So the example above might read:

  warning: 'g' on write-only file descriptor 'fd'
  note: argument 1 of 'g' must be a readable file descriptor, due to 
'__attribute__((fd_arg_read(1)))'


[...snip...]

> @@ -317,29 +398,25 @@ public:
>    bool
>    emit (rich_location *rich_loc) final override
>    {
> +    bool warned;
>      switch (m_fd_dir)
>        {
> -      case DIR_READ:
> -        return warning_at (rich_loc, get_controlling_option (),
> +      case DIRS_READ:
> +        warned =  warning_at (rich_loc, get_controlling_option (),
>                             "%qE on %<read-only%> file descriptor %qE",

I hadn't noticed this before, but read-only shouldn't be in quotes in
this message.

>                             m_callee_fndecl, m_arg);
> -      case DIR_WRITE:
> -        return warning_at (rich_loc, get_controlling_option (),
> +        break;
> +      case DIRS_WRITE:
> +        warned = warning_at (rich_loc, get_controlling_option (),
>                             "%qE on %<write-only%> file descriptor %qE",

Likewise.

>                             m_callee_fndecl, m_arg);
> +        break;
>        default:
>          gcc_unreachable ();
>        }
> -  }
> -
> -  bool
> -  subclass_equal_p (const pending_diagnostic &base_other) const override
> -  {
> -    const fd_access_mode_mismatch &sub_other
> -        = (const fd_access_mode_mismatch &)base_other;
> -    return (same_tree_p (m_arg, sub_other.m_arg)
> -            && m_callee_fndecl == sub_other.m_callee_fndecl
> -            && m_fd_dir == sub_other.m_fd_dir);
> +      if (warned)
> +        inform_filedescriptor_attribute (m_fd_dir);
> +      return warned;
>    }
>  
>    label_text
> @@ -347,10 +424,10 @@ public:
>    {
>      switch (m_fd_dir)
>        {
> -      case DIR_READ:
> +      case DIRS_READ:
>          return ev.formatted_print ("%qE on %<read-only%> file descriptor 
> %qE",
>                                     m_callee_fndecl, m_arg);

Likewise.

> -      case DIR_WRITE:
> +      case DIRS_WRITE:
>          return ev.formatted_print ("%qE on %<write-only%> file descriptor 
> %qE",
>                                     m_callee_fndecl, m_arg);

Likewise.

[...snip...]

> @@ -542,7 +627,7 @@ public:
>  
>  private:
>    diagnostic_event_id_t m_first_open_event;
> -  const tree m_callee_fndecl;
> +

We can lose this extra newline.

[...snip...]

> +void
> +fd_state_machine::check_for_fd_attrs (
> +    sm_context *sm_ctxt, const supernode *node, const gimple *stmt,
> +    const tree callee_fndecl, const char *attr_name,
> +    access_directions fd_attr_access_dir) const
> +{
> +
> +  tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (callee_fndecl));
> +  attrs = lookup_attribute (attr_name, attrs);
> +  if (!attrs)
> +    return;
> +
> +  if (!TREE_VALUE (attrs))
> +    return;
> +
> +  auto_bitmap argmap;
> +
> +  for (tree idx = TREE_VALUE (attrs); idx; idx = TREE_CHAIN (idx))
> +    {
> +      unsigned int val = TREE_INT_CST_LOW (TREE_VALUE (idx)) - 1;
> +      bitmap_set_bit (argmap, val);
> +    }
> +  if (bitmap_empty_p (argmap))
> +    return;
> +
> +  for (unsigned i = 0; i < gimple_call_num_args (stmt); i++)
> +    {
> +
> +      unsigned int arg_idx = i;

I think "i" is redundant here.  Just declare and use "arg_idx" directly
in the "for" loop; it's much more descriptive than just "i".

[...snip...]

> diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc
> index c8d96723f4c..a04cc541f95 100644
> --- a/gcc/c-family/c-attribs.cc
> +++ b/gcc/c-family/c-attribs.cc

[...snip...]

> @@ -426,7 +427,7 @@ const struct attribute_spec c_common_attribute_table[] =
>    { "tls_model",           1, 1, true,  false, false, false,
>                             handle_tls_model_attribute, NULL },
>    { "nonnull",                0, -1, false, true, true, false,
> -                           handle_nonnull_attribute, NULL },
> +                           handle_nonnull_attribute, NULL },

There's a stray addition of extra whitespace at the end of this line;
please fix to avoid noise in the git history.

[...snip...]

Thanks again for the patch; hope the above make sense
Dave

Reply via email to