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-2024 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 "config.h"
24 : : #define INCLUDE_VECTOR
25 : : #include "system.h"
26 : : #include "coretypes.h"
27 : : #include "make-unique.h"
28 : : #include "tree.h"
29 : : #include "function.h"
30 : : #include "basic-block.h"
31 : : #include "gimple.h"
32 : : #include "tree-pretty-print.h"
33 : : #include "diagnostic-path.h"
34 : : #include "analyzer/analyzer.h"
35 : : #include "diagnostic-event-id.h"
36 : : #include "analyzer/analyzer-logging.h"
37 : : #include "analyzer/sm.h"
38 : : #include "analyzer/pending-diagnostic.h"
39 : : #include "analyzer/call-string.h"
40 : : #include "analyzer/program-point.h"
41 : : #include "analyzer/store.h"
42 : : #include "analyzer/region-model.h"
43 : :
44 : : #if ENABLE_ANALYZER
45 : :
46 : : namespace ana {
47 : :
48 : : namespace {
49 : :
50 : : /* A state machine for use in DejaGnu tests, to check that
51 : : pattern-matching works as expected. */
52 : :
53 : : class pattern_test_state_machine : public state_machine
54 : : {
55 : : public:
56 : : pattern_test_state_machine (logger *logger);
57 : :
58 : 108 : bool inherited_state_p () const final override { return false; }
59 : :
60 : : bool on_stmt (sm_context &sm_ctxt,
61 : : const supernode *node,
62 : : const gimple *stmt) const final override;
63 : :
64 : : void on_condition (sm_context &sm_ctxt,
65 : : const supernode *node,
66 : : const gimple *stmt,
67 : : const svalue *lhs,
68 : : enum tree_code op,
69 : : const svalue *rhs) const final override;
70 : :
71 : : bool can_purge_p (state_t s) const final override;
72 : : };
73 : :
74 : 0 : class pattern_match : public pending_diagnostic_subclass<pattern_match>
75 : : {
76 : : public:
77 : 32 : pattern_match (tree lhs, enum tree_code op, tree rhs)
78 : 32 : : m_lhs (lhs), m_op (op), m_rhs (rhs) {}
79 : :
80 : 320 : const char *get_kind () const final override { return "pattern_match"; }
81 : :
82 : 71 : bool operator== (const pattern_match &other) const
83 : : {
84 : 71 : return (same_tree_p (m_lhs, other.m_lhs)
85 : 71 : && m_op == other.m_op
86 : 103 : && same_tree_p (m_rhs, other.m_rhs));
87 : : }
88 : :
89 : 64 : int get_controlling_option () const final override
90 : : {
91 : 64 : return 0;
92 : : }
93 : :
94 : 32 : bool emit (diagnostic_emission_context &ctxt) final override
95 : : {
96 : 32 : return ctxt.warn ("pattern match on %<%E %s %E%>",
97 : 32 : m_lhs, op_symbol_code (m_op), m_rhs);
98 : : }
99 : :
100 : : private:
101 : : tree m_lhs;
102 : : enum tree_code m_op;
103 : : tree m_rhs;
104 : : };
105 : :
106 : 10 : pattern_test_state_machine::pattern_test_state_machine (logger *logger)
107 : 0 : : state_machine ("pattern-test", logger)
108 : : {
109 : 0 : }
110 : :
111 : : bool
112 : 74 : pattern_test_state_machine::on_stmt (sm_context &sm_ctxt ATTRIBUTE_UNUSED,
113 : : const supernode *node ATTRIBUTE_UNUSED,
114 : : const gimple *stmt ATTRIBUTE_UNUSED) const
115 : : {
116 : 74 : return false;
117 : : }
118 : :
119 : : /* Implementation of state_machine::on_condition vfunc for
120 : : pattern_test_state_machine.
121 : :
122 : : Queue a pattern_match diagnostic for any comparison against a
123 : : constant. */
124 : :
125 : : void
126 : 32 : pattern_test_state_machine::on_condition (sm_context &sm_ctxt,
127 : : const supernode *node,
128 : : const gimple *stmt,
129 : : const svalue *lhs,
130 : : enum tree_code op,
131 : : const svalue *rhs) const
132 : : {
133 : 32 : if (stmt == NULL)
134 : 0 : return;
135 : :
136 : 32 : tree rhs_cst = rhs->maybe_get_constant ();
137 : 32 : if (!rhs_cst)
138 : : return;
139 : :
140 : 32 : if (tree lhs_expr = sm_ctxt.get_diagnostic_tree (lhs))
141 : : {
142 : 32 : sm_ctxt.warn (node, stmt, lhs_expr,
143 : 64 : make_unique<pattern_match> (lhs_expr, op, rhs_cst));
144 : : }
145 : : }
146 : :
147 : : bool
148 : 76 : pattern_test_state_machine::can_purge_p (state_t s ATTRIBUTE_UNUSED) const
149 : : {
150 : 76 : return true;
151 : : }
152 : :
153 : : } // anonymous namespace
154 : :
155 : : /* Internal interface to this file. */
156 : :
157 : : state_machine *
158 : 10 : make_pattern_test_state_machine (logger *logger)
159 : : {
160 : 10 : return new pattern_test_state_machine (logger);
161 : : }
162 : :
163 : : } // namespace ana
164 : :
165 : : #endif /* #if ENABLE_ANALYZER */
|