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