aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite/gcc.dg/plugin
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/testsuite/gcc.dg/plugin')
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic-test-expressions-1.c422
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-trees-1.c65
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_show_trees.c174
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.c24
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_tree_expression_range.c98
-rw-r--r--gcc/testsuite/gcc.dg/plugin/levenshtein-test-1.c9
-rw-r--r--gcc/testsuite/gcc.dg/plugin/levenshtein_plugin.c64
-rw-r--r--gcc/testsuite/gcc.dg/plugin/plugin.exp5
8 files changed, 847 insertions, 14 deletions
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-expressions-1.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-expressions-1.c
new file mode 100644
index 00000000000..5485aafec01
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-expressions-1.c
@@ -0,0 +1,422 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdiagnostics-show-caret" } */
+
+/* This is a collection of unittests to verify that we're correctly
+ capturing the source code ranges of various kinds of expression.
+
+ It uses the various "diagnostic_test_*_expression_range_plugin"
+ plugins which handles "__emit_expression_range" by generating a warning
+ at the given source range of the input argument. Each of the
+ different plugins do this at a different phase of the internal
+ representation (tree, gimple, etc), so we can verify that the
+ source code range information is valid at each phase.
+
+ We want to accept an expression of any type. To do this in C, we
+ use variadic arguments, but C requires at least one argument before
+ the ellipsis, so we have a dummy one. */
+
+extern void __emit_expression_range (int dummy, ...);
+
+int global;
+
+void test_parentheses (int a, int b)
+{
+ __emit_expression_range (0, (a + b) ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, (a + b) );
+ ~~~^~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, (a + b) * (a - b) ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, (a + b) * (a - b) );
+ ~~~~~~~~^~~~~~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, !(a && b) ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, !(a && b) );
+ ^~~~~~~~~
+ { dg-end-multiline-output "" } */
+}
+
+/* Postfix expressions. ************************************************/
+
+void test_array_reference (int *arr)
+{
+ __emit_expression_range (0, arr[100] ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, arr[100] );
+ ~~~^~~~~
+ { dg-end-multiline-output "" } */
+}
+
+int test_function_call (int p, int q, int r)
+{
+ __emit_expression_range (0, test_function_call (p, q, r) ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, test_function_call (p, q, r) );
+ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ { dg-end-multiline-output "" } */
+ return 0;
+}
+
+struct test_struct
+{
+ int field;
+};
+
+int test_structure_references (struct test_struct *ptr)
+{
+ struct test_struct local;
+ local.field = 42;
+
+ __emit_expression_range (0, local.field ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, local.field );
+ ~~~~~^~~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, ptr->field ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, ptr->field );
+ ~~~^~~~~~~
+ { dg-end-multiline-output "" } */
+}
+
+int test_postfix_incdec (int i)
+{
+ __emit_expression_range (0, i++ ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, i++ );
+ ~^~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, i-- ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, i-- );
+ ~^~
+ { dg-end-multiline-output "" } */
+}
+
+/* Unary operators. ****************************************************/
+
+int test_prefix_incdec (int i)
+{
+ __emit_expression_range (0, ++i ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, ++i );
+ ^~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, --i ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, --i );
+ ^~~
+ { dg-end-multiline-output "" } */
+}
+
+void test_address_operator (void)
+{
+ __emit_expression_range (0, &global ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, &global );
+ ^~~~~~~
+ { dg-end-multiline-output "" } */
+}
+
+void test_indirection (int *ptr)
+{
+ __emit_expression_range (0, *ptr ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, *ptr );
+ ^~~~
+ { dg-end-multiline-output "" } */
+}
+
+void test_unary_minus (int i)
+{
+ __emit_expression_range (0, -i ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, -i );
+ ^~
+ { dg-end-multiline-output "" } */
+}
+
+void test_ones_complement (int i)
+{
+ __emit_expression_range (0, ~i ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, ~i );
+ ^~
+ { dg-end-multiline-output "" } */
+}
+
+void test_logical_negation (int flag)
+{
+ __emit_expression_range (0, !flag ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, !flag );
+ ^~~~~
+ { dg-end-multiline-output "" } */
+}
+
+/* Casts. ****************************************************/
+
+void test_cast (void *ptr)
+{
+ __emit_expression_range (0, (int *)ptr ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, (int *)ptr );
+ ^~~~~~~~~~
+ { dg-end-multiline-output "" } */
+
+}
+
+/* Binary operators. *******************************************/
+
+void test_multiplicative_operators (int lhs, int rhs)
+{
+ __emit_expression_range (0, lhs * rhs ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, lhs * rhs );
+ ~~~~^~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, lhs / rhs ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, lhs / rhs );
+ ~~~~^~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, lhs % rhs ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, lhs % rhs );
+ ~~~~^~~~~
+ { dg-end-multiline-output "" } */
+}
+
+void test_additive_operators (int lhs, int rhs)
+{
+ __emit_expression_range (0, lhs + rhs ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, lhs + rhs );
+ ~~~~^~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, lhs - rhs ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, lhs - rhs );
+ ~~~~^~~~~
+ { dg-end-multiline-output "" } */
+}
+
+void test_shift_operators (int lhs, int rhs)
+{
+ __emit_expression_range (0, lhs << rhs ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, lhs << rhs );
+ ~~~~^~~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, lhs >> rhs ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, lhs >> rhs );
+ ~~~~^~~~~~
+ { dg-end-multiline-output "" } */
+}
+
+void test_relational_operators (int lhs, int rhs)
+{
+ __emit_expression_range (0, lhs < rhs ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, lhs < rhs );
+ ~~~~^~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, lhs > rhs ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, lhs > rhs );
+ ~~~~^~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, lhs <= rhs ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, lhs <= rhs );
+ ~~~~^~~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, lhs >= rhs ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, lhs >= rhs );
+ ~~~~^~~~~~
+ { dg-end-multiline-output "" } */
+}
+
+void test_equality_operators (int lhs, int rhs)
+{
+ __emit_expression_range (0, lhs == rhs ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, lhs == rhs );
+ ~~~~^~~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, lhs != rhs ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, lhs != rhs );
+ ~~~~^~~~~~
+ { dg-end-multiline-output "" } */
+}
+
+void test_bitwise_binary_operators (int lhs, int rhs)
+{
+ __emit_expression_range (0, lhs & rhs ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, lhs & rhs );
+ ~~~~^~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, lhs ^ rhs ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, lhs ^ rhs );
+ ~~~~^~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, lhs | rhs ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, lhs | rhs );
+ ~~~~^~~~~
+ { dg-end-multiline-output "" } */
+}
+
+void test_logical_operators (int lhs, int rhs)
+{
+ __emit_expression_range (0, lhs && rhs ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, lhs && rhs );
+ ~~~~^~~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, lhs || rhs ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, lhs || rhs );
+ ~~~~^~~~~~
+ { dg-end-multiline-output "" } */
+}
+
+/* Conditional operator. *******************************************/
+
+void test_conditional_operators (int flag, int on_true, int on_false)
+{
+ __emit_expression_range (0, flag ? on_true : on_false ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, flag ? on_true : on_false );
+ ~~~~~~~~~~~~~~~^~~~~~~~~~
+ { dg-end-multiline-output "" } */
+}
+
+/* Assignment expressions. *******************************************/
+
+void test_assignment_expressions (int dest, int other)
+{
+ __emit_expression_range (0, dest = other ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, dest = other );
+ ~~~~~^~~~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, dest *= other ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, dest *= other );
+ ~~~~~^~~~~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, dest /= other ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, dest /= other );
+ ~~~~~^~~~~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, dest %= other ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, dest %= other );
+ ~~~~~^~~~~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, dest += other ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, dest += other );
+ ~~~~~^~~~~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, dest -= other ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, dest -= other );
+ ~~~~~^~~~~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, dest <<= other ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, dest <<= other );
+ ~~~~~^~~~~~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, dest >>= other ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, dest >>= other );
+ ~~~~~^~~~~~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, dest &= other ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, dest &= other );
+ ~~~~~^~~~~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, dest ^= other ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, dest ^= other );
+ ~~~~~^~~~~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, dest |= other ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, dest |= other );
+ ~~~~~^~~~~~~~
+ { dg-end-multiline-output "" } */
+}
+
+/* Comma operator. *******************************************/
+
+void test_comma_operator (int a, int b)
+{
+ __emit_expression_range (0, (a++, a + b) ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, (a++, a + b) );
+ ~~~~^~~~~~~~
+ { dg-end-multiline-output "" } */
+}
+
+/* Examples of non-trivial expressions. ****************************/
+
+extern double sqrt (double x);
+
+void test_quadratic (double a, double b, double c)
+{
+ __emit_expression_range (0, b * b - 4 * a * c ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, b * b - 4 * a * c );
+ ~~~~~~^~~~~~~~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0,
+ (-b + sqrt (b * b - 4 * a * c))
+ / (2 * a)); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ (-b + sqrt (b * b - 4 * a * c))
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ / (2 * a));
+ ^~~~~~~~~
+ { dg-end-multiline-output "" } */
+
+}
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-trees-1.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-trees-1.c
new file mode 100644
index 00000000000..7473a07961f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-trees-1.c
@@ -0,0 +1,65 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdiagnostics-show-caret" } */
+
+/* This is an example file for use with
+ diagnostic_plugin_show_trees.c.
+
+ The plugin handles "__show_tree" by recursively dumping
+ the internal structure of the second input argument.
+
+ We want to accept an expression of any type. To do this in C, we
+ use variadic arguments, but C requires at least one argument before
+ the ellipsis, so we have a dummy one. */
+
+extern void __show_tree (int dummy, ...);
+
+extern double sqrt (double x);
+
+void test_quadratic (double a, double b, double c)
+{
+ __show_tree (0,
+ (-b + sqrt (b * b - 4 * a * c))
+ / (2 * a));
+
+/* { dg-begin-multiline-output "" }
+ (-b + sqrt (b * b - 4 * a * c))
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ / (2 * a));
+ ^~~~~~~~~
+ { dg-end-multiline-output "" } */
+
+/* { dg-begin-multiline-output "" }
+ (-b + sqrt (b * b - 4 * a * c))
+ ~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~
+ { dg-end-multiline-output "" } */
+
+/* { dg-begin-multiline-output "" }
+ (-b + sqrt (b * b - 4 * a * c))
+ ^~~~~~~~~~~~~~~~~~~~~~~~
+ { dg-end-multiline-output "" } */
+
+/* { dg-begin-multiline-output "" }
+ (-b + sqrt (b * b - 4 * a * c))
+ ~~~~~~^~~~~~~~~~~
+ { dg-end-multiline-output "" } */
+
+/* { dg-begin-multiline-output "" }
+ (-b + sqrt (b * b - 4 * a * c))
+ ~~^~~
+ { dg-end-multiline-output "" } */
+
+/* { dg-begin-multiline-output "" }
+ (-b + sqrt (b * b - 4 * a * c))
+ ~~~~~~^~~
+ { dg-end-multiline-output "" } */
+
+/* { dg-begin-multiline-output "" }
+ (-b + sqrt (b * b - 4 * a * c))
+ ~~^~~
+ { dg-end-multiline-output "" } */
+
+/* { dg-begin-multiline-output "" }
+ / (2 * a));
+ ~~~^~~~
+ { dg-end-multiline-output "" } */
+}
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_show_trees.c b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_show_trees.c
new file mode 100644
index 00000000000..5a911c17a4e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_show_trees.c
@@ -0,0 +1,174 @@
+/* This plugin recursively dumps the source-code location ranges of
+ expressions, at the pre-gimplification tree stage. */
+/* { dg-options "-O" } */
+
+#include "gcc-plugin.h"
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "stringpool.h"
+#include "toplev.h"
+#include "basic-block.h"
+#include "hash-table.h"
+#include "vec.h"
+#include "ggc.h"
+#include "basic-block.h"
+#include "tree-ssa-alias.h"
+#include "internal-fn.h"
+#include "gimple-fold.h"
+#include "tree-eh.h"
+#include "gimple-expr.h"
+#include "is-a.h"
+#include "gimple.h"
+#include "gimple-iterator.h"
+#include "tree.h"
+#include "tree-pass.h"
+#include "intl.h"
+#include "plugin-version.h"
+#include "diagnostic.h"
+#include "context.h"
+#include "gcc-rich-location.h"
+#include "print-tree.h"
+
+/*
+ Hack: fails with linker error:
+./diagnostic_plugin_show_trees.so: undefined symbol: _ZN17gcc_rich_location8add_exprEP9tree_node
+ since nothing in the tree is using gcc_rich_location::add_expr yet.
+
+ I've tried various workarounds (adding DEBUG_FUNCTION to the
+ method, taking its address), but can't seem to fix it that way.
+ So as a nasty workaround, the following material is copied&pasted
+ from gcc-rich-location.c: */
+
+static bool
+get_range_for_expr (tree expr, location_range *r)
+{
+ if (EXPR_HAS_RANGE (expr))
+ {
+ source_range sr = EXPR_LOCATION_RANGE (expr);
+
+ /* Do we have meaningful data? */
+ if (sr.m_start && sr.m_finish)
+ {
+ r->m_start = expand_location (sr.m_start);
+ r->m_finish = expand_location (sr.m_finish);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/* Add a range to the rich_location, covering expression EXPR. */
+
+void
+gcc_rich_location::add_expr (tree expr)
+{
+ gcc_assert (expr);
+
+ location_range r;
+ r.m_show_caret_p = false;
+ if (get_range_for_expr (expr, &r))
+ add_range (&r);
+}
+
+/* FIXME: end of material taken from gcc-rich-location.c */
+
+int plugin_is_GPL_compatible;
+
+static void
+show_tree (tree node)
+{
+ if (!CAN_HAVE_RANGE_P (node))
+ return;
+
+ gcc_rich_location richloc (EXPR_LOCATION (node));
+ richloc.add_expr (node);
+
+ if (richloc.get_num_locations () < 2)
+ {
+ error_at_rich_loc (&richloc, "range not found");
+ return;
+ }
+
+ enum tree_code code = TREE_CODE (node);
+
+ location_range *range = richloc.get_range (1);
+ inform_at_rich_loc (&richloc,
+ "%s at range %i:%i-%i:%i",
+ get_tree_code_name (code),
+ range->m_start.line,
+ range->m_start.column,
+ range->m_finish.line,
+ range->m_finish.column);
+
+ /* Recurse. */
+ int min_idx = 0;
+ int max_idx = TREE_OPERAND_LENGTH (node);
+ switch (code)
+ {
+ case CALL_EXPR:
+ min_idx = 3;
+ break;
+
+ default:
+ break;
+ }
+
+ for (int i = min_idx; i < max_idx; i++)
+ show_tree (TREE_OPERAND (node, i));
+}
+
+tree
+cb_walk_tree_fn (tree * tp, int * walk_subtrees,
+ void * data ATTRIBUTE_UNUSED)
+{
+ if (TREE_CODE (*tp) != CALL_EXPR)
+ return NULL_TREE;
+
+ tree call_expr = *tp;
+ tree fn = CALL_EXPR_FN (call_expr);
+ if (TREE_CODE (fn) != ADDR_EXPR)
+ return NULL_TREE;
+ fn = TREE_OPERAND (fn, 0);
+ if (TREE_CODE (fn) != FUNCTION_DECL)
+ return NULL_TREE;
+ if (strcmp (IDENTIFIER_POINTER (DECL_NAME (fn)), "__show_tree"))
+ return NULL_TREE;
+
+ /* Get arg 1; print it! */
+ tree arg = CALL_EXPR_ARG (call_expr, 1);
+
+ show_tree (arg);
+
+ return NULL_TREE;
+}
+
+static void
+callback (void *gcc_data, void *user_data)
+{
+ tree fndecl = (tree)gcc_data;
+ walk_tree (&DECL_SAVED_TREE (fndecl), cb_walk_tree_fn, NULL, NULL);
+}
+
+int
+plugin_init (struct plugin_name_args *plugin_info,
+ struct plugin_gcc_version *version)
+{
+ struct register_pass_info pass_info;
+ const char *plugin_name = plugin_info->base_name;
+ int argc = plugin_info->argc;
+ struct plugin_argument *argv = plugin_info->argv;
+
+ if (!plugin_default_version_check (version, &gcc_version))
+ return 1;
+
+ register_callback (plugin_name,
+ PLUGIN_PRE_GENERICIZE,
+ callback,
+ NULL);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.c b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.c
index 8f5724ec27d..158c6124a99 100644
--- a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.c
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.c
@@ -109,7 +109,8 @@ get_loc (unsigned int line_num, unsigned int col_num)
/* Convert from 0-based column numbers to 1-based column numbers. */
source_location loc
- = linemap_position_for_line_and_column (line_map,
+ = linemap_position_for_line_and_column (line_table,
+ line_map,
line_num, col_num + 1);
return loc;
@@ -163,7 +164,7 @@ test_show_locus (function *fun)
if (0 == strcmp (fnname, "test_simple"))
{
const int line = fnstart_line + 2;
- rich_location richloc (get_loc (line, 15));
+ rich_location richloc (line_table, get_loc (line, 15));
richloc.add_range (get_loc (line, 10), get_loc (line, 14), false);
richloc.add_range (get_loc (line, 16), get_loc (line, 16), false);
warning_at_rich_loc (&richloc, 0, "test");
@@ -172,7 +173,7 @@ test_show_locus (function *fun)
if (0 == strcmp (fnname, "test_simple_2"))
{
const int line = fnstart_line + 2;
- rich_location richloc (get_loc (line, 24));
+ rich_location richloc (line_table, get_loc (line, 24));
richloc.add_range (get_loc (line, 6),
get_loc (line, 22), false);
richloc.add_range (get_loc (line, 26),
@@ -183,7 +184,7 @@ test_show_locus (function *fun)
if (0 == strcmp (fnname, "test_multiline"))
{
const int line = fnstart_line + 2;
- rich_location richloc (get_loc (line + 1, 7));
+ rich_location richloc (line_table, get_loc (line + 1, 7));
richloc.add_range (get_loc (line, 7),
get_loc (line, 23), false);
richloc.add_range (get_loc (line + 1, 9),
@@ -194,7 +195,7 @@ test_show_locus (function *fun)
if (0 == strcmp (fnname, "test_many_lines"))
{
const int line = fnstart_line + 2;
- rich_location richloc (get_loc (line + 5, 7));
+ rich_location richloc (line_table, get_loc (line + 5, 7));
richloc.add_range (get_loc (line, 7),
get_loc (line + 4, 65), false);
richloc.add_range (get_loc (line + 5, 9),
@@ -223,7 +224,7 @@ test_show_locus (function *fun)
source_range src_range;
src_range.m_start = get_loc (line, 12);
src_range.m_finish = get_loc (line, 20);
- rich_location richloc (caret);
+ rich_location richloc (line_table, caret);
richloc.set_range (0, src_range, true, false);
warning_at_rich_loc (&richloc, 0, "test");
}
@@ -237,7 +238,7 @@ test_show_locus (function *fun)
source_range src_range;
src_range.m_start = get_loc (line, 90);
src_range.m_finish = get_loc (line, 98);
- rich_location richloc (caret);
+ rich_location richloc (line_table, caret);
richloc.set_range (0, src_range, true, false);
warning_at_rich_loc (&richloc, 0, "test");
}
@@ -248,7 +249,7 @@ test_show_locus (function *fun)
const int line = fnstart_line + 2;
location_t caret_a = get_loc (line, 7);
location_t caret_b = get_loc (line, 11);
- rich_location richloc (caret_a);
+ rich_location richloc (line_table, caret_a);
richloc.add_range (caret_b, caret_b, true);
global_dc->caret_chars[0] = 'A';
global_dc->caret_chars[1] = 'B';
@@ -269,7 +270,7 @@ test_show_locus (function *fun)
const int line = fnstart_line + 3;
location_t caret_a = get_loc (line, 5);
location_t caret_b = get_loc (line - 1, 19);
- rich_location richloc (caret_a);
+ rich_location richloc (line_table, caret_a);
richloc.add_range (caret_b, caret_b, true);
global_dc->caret_chars[0] = '1';
global_dc->caret_chars[1] = '2';
@@ -304,11 +305,6 @@ plugin_init (struct plugin_name_args *plugin_info,
if (!plugin_default_version_check (version, &gcc_version))
return 1;
- /* For now, tell the dc to expect ranges and thus to colorize the source
- lines, not just the carets/underlines. This will be redundant
- once the C frontend generates ranges. */
- global_dc->colorize_source_p = true;
-
for (int i = 0; i < argc; i++)
{
if (0 == strcmp (argv[i].key, "color"))
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_tree_expression_range.c b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_tree_expression_range.c
new file mode 100644
index 00000000000..89cc95acd99
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_tree_expression_range.c
@@ -0,0 +1,98 @@
+/* This plugin verifies the source-code location ranges of
+ expressions, at the pre-gimplification tree stage. */
+/* { dg-options "-O" } */
+
+#include "gcc-plugin.h"
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "stringpool.h"
+#include "toplev.h"
+#include "basic-block.h"
+#include "hash-table.h"
+#include "vec.h"
+#include "ggc.h"
+#include "basic-block.h"
+#include "tree-ssa-alias.h"
+#include "internal-fn.h"
+#include "gimple-fold.h"
+#include "tree-eh.h"
+#include "gimple-expr.h"
+#include "is-a.h"
+#include "gimple.h"
+#include "gimple-iterator.h"
+#include "tree.h"
+#include "tree-pass.h"
+#include "intl.h"
+#include "plugin-version.h"
+#include "diagnostic.h"
+#include "context.h"
+#include "print-tree.h"
+
+int plugin_is_GPL_compatible;
+
+static void
+emit_warning (location_t loc)
+{
+ source_range src_range = get_range_from_loc (line_table, loc);
+ warning_at (loc, 0,
+ "tree range %i:%i-%i:%i",
+ LOCATION_LINE (src_range.m_start),
+ LOCATION_COLUMN (src_range.m_start),
+ LOCATION_LINE (src_range.m_finish),
+ LOCATION_COLUMN (src_range.m_finish));
+}
+
+tree
+cb_walk_tree_fn (tree * tp, int * walk_subtrees,
+ void * data ATTRIBUTE_UNUSED)
+{
+ if (TREE_CODE (*tp) != CALL_EXPR)
+ return NULL_TREE;
+
+ tree call_expr = *tp;
+ tree fn = CALL_EXPR_FN (call_expr);
+ if (TREE_CODE (fn) != ADDR_EXPR)
+ return NULL_TREE;
+ fn = TREE_OPERAND (fn, 0);
+ if (TREE_CODE (fn) != FUNCTION_DECL)
+ return NULL_TREE;
+ if (strcmp (IDENTIFIER_POINTER (DECL_NAME (fn)), "__emit_expression_range"))
+ return NULL_TREE;
+
+ /* Get arg 1; print it! */
+ tree arg = CALL_EXPR_ARG (call_expr, 1);
+
+ emit_warning (EXPR_LOCATION (arg));
+
+ return NULL_TREE;
+}
+
+static void
+callback (void *gcc_data, void *user_data)
+{
+ tree fndecl = (tree)gcc_data;
+ walk_tree (&DECL_SAVED_TREE (fndecl), cb_walk_tree_fn, NULL, NULL);
+}
+
+int
+plugin_init (struct plugin_name_args *plugin_info,
+ struct plugin_gcc_version *version)
+{
+ struct register_pass_info pass_info;
+ const char *plugin_name = plugin_info->base_name;
+ int argc = plugin_info->argc;
+ struct plugin_argument *argv = plugin_info->argv;
+
+ if (!plugin_default_version_check (version, &gcc_version))
+ return 1;
+
+ register_callback (plugin_name,
+ PLUGIN_PRE_GENERICIZE,
+ callback,
+ NULL);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/plugin/levenshtein-test-1.c b/gcc/testsuite/gcc.dg/plugin/levenshtein-test-1.c
new file mode 100644
index 00000000000..ac49992780d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/levenshtein-test-1.c
@@ -0,0 +1,9 @@
+/* Placeholder C source file for unit-testing gcc/spellcheck.c. */
+/* { dg-do compile } */
+/* { dg-options "-O" } */
+
+int
+main (int argc, char **argv)
+{
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/plugin/levenshtein_plugin.c b/gcc/testsuite/gcc.dg/plugin/levenshtein_plugin.c
new file mode 100644
index 00000000000..3e7dc788930
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/levenshtein_plugin.c
@@ -0,0 +1,64 @@
+/* Plugin for unittesting gcc/spellcheck.h. */
+
+#include "config.h"
+#include "gcc-plugin.h"
+#include "system.h"
+#include "coretypes.h"
+#include "spellcheck.h"
+#include "diagnostic.h"
+
+int plugin_is_GPL_compatible;
+
+static void
+levenshtein_distance_unit_test_oneway (const char *a, const char *b,
+ edit_distance_t expected)
+{
+ edit_distance_t actual = levenshtein_distance (a, b);
+ if (actual != expected)
+ error ("levenshtein_distance (\"%s\", \"%s\") : expected: %i got %i",
+ a, b, expected, actual);
+}
+
+
+static void
+levenshtein_distance_unit_test (const char *a, const char *b,
+ edit_distance_t expected)
+{
+ /* Run every test both ways to ensure it's symmetric. */
+ levenshtein_distance_unit_test_oneway (a, b, expected);
+ levenshtein_distance_unit_test_oneway (b, a, expected);
+}
+
+/* Callback handler for the PLUGIN_FINISH event; run
+ levenshtein_distance unit tests here. */
+
+static void
+on_finish (void */*gcc_data*/, void */*user_data*/)
+{
+ levenshtein_distance_unit_test ("", "nonempty", strlen ("nonempty"));
+ levenshtein_distance_unit_test ("saturday", "sunday", 3);
+ levenshtein_distance_unit_test ("foo", "m_foo", 2);
+ levenshtein_distance_unit_test ("hello_world", "HelloWorld", 3);
+ levenshtein_distance_unit_test
+ ("the quick brown fox jumps over the lazy dog", "dog", 40);
+ levenshtein_distance_unit_test
+ ("the quick brown fox jumps over the lazy dog",
+ "the quick brown dog jumps over the lazy fox",
+ 4);
+ levenshtein_distance_unit_test
+ ("Lorem ipsum dolor sit amet, consectetur adipiscing elit,",
+ "All your base are belong to us",
+ 44);
+}
+
+int
+plugin_init (struct plugin_name_args *plugin_info,
+ struct plugin_gcc_version */*version*/)
+{
+ register_callback (plugin_info->base_name,
+ PLUGIN_FINISH,
+ on_finish,
+ NULL); /* void *user_data */
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/plugin/plugin.exp b/gcc/testsuite/gcc.dg/plugin/plugin.exp
index 941bccc4387..06080cce8d2 100644
--- a/gcc/testsuite/gcc.dg/plugin/plugin.exp
+++ b/gcc/testsuite/gcc.dg/plugin/plugin.exp
@@ -66,6 +66,11 @@ set plugin_test_list [list \
{ diagnostic_plugin_test_show_locus.c \
diagnostic-test-show-locus-bw.c \
diagnostic-test-show-locus-color.c } \
+ { diagnostic_plugin_test_tree_expression_range.c \
+ diagnostic-test-expressions-1.c } \
+ { diagnostic_plugin_show_trees.c \
+ diagnostic-test-show-trees-1.c } \
+ { levenshtein_plugin.c levenshtein-test-1.c } \
]
foreach plugin_test $plugin_test_list {