Line data Source code
1 : /* A state machine for use in DejaGnu tests, to check that
2 : pattern-matching works as expected.
3 :
4 : Copyright (C) 2019-2026 Free Software Foundation, Inc.
5 : Contributed by David Malcolm <dmalcolm@redhat.com>.
6 :
7 : This file is part of GCC.
8 :
9 : GCC is free software; you can redistribute it and/or modify it
10 : under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3, or (at your option)
12 : any later version.
13 :
14 : GCC is distributed in the hope that it will be useful, but
15 : WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 : General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with GCC; see the file COPYING3. If not see
21 : <http://www.gnu.org/licenses/>. */
22 :
23 : #include "analyzer/common.h"
24 :
25 : #include "tree-pretty-print.h"
26 : #include "diagnostics/event-id.h"
27 :
28 : #include "analyzer/analyzer-logging.h"
29 : #include "analyzer/sm.h"
30 : #include "analyzer/pending-diagnostic.h"
31 : #include "analyzer/call-string.h"
32 : #include "analyzer/program-point.h"
33 : #include "analyzer/store.h"
34 : #include "analyzer/region-model.h"
35 :
36 : #if ENABLE_ANALYZER
37 :
38 : namespace ana {
39 :
40 : namespace {
41 :
42 : /* A state machine for use in DejaGnu tests, to check that
43 : pattern-matching works as expected. */
44 :
45 : class pattern_test_state_machine : public state_machine
46 : {
47 : public:
48 : pattern_test_state_machine (logger *logger);
49 :
50 132 : bool inherited_state_p () const final override { return false; }
51 :
52 : bool on_stmt (sm_context &sm_ctxt,
53 : const gimple *stmt) const final override;
54 :
55 : void on_condition (sm_context &sm_ctxt,
56 : const svalue *lhs,
57 : enum tree_code op,
58 : const svalue *rhs) const final override;
59 :
60 : bool can_purge_p (state_t s) const final override;
61 : };
62 :
63 0 : class pattern_match : public pending_diagnostic_subclass<pattern_match>
64 : {
65 : public:
66 32 : pattern_match (tree lhs, enum tree_code op, tree rhs)
67 32 : : m_lhs (lhs), m_op (op), m_rhs (rhs) {}
68 :
69 622 : const char *get_kind () const final override { return "pattern_match"; }
70 :
71 71 : bool operator== (const pattern_match &other) const
72 : {
73 71 : return (same_tree_p (m_lhs, other.m_lhs)
74 71 : && m_op == other.m_op
75 103 : && same_tree_p (m_rhs, other.m_rhs));
76 : }
77 :
78 64 : int get_controlling_option () const final override
79 : {
80 64 : return 0;
81 : }
82 :
83 32 : bool emit (diagnostic_emission_context &ctxt) final override
84 : {
85 32 : return ctxt.warn ("pattern match on %<%E %s %E%>",
86 32 : m_lhs, op_symbol_code (m_op), m_rhs);
87 : }
88 :
89 : private:
90 : tree m_lhs;
91 : enum tree_code m_op;
92 : tree m_rhs;
93 : };
94 :
95 10 : pattern_test_state_machine::pattern_test_state_machine (logger *logger)
96 10 : : state_machine ("pattern-test", logger)
97 : {
98 0 : }
99 :
100 : bool
101 74 : pattern_test_state_machine::on_stmt (sm_context &sm_ctxt ATTRIBUTE_UNUSED,
102 : const gimple *stmt ATTRIBUTE_UNUSED) const
103 : {
104 74 : return false;
105 : }
106 :
107 : /* Implementation of state_machine::on_condition vfunc for
108 : pattern_test_state_machine.
109 :
110 : Queue a pattern_match diagnostic for any comparison against a
111 : constant. */
112 :
113 : void
114 32 : pattern_test_state_machine::on_condition (sm_context &sm_ctxt,
115 : const svalue *lhs,
116 : enum tree_code op,
117 : const svalue *rhs) const
118 : {
119 32 : tree rhs_cst = rhs->maybe_get_constant ();
120 32 : if (!rhs_cst)
121 0 : return;
122 :
123 32 : if (tree lhs_expr = sm_ctxt.get_diagnostic_tree (lhs))
124 : {
125 32 : sm_ctxt.warn (lhs_expr,
126 32 : std::make_unique<pattern_match> (lhs_expr, op, rhs_cst));
127 : }
128 : }
129 :
130 : bool
131 100 : pattern_test_state_machine::can_purge_p (state_t s ATTRIBUTE_UNUSED) const
132 : {
133 100 : return true;
134 : }
135 :
136 : } // anonymous namespace
137 :
138 : /* Internal interface to this file. */
139 :
140 : std::unique_ptr<state_machine>
141 10 : make_pattern_test_state_machine (logger *logger)
142 : {
143 10 : return std::make_unique<pattern_test_state_machine> (logger);
144 : }
145 :
146 : } // namespace ana
147 :
148 : #endif /* #if ENABLE_ANALYZER */
|