The above patch is bootstrapped, lightly tested (on x86_64 Linux) and
approved for trunk by David.
On Tue, Aug 2, 2022 at 10:04 PM Immad Mir wrote:
> This patch extends the state machine in sm-fd.cc to support
> creat, dup, dup2 and dup3 functions.
>
> Lightly tested on x86_64 Linux.
>
> gcc/analyzer/ChangeLog:
> PR analyzer/106298
> * sm-fd.cc (fd_state_machine::on_open): Add
> creat, dup, dup2 and dup3 functions.
> (enum dup): New.
> (fd_state_machine::valid_to_unchecked_state): New.
> (fd_state_machine::on_creat): New.
> (fd_state_machine::on_dup): New.
>
> gcc/testsuite/ChangeLog:
> PR analyzer/106298
> * gcc.dg/analyzer/fd-1.c: Add tests for 'creat'.
> * gcc.dg/analyzer/fd-2.c: Likewise.
> * gcc.dg/analyzer/fd-4.c: Likewise.
> * gcc.dg/analyzer/fd-dup-1.c: New tests.
>
> Signed-off-by: Immad Mir
> ---
> gcc/analyzer/sm-fd.cc| 129 -
> gcc/testsuite/gcc.dg/analyzer/fd-1.c | 21 +++
> gcc/testsuite/gcc.dg/analyzer/fd-2.c | 15 ++
> gcc/testsuite/gcc.dg/analyzer/fd-4.c | 31 +++-
> gcc/testsuite/gcc.dg/analyzer/fd-dup-1.c | 223 +++
> 5 files changed, 415 insertions(+), 4 deletions(-)
> create mode 100644 gcc/testsuite/gcc.dg/analyzer/fd-dup-1.c
>
> diff --git a/gcc/analyzer/sm-fd.cc b/gcc/analyzer/sm-fd.cc
> index ed923ade100..8bb76d72b05 100644
> --- a/gcc/analyzer/sm-fd.cc
> +++ b/gcc/analyzer/sm-fd.cc
> @@ -69,6 +69,14 @@ enum access_directions
>DIRS_WRITE
> };
>
> +/* An enum for distinguishing between dup, dup2 and dup3. */
> +enum dup
> +{
> + DUP_1,
> + DUP_2,
> + DUP_3
> +};
> +
> class fd_state_machine : public state_machine
> {
> public:
> @@ -114,7 +122,9 @@ public:
>bool is_readonly_fd_p (state_t s) const;
>bool is_writeonly_fd_p (state_t s) const;
>enum access_mode get_access_mode_from_flag (int flag) const;
> -
> + /* Function for one-to-one correspondence between valid
> + and unchecked states. */
> + state_t valid_to_unchecked_state (state_t state) const;
>/* State for a constant file descriptor (>= 0) */
>state_t m_constant_fd;
>
> @@ -147,6 +157,8 @@ public:
> private:
>void on_open (sm_context *sm_ctxt, const supernode *node, const gimple
> *stmt,
> const gcall *call) const;
> + void on_creat (sm_context *sm_ctxt, const supernode *node, const gimple
> *stmt,
> + const gcall *call) const;
>void on_close (sm_context *sm_ctxt, const supernode *node, const gimple
> *stmt,
> const gcall *call) const;
>void on_read (sm_context *sm_ctxt, const supernode *node, const gimple
> *stmt,
> @@ -170,6 +182,9 @@ private:
>const gimple *stmt, const gcall *call,
>const tree callee_fndecl, const char *attr_name,
>access_directions fd_attr_access_dir) const;
> + void check_for_dup (sm_context *sm_ctxt, const supernode *node,
> + const gimple *stmt, const gcall *call, const tree callee_fndecl,
> + enum dup kind) const;
> };
>
> /* Base diagnostic class relative to fd_state_machine. */
> @@ -723,6 +738,20 @@ fd_state_machine::is_constant_fd_p (state_t state)
> const
>return (state == m_constant_fd);
> }
>
> +fd_state_machine::state_t
> +fd_state_machine::valid_to_unchecked_state (state_t state) const
> +{
> + if (state == m_valid_read_write)
> +return m_unchecked_read_write;
> + else if (state == m_valid_write_only)
> +return m_unchecked_write_only;
> + else if (state == m_valid_read_only)
> +return m_unchecked_read_only;
> + else
> +gcc_unreachable ();
> + return NULL;
> +}
> +
> bool
> fd_state_machine::on_stmt (sm_context *sm_ctxt, const supernode *node,
>const gimple *stmt) const
> @@ -736,6 +765,11 @@ fd_state_machine::on_stmt (sm_context *sm_ctxt, const
> supernode *node,
> return true;
> } // "open"
>
> + if (is_named_call_p (callee_fndecl, "creat", call, 2))
> + {
> + on_creat (sm_ctxt, node, stmt, call);
> + } // "creat"
> +
> if (is_named_call_p (callee_fndecl, "close", call, 1))
> {
> on_close (sm_ctxt, node, stmt, call);
> @@ -754,6 +788,23 @@ fd_state_machine::on_stmt (sm_context *sm_ctxt, const
> supernode *node,
> return true;
> } // "read"
>
> + if (is_named_call_p (callee_fndecl, "dup", call, 1))
> + {
> + check_for_dup (sm_ctxt, node, stmt, call, callee_fndecl,
> DUP_1);
> + return true;
> + }
> +
> + if (is_named_call_p (callee_fndecl, "dup2", call, 2))
> + {
> + check_for_dup (sm_ctxt, node, stmt, call, callee_fndecl,
> DUP_2);
> + return true;
> + }
> +
> + if (is_named_call_p (callee_fndecl, "dup3", call, 3))
> + {
> + check_for_dup (sm_ctxt, node, stmt, ca