Branch data 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-2025 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 "diagnostic-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 : 156 : bool inherited_state_p () const final override { return false; }
51 : :
52 : : bool on_stmt (sm_context &sm_ctxt,
53 : : const supernode *node,
54 : : const gimple *stmt) const final override;
55 : :
56 : : void on_condition (sm_context &sm_ctxt,
57 : : const supernode *node,
58 : : const gimple *stmt,
59 : : const svalue *lhs,
60 : : enum tree_code op,
61 : : const svalue *rhs) const final override;
62 : :
63 : : bool can_purge_p (state_t s) const final override;
64 : : };
65 : :
66 : 0 : class pattern_match : public pending_diagnostic_subclass<pattern_match>
67 : : {
68 : : public:
69 : 32 : pattern_match (tree lhs, enum tree_code op, tree rhs)
70 : 32 : : m_lhs (lhs), m_op (op), m_rhs (rhs) {}
71 : :
72 : 318 : const char *get_kind () const final override { return "pattern_match"; }
73 : :
74 : 71 : bool operator== (const pattern_match &other) const
75 : : {
76 : 71 : return (same_tree_p (m_lhs, other.m_lhs)
77 : 71 : && m_op == other.m_op
78 : 103 : && same_tree_p (m_rhs, other.m_rhs));
79 : : }
80 : :
81 : 64 : int get_controlling_option () const final override
82 : : {
83 : 64 : return 0;
84 : : }
85 : :
86 : 32 : bool emit (diagnostic_emission_context &ctxt) final override
87 : : {
88 : 32 : return ctxt.warn ("pattern match on %<%E %s %E%>",
89 : 32 : m_lhs, op_symbol_code (m_op), m_rhs);
90 : : }
91 : :
92 : : private:
93 : : tree m_lhs;
94 : : enum tree_code m_op;
95 : : tree m_rhs;
96 : : };
97 : :
98 : 10 : pattern_test_state_machine::pattern_test_state_machine (logger *logger)
99 : 10 : : state_machine ("pattern-test", logger)
100 : : {
101 : 0 : }
102 : :
103 : : bool
104 : 74 : pattern_test_state_machine::on_stmt (sm_context &sm_ctxt ATTRIBUTE_UNUSED,
105 : : const supernode *node ATTRIBUTE_UNUSED,
106 : : const gimple *stmt ATTRIBUTE_UNUSED) const
107 : : {
108 : 74 : return false;
109 : : }
110 : :
111 : : /* Implementation of state_machine::on_condition vfunc for
112 : : pattern_test_state_machine.
113 : :
114 : : Queue a pattern_match diagnostic for any comparison against a
115 : : constant. */
116 : :
117 : : void
118 : 32 : pattern_test_state_machine::on_condition (sm_context &sm_ctxt,
119 : : const supernode *node,
120 : : const gimple *stmt,
121 : : const svalue *lhs,
122 : : enum tree_code op,
123 : : const svalue *rhs) const
124 : : {
125 : 32 : if (stmt == NULL)
126 : 0 : return;
127 : :
128 : 32 : tree rhs_cst = rhs->maybe_get_constant ();
129 : 32 : if (!rhs_cst)
130 : : return;
131 : :
132 : 32 : if (tree lhs_expr = sm_ctxt.get_diagnostic_tree (lhs))
133 : : {
134 : 32 : sm_ctxt.warn (node, stmt, lhs_expr,
135 : 32 : std::make_unique<pattern_match> (lhs_expr, op, rhs_cst));
136 : : }
137 : : }
138 : :
139 : : bool
140 : 124 : pattern_test_state_machine::can_purge_p (state_t s ATTRIBUTE_UNUSED) const
141 : : {
142 : 124 : return true;
143 : : }
144 : :
145 : : } // anonymous namespace
146 : :
147 : : /* Internal interface to this file. */
148 : :
149 : : std::unique_ptr<state_machine>
150 : 10 : make_pattern_test_state_machine (logger *logger)
151 : : {
152 : 10 : return std::make_unique<pattern_test_state_machine> (logger);
153 : : }
154 : :
155 : : } // namespace ana
156 : :
157 : : #endif /* #if ENABLE_ANALYZER */
|