[36/49] analyzer: new file: sm-pattern-test.cc
diff mbox series

Message ID 1573867416-55618-37-git-send-email-dmalcolm@redhat.com
State New
Headers show
Series
  • RFC: Add a static analysis framework to GCC
Related show

Commit Message

David Malcolm Nov. 16, 2019, 1:23 a.m. UTC
This patch adds a custom state machine checker intended purely for DejaGnu
testing of the sm "machinery".

gcc/ChangeLog:
	* analyzer/sm-pattern-test.cc: New file.
---
 gcc/analyzer/sm-pattern-test.cc | 165 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 165 insertions(+)
 create mode 100644 gcc/analyzer/sm-pattern-test.cc

Comments

Jeff Law Dec. 7, 2019, 3:16 p.m. UTC | #1
On Fri, 2019-11-15 at 20:23 -0500, David Malcolm wrote:
> This patch adds a custom state machine checker intended purely for
> DejaGnu
> testing of the sm "machinery".
> 
> gcc/ChangeLog:
> 	* analyzer/sm-pattern-test.cc: New file.
OK when prereqs are all approved.

jeff

Patch
diff mbox series

diff --git a/gcc/analyzer/sm-pattern-test.cc b/gcc/analyzer/sm-pattern-test.cc
new file mode 100644
index 0000000..cf42cfd
--- /dev/null
+++ b/gcc/analyzer/sm-pattern-test.cc
@@ -0,0 +1,165 @@ 
+/* A state machine for use in DejaGnu tests, to check that
+   pattern-matching works as expected.
+
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   Contributed by David Malcolm <dmalcolm@redhat.com>.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "gcc-plugin.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "gimple.h"
+#include "tree-pretty-print.h"
+#include "diagnostic-path.h"
+#include "diagnostic-metadata.h"
+#include "analyzer/analyzer.h"
+#include "analyzer/pending-diagnostic.h"
+#include "analyzer/sm.h"
+
+namespace {
+
+/* A state machine for use in DejaGnu tests, to check that
+   pattern-matching works as expected.  */
+
+class pattern_test_state_machine : public state_machine
+{
+public:
+  pattern_test_state_machine (logger *logger);
+
+  bool inherited_state_p () const FINAL OVERRIDE { return false; }
+
+  bool on_stmt (sm_context *sm_ctxt,
+		const supernode *node,
+		const gimple *stmt) const FINAL OVERRIDE;
+
+  void on_condition (sm_context *sm_ctxt,
+		     const supernode *node,
+		     const gimple *stmt,
+		     tree lhs,
+		     enum tree_code op,
+		     tree rhs) const FINAL OVERRIDE;
+
+  void on_leak (sm_context *sm_ctxt,
+		const supernode *node,
+		const gimple *stmt,
+		tree var,
+		state_machine::state_t state) const FINAL OVERRIDE;
+  bool can_purge_p (state_t s) const FINAL OVERRIDE;
+
+private:
+  state_t m_start;
+};
+
+////////////////////////////////////////////////////////////////////////////
+
+class pattern_match : public pending_diagnostic_subclass<pattern_match>
+{
+public:
+  pattern_match (tree lhs, enum tree_code op, tree rhs)
+  : m_lhs (lhs), m_op (op), m_rhs (rhs) {}
+
+  const char *get_kind () const FINAL OVERRIDE { return "pattern_match"; }
+
+  bool operator== (const pattern_match &other) const
+  {
+    return (m_lhs == other.m_lhs
+	    && m_op == other.m_op
+	    && m_rhs == other.m_rhs);
+  }
+
+  bool emit (rich_location *rich_loc) FINAL OVERRIDE
+  {
+    return warning_at (rich_loc, 0, "pattern match on %<%E %s %E%>",
+		       m_lhs, op_symbol_code (m_op), m_rhs);
+  }
+
+private:
+  tree m_lhs;
+  enum tree_code m_op;
+  tree m_rhs;
+};
+
+////////////////////////////////////////////////////////////////////////////
+
+pattern_test_state_machine::pattern_test_state_machine (logger *logger)
+: state_machine ("pattern-test", logger)
+{
+  m_start = add_state ("start");
+}
+
+bool
+pattern_test_state_machine::on_stmt (sm_context *sm_ctxt ATTRIBUTE_UNUSED,
+				     const supernode *node ATTRIBUTE_UNUSED,
+				     const gimple *stmt ATTRIBUTE_UNUSED) const
+{
+  return false;
+}
+
+/* Implementation of state_machine::on_condition vfunc for
+   pattern_test_state_machine.
+
+   Queue a pattern_match diagnostic for any comparison against a
+   constant.  */
+
+void
+pattern_test_state_machine::on_condition (sm_context *sm_ctxt,
+					  const supernode *node,
+					  const gimple *stmt,
+					  tree lhs,
+					  enum tree_code op,
+					  tree rhs) const
+{
+  if (stmt == NULL)
+    return;
+
+  if (!CONSTANT_CLASS_P (rhs))
+    return;
+
+  pending_diagnostic *diag = new pattern_match (lhs, op, rhs);
+  sm_ctxt->warn_for_state (node, stmt, lhs, m_start, diag);
+}
+
+void
+pattern_test_state_machine::on_leak (sm_context *sm_ctxt ATTRIBUTE_UNUSED,
+				     const supernode *node ATTRIBUTE_UNUSED,
+				     const gimple *stmt ATTRIBUTE_UNUSED,
+				     tree var ATTRIBUTE_UNUSED,
+				     state_machine::state_t state
+				       ATTRIBUTE_UNUSED)
+  const
+{
+  /* Empty.  */
+}
+
+bool
+pattern_test_state_machine::can_purge_p (state_t s ATTRIBUTE_UNUSED) const
+{
+  return true;
+}
+
+} // anonymous namespace
+
+/* Internal interface to this file. */
+
+state_machine *
+make_pattern_test_state_machine (logger *logger)
+{
+  return new pattern_test_state_machine (logger);
+}