public inbox for fortran@gcc.gnu.org
 help / color / mirror / Atom feed
From: Bernhard Reutner-Fischer <rep.dot.nop@gmail.com>
To: fortran@gcc.gnu.org
Cc: gcc-patches@gcc.gnu.org,David Malcolm
	<dmalcolm@redhat.com>,VandeVondele Joost
	<joost.vandevondele@mat.ethz.ch>
Subject: Ping: [Re: [PATCH, fortran, v4] Use Levenshtein spelling suggestions in Fortran FE]
Date: Sun, 03 Jul 2016 22:46:00 -0000	[thread overview]
Message-ID: <6C3ABDCF-FBB7-45E2-9AFD-5C0082FC27D7@gmail.com> (raw)
In-Reply-To: <1466279927-9661-1-git-send-email-rep.dot.nop@gmail.com>

Ping

On June 18, 2016 9:58:47 PM GMT+02:00, Bernhard Reutner-Fischer <rep.dot.nop@gmail.com> wrote:
>Hi,
>
>Ok for trunk?
>
>Changes for v4 -> v3:
>
>- rebased
>- Use 4 argument levenshtein_distance() to save multiple strlen(typo)
>  calls as suggested by dmalcolm
>
>Changes for v2 -> v3:
>
>- rebased
>
>Changes for v1 -> v2:
>
>- subroutines using interfaces
>- keyword arguments (named parameters)
>
>Rewrite C++ autovec in plain C.
>Factor out levenshtein distance handling into a commonly used
>gfc_closest_fuzzy_match().
>
>gcc/fortran/ChangeLog
>
>2015-12-27  Bernhard Reutner-Fischer  <aldot@gcc.gnu.org>
>
>	* gfortran.h (gfc_lookup_function_fuzzy): New declaration.
>	(gfc_closest_fuzzy_match): New declaration.
>	(vec_push): New definition.
>	* misc.c (gfc_closest_fuzzy_match): New definition.
>	* resolve.c: Include spellcheck.h.
>	(lookup_function_fuzzy_find_candidates): New static function.
>	(lookup_uop_fuzzy_find_candidates): Likewise.
>	(lookup_uop_fuzzy): Likewise.
>	(resolve_operator) <INTRINSIC_USER>: Call lookup_uop_fuzzy.
>	(gfc_lookup_function_fuzzy): New definition.
>	(resolve_unknown_f): Call gfc_lookup_function_fuzzy.
>	* interface.c (check_interface0): Likewise.
>	(lookup_arg_fuzzy_find_candidates): New static function.
>	(lookup_arg_fuzzy ): Likewise.
>	(compare_actual_formal): Call lookup_arg_fuzzy.
>	* symbol.c: Include spellcheck.h.
>	(lookup_symbol_fuzzy_find_candidates): New static function.
>	(lookup_symbol_fuzzy): Likewise.
>	(gfc_set_default_type): Call lookup_symbol_fuzzy.
>	(lookup_component_fuzzy_find_candidates): New static function.
>	(lookup_component_fuzzy): Likewise.
>	(gfc_find_component): Call lookup_component_fuzzy.
>
>gcc/testsuite/ChangeLog
>
>2015-12-27  Bernhard Reutner-Fischer  <aldot@gcc.gnu.org>
>
>	* gfortran.dg/spellcheck-operator.f90: New testcase.
>	* gfortran.dg/spellcheck-procedure_1.f90: New testcase.
>	* gfortran.dg/spellcheck-procedure_2.f90: New testcase.
>	* gfortran.dg/spellcheck-structure.f90: New testcase.
>	* gfortran.dg/spellcheck-parameter.f90: New testcase.
>
>---
>
>David Malcolm's nice Levenshtein distance spelling check helpers
>were used in some parts of other frontends. This proposed patch adds
>some spelling corrections to the fortran frontend.
>
>Suggestions are printed if we can find a suitable name, currently
>perusing a very simple cutoff factor:
>/* If more than half of the letters were misspelled, the suggestion is
>   likely to be meaningless.  */
>cutoff = MAX (strlen (typo), strlen (best_guess)) / 2;
>which effectively skips names with less than 4 characters.
>For e.g. structures, one could try to be much smarter in an attempt to
>also provide suggestions for single-letter members/components.
>
>This patch covers (at least partly):
>- user-defined operators
>- structures (types and their components)
>- functions
>- symbols (variables)
>
>If anybody has a testcase where a spelling-suggestion would make sense
>then please pass it along so we maybe can add support for GCC-7.
>
>Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop@gmail.com>
>---
> gcc/fortran/gfortran.h                             |  12 +++
>gcc/fortran/interface.c                            |  72
>+++++++++++++--
> gcc/fortran/misc.c                                 |  41 +++++++++
>gcc/fortran/resolve.c                              | 100
>++++++++++++++++++++-
>gcc/fortran/symbol.c                               |  86
>+++++++++++++++++-
> gcc/testsuite/gfortran.dg/spellcheck-operator.f90  |  30 +++++++
> gcc/testsuite/gfortran.dg/spellcheck-parameter.f90 |  15 ++++
> .../gfortran.dg/spellcheck-procedure_1.f90         |  41 +++++++++
> .../gfortran.dg/spellcheck-procedure_2.f90         |  35 ++++++++
> gcc/testsuite/gfortran.dg/spellcheck-structure.f90 |  35 ++++++++
> 10 files changed, 450 insertions(+), 17 deletions(-)
> create mode 100644 gcc/testsuite/gfortran.dg/spellcheck-operator.f90
> create mode 100644 gcc/testsuite/gfortran.dg/spellcheck-parameter.f90
>create mode 100644 gcc/testsuite/gfortran.dg/spellcheck-procedure_1.f90
>create mode 100644 gcc/testsuite/gfortran.dg/spellcheck-procedure_2.f90
> create mode 100644 gcc/testsuite/gfortran.dg/spellcheck-structure.f90
>
>diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
>index 0bb71cb..5d43c2d 100644
>--- a/gcc/fortran/gfortran.h
>+++ b/gcc/fortran/gfortran.h
>@@ -2682,6 +2682,17 @@ void gfc_done_2 (void);
> 
> int get_c_kind (const char *, CInteropKind_t *);
> 
>+const char *gfc_closest_fuzzy_match (const char *, char **);
>+static inline void
>+vec_push (char **&optr, size_t &osz, const char *elt)
>+{
>+  /* {auto,}vec.safe_push () replacement.  Don't ask..  */
>+  // if (strlen (elt) < 4) return; premature optimization: eliminated
>by cutoff
>+  optr = XRESIZEVEC (char *, optr, osz + 2);
>+  optr[osz] = CONST_CAST (char *, elt);
>+  optr[++osz] = NULL;
>+}
>+
> /* options.c */
> unsigned int gfc_option_lang_mask (void);
> void gfc_init_options_struct (struct gcc_options *);
>@@ -3103,6 +3114,7 @@ bool gfc_type_is_extensible (gfc_symbol *);
> bool gfc_resolve_intrinsic (gfc_symbol *, locus *);
> bool gfc_explicit_interface_required (gfc_symbol *, char *, int);
> extern int gfc_do_concurrent_flag;
>+const char* gfc_lookup_function_fuzzy (const char *, gfc_symtree *);
> 
> 
> /* array.c */
>diff --git a/gcc/fortran/interface.c b/gcc/fortran/interface.c
>index b012de5..bef514c 100644
>--- a/gcc/fortran/interface.c
>+++ b/gcc/fortran/interface.c
>@@ -1694,13 +1694,27 @@ check_interface0 (gfc_interface *p, const char
>*interface_name)
> 	   || !p->sym->attr.if_source)
> 	  && !gfc_fl_struct (p->sym->attr.flavor))
> 	{
>+	  const char *guessed
>+	    = gfc_lookup_function_fuzzy (p->sym->name, p->sym->ns->sym_root);
>+
> 	  if (p->sym->attr.external)
>-	    gfc_error ("Procedure %qs in %s at %L has no explicit interface",
>-		       p->sym->name, interface_name, &p->sym->declared_at);
>+	    if (guessed)
>+	      gfc_error ("Procedure %qs in %s at %L has no explicit
>interface"
>+			 "; did you mean %qs?",
>+			 p->sym->name, interface_name, &p->sym->declared_at,
>+			 guessed);
>+	    else
>+	      gfc_error ("Procedure %qs in %s at %L has no explicit
>interface",
>+			 p->sym->name, interface_name, &p->sym->declared_at);
> 	  else
>-	    gfc_error ("Procedure %qs in %s at %L is neither function nor "
>-		       "subroutine", p->sym->name, interface_name,
>-		      &p->sym->declared_at);
>+	    if (guessed)
>+	      gfc_error ("Procedure %qs in %s at %L is neither function nor "
>+			 "subroutine; did you mean %qs?", p->sym->name,
>+			interface_name, &p->sym->declared_at, guessed);
>+	    else
>+	      gfc_error ("Procedure %qs in %s at %L is neither function nor "
>+			 "subroutine", p->sym->name, interface_name,
>+			&p->sym->declared_at);
> 	  return 1;
> 	}
> 
>@@ -2684,6 +2698,31 @@ is_procptr_result (gfc_expr *expr)
> }
> 
> 
>+/* Recursively append candidate argument ARG to CANDIDATES.  Store the
>+   number of total candidates in CANDIDATES_LEN.  */
>+
>+static void
>+lookup_arg_fuzzy_find_candidates (gfc_formal_arglist *arg,
>+				  char **&candidates,
>+				  size_t &candidates_len)
>+{
>+  for (gfc_formal_arglist *p = arg; p && p->sym; p = p->next)
>+    vec_push (candidates, candidates_len, p->sym->name);
>+}
>+
>+
>+/* Lookup argument ARG fuzzily, taking names in ARGUMENTS into
>account.  */
>+
>+static const char*
>+lookup_arg_fuzzy (const char *arg, gfc_formal_arglist *arguments)
>+{
>+  char **candidates = NULL;
>+  size_t candidates_len = 0;
>+  lookup_arg_fuzzy_find_candidates (arguments, candidates,
>candidates_len);
>+  return gfc_closest_fuzzy_match (arg, candidates);
>+}
>+
>+
> /* Given formal and actual argument lists, see if they are compatible.
>    If they are compatible, the actual argument list is sorted to
>    correspond with the formal list, and elements for missing optional
>@@ -2736,8 +2775,16 @@ compare_actual_formal (gfc_actual_arglist **ap,
>gfc_formal_arglist *formal,
> 	  if (f == NULL)
> 	    {
> 	      if (where)
>-		gfc_error ("Keyword argument %qs at %L is not in "
>-			   "the procedure", a->name, &a->expr->where);
>+		{
>+		  const char *guessed = lookup_arg_fuzzy (a->name, formal);
>+		  if (guessed)
>+		    gfc_error ("Keyword argument %qs at %L is not in "
>+			       "the procedure; did you mean %qs?",
>+			       a->name, &a->expr->where, guessed);
>+		  else
>+		    gfc_error ("Keyword argument %qs at %L is not in "
>+			       "the procedure", a->name, &a->expr->where);
>+		}
> 	      return 0;
> 	    }
> 
>@@ -3436,8 +3483,15 @@ gfc_procedure_use (gfc_symbol *sym,
>gfc_actual_arglist **ap, locus *where)
>     {
>if (sym->ns->has_implicit_none_export && sym->attr.proc ==
>PROC_UNKNOWN)
> 	{
>-	  gfc_error ("Procedure %qs called at %L is not explicitly declared",
>-		     sym->name, where);
>+	  const char *guessed
>+	    = gfc_lookup_function_fuzzy (sym->name, sym->ns->sym_root);
>+	  if (guessed)
>+	    gfc_error ("Procedure %qs called at %L is not explicitly
>declared"
>+		       "; did you mean %qs?",
>+		       sym->name, where, guessed);
>+	  else
>+	    gfc_error ("Procedure %qs called at %L is not explicitly
>declared",
>+		       sym->name, where);
> 	  return false;
> 	}
>       if (warn_implicit_interface)
>diff --git a/gcc/fortran/misc.c b/gcc/fortran/misc.c
>index 1747ff2..dd17f46 100644
>--- a/gcc/fortran/misc.c
>+++ b/gcc/fortran/misc.c
>@@ -22,6 +22,7 @@ along with GCC; see the file COPYING3.  If not see
> #include "system.h"
> #include "coretypes.h"
> #include "gfortran.h"
>+#include "spellcheck.h"
> 
> 
> /* Initialize a typespec to unknown.  */
>@@ -280,3 +281,43 @@ get_c_kind(const char *c_kind_name, CInteropKind_t
>kinds_table[])
> 
>   return ISOCBINDING_INVALID;
> }
>+
>+
>+/* For a given name TYPO, determine the best candidate from CANDIDATES
>+   perusing Levenshtein distance.  Frees CANDIDATES before returning. 
>*/
>+
>+const char *
>+gfc_closest_fuzzy_match (const char *typo, char **candidates)
>+{
>+  /* Determine closest match.  */
>+  const char *best = NULL;
>+  char **cand = candidates;
>+  edit_distance_t best_distance = MAX_EDIT_DISTANCE;
>+  const size_t tl = strlen (typo);
>+
>+  while (cand && *cand)
>+    {
>+      edit_distance_t dist = levenshtein_distance (typo, tl, *cand,
>+	  strlen (*cand));
>+      if (dist < best_distance)
>+	{
>+	   best_distance = dist;
>+	   best = *cand;
>+	}
>+      cand++;
>+    }
>+  /* If more than half of the letters were misspelled, the suggestion
>is
>+     likely to be meaningless.  */
>+  if (best)
>+    {
>+      unsigned int cutoff = MAX (tl, strlen (best)) / 2;
>+
>+      if (best_distance > cutoff)
>+	{
>+	  XDELETEVEC (candidates);
>+	  return NULL;
>+	}
>+      XDELETEVEC (candidates);
>+    }
>+  return best;
>+}
>diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
>index 77f8c10..089afa3 100644
>--- a/gcc/fortran/resolve.c
>+++ b/gcc/fortran/resolve.c
>@@ -2693,6 +2693,43 @@ resolve_specific_f (gfc_expr *expr)
>   return true;
> }
> 
>+/* Recursively append candidate SYM to CANDIDATES.  Store the number
>of
>+   candidates in CANDIDATES_LEN.  */
>+
>+static void
>+lookup_function_fuzzy_find_candidates (gfc_symtree *sym,
>+				       char **&candidates,
>+				       size_t &candidates_len)
>+{
>+  gfc_symtree *p;
>+
>+  if (sym == NULL)
>+    return;
>+  if ((sym->n.sym->ts.type != BT_UNKNOWN || sym->n.sym->attr.external)
>+      && sym->n.sym->attr.flavor == FL_PROCEDURE)
>+    vec_push (candidates, candidates_len, sym->name);
>+
>+  p = sym->left;
>+  if (p)
>+    lookup_function_fuzzy_find_candidates (p, candidates,
>candidates_len);
>+
>+  p = sym->right;
>+  if (p)
>+    lookup_function_fuzzy_find_candidates (p, candidates,
>candidates_len);
>+}
>+
>+
>+/* Lookup function FN fuzzily, taking names in SYMROOT into account. 
>*/
>+
>+const char*
>+gfc_lookup_function_fuzzy (const char *fn, gfc_symtree *symroot)
>+{
>+  char **candidates = NULL;
>+  size_t candidates_len = 0;
>+  lookup_function_fuzzy_find_candidates (symroot, candidates,
>candidates_len);
>+  return gfc_closest_fuzzy_match (fn, candidates);
>+}
>+
> 
> /* Resolve a procedure call not known to be generic nor specific.  */
> 
>@@ -2743,8 +2780,15 @@ set_type:
> 
>       if (ts->type == BT_UNKNOWN)
> 	{
>-	  gfc_error ("Function %qs at %L has no IMPLICIT type",
>-		     sym->name, &expr->where);
>+	  const char *guessed
>+	    = gfc_lookup_function_fuzzy (sym->name, sym->ns->sym_root);
>+	  if (guessed)
>+	    gfc_error ("Function %qs at %L has no IMPLICIT type"
>+		       "; did you mean %qs?",
>+		       sym->name, &expr->where, guessed);
>+	  else
>+	    gfc_error ("Function %qs at %L has no IMPLICIT type",
>+		       sym->name, &expr->where);
> 	  return false;
> 	}
>       else
>@@ -3516,6 +3560,46 @@ compare_shapes (gfc_expr *op1, gfc_expr *op2)
> }
> 
> 
>+/* Recursively append candidate UOP to CANDIDATES.  Store the number
>of
>+   candidates in CANDIDATES_LEN.  */
>+static void
>+lookup_uop_fuzzy_find_candidates (gfc_symtree *uop,
>+				  char **&candidates,
>+				  size_t &candidates_len)
>+{
>+  gfc_symtree *p;
>+
>+  if (uop == NULL)
>+    return;
>+
>+  /* Not sure how to properly filter here.  Use all for a start.
>+     n.uop.op is NULL for empty interface operators (is that legal?)
>disregard
>+     these as i suppose they don't make terribly sense.  */
>+
>+  if (uop->n.uop->op != NULL)
>+    vec_push (candidates, candidates_len, uop->name);
>+
>+  p = uop->left;
>+  if (p)
>+    lookup_uop_fuzzy_find_candidates (p, candidates, candidates_len);
>+
>+  p = uop->right;
>+  if (p)
>+    lookup_uop_fuzzy_find_candidates (p, candidates, candidates_len);
>+}
>+
>+/* Lookup user-operator OP fuzzily, taking names in UOP into account. 
>*/
>+
>+static const char*
>+lookup_uop_fuzzy (const char *op, gfc_symtree *uop)
>+{
>+  char **candidates = NULL;
>+  size_t candidates_len = 0;
>+  lookup_uop_fuzzy_find_candidates (uop, candidates, candidates_len);
>+  return gfc_closest_fuzzy_match (op, candidates);
>+}
>+
>+
>/* Resolve an operator expression node.  This can involve replacing the
>    operation with a user defined function call.  */
> 
>@@ -3714,8 +3798,16 @@ resolve_operator (gfc_expr *e)
> 
>     case INTRINSIC_USER:
>       if (e->value.op.uop->op == NULL)
>-	sprintf (msg, _("Unknown operator %%<%s%%> at %%L"),
>-		 e->value.op.uop->name);
>+	{
>+	  const char *name = e->value.op.uop->name;
>+	  const char *guessed;
>+	  guessed = lookup_uop_fuzzy (name, e->value.op.uop->ns->uop_root);
>+	  if (guessed)
>+	    sprintf (msg, _("Unknown operator %%<%s%%> at %%L; did you mean
>'%s'?"),
>+		name, guessed);
>+	  else
>+	    sprintf (msg, _("Unknown operator %%<%s%%> at %%L"), name);
>+	}
>       else if (op2 == NULL)
> 	sprintf (msg, _("Operand of user operator %%<%s%%> at %%L is %s"),
> 		 e->value.op.uop->name, gfc_typename (&op1->ts));
>diff --git a/gcc/fortran/symbol.c b/gcc/fortran/symbol.c
>index 0ee7dec..776610c 100644
>--- a/gcc/fortran/symbol.c
>+++ b/gcc/fortran/symbol.c
>@@ -236,6 +236,44 @@ gfc_get_default_type (const char *name,
>gfc_namespace *ns)
> }
> 
> 
>+/* Recursively append candidate SYM to CANDIDATES.  Store the number
>of
>+   candidates in CANDIDATES_LEN.  */
>+
>+static void
>+lookup_symbol_fuzzy_find_candidates (gfc_symtree *sym,
>+				     char **&candidates,
>+				     size_t &candidates_len)
>+{
>+  gfc_symtree *p;
>+
>+  if (sym == NULL)
>+    return;
>+
>+  if (sym->n.sym->ts.type != BT_UNKNOWN && sym->n.sym->ts.type !=
>BT_PROCEDURE)
>+    vec_push (candidates, candidates_len, sym->name);
>+  p = sym->left;
>+  if (p)
>+    lookup_symbol_fuzzy_find_candidates (p, candidates,
>candidates_len);
>+
>+  p = sym->right;
>+  if (p)
>+    lookup_symbol_fuzzy_find_candidates (p, candidates,
>candidates_len);
>+}
>+
>+
>+/* Lookup symbol SYM_NAME fuzzily, taking names in SYMBOL into
>account.  */
>+
>+static const char*
>+lookup_symbol_fuzzy (const char *sym_name, gfc_symbol *symbol)
>+{
>+  char **candidates = NULL;
>+  size_t candidates_len = 0;
>+  lookup_symbol_fuzzy_find_candidates (symbol->ns->sym_root,
>candidates,
>+				       candidates_len);
>+  return gfc_closest_fuzzy_match (sym_name, candidates);
>+}
>+
>+
> /* Given a pointer to a symbol, set its type according to the first
>    letter of its name.  Fails if the letter in question has no default
>    type.  */
>@@ -254,8 +292,14 @@ gfc_set_default_type (gfc_symbol *sym, int
>error_flag, gfc_namespace *ns)
>     {
>       if (error_flag && !sym->attr.untyped)
> 	{
>-	  gfc_error ("Symbol %qs at %L has no IMPLICIT type",
>-		     sym->name, &sym->declared_at);
>+	  const char *guessed = lookup_symbol_fuzzy (sym->name, sym);
>+	  if (guessed)
>+	    gfc_error ("Symbol %qs at %L has no IMPLICIT type"
>+		       "; did you mean %qs?",
>+		       sym->name, &sym->declared_at, guessed);
>+	  else
>+	    gfc_error ("Symbol %qs at %L has no IMPLICIT type",
>+		       sym->name, &sym->declared_at);
> 	  sym->attr.untyped = 1; /* Ensure we only give an error once.  */
> 	}
> 
>@@ -2233,6 +2277,32 @@ find_union_component (gfc_symbol *un, const char
>*name,
> }
> 
> 
>+/* Recursively append candidate COMPONENT structures to CANDIDATES. 
>Store
>+   the number of total candidates in CANDIDATES_LEN.  */
>+
>+static void
>+lookup_component_fuzzy_find_candidates (gfc_component *component,
>+					char **&candidates,
>+					size_t &candidates_len)
>+{
>+  for (gfc_component *p = component; p; p = p->next)
>+    vec_push (candidates, candidates_len, p->name);
>+}
>+
>+
>+/* Lookup component MEMBER fuzzily, taking names in COMPONENT into
>account.  */
>+
>+static const char*
>+lookup_component_fuzzy (const char *member, gfc_component *component)
>+{
>+  char **candidates = NULL;
>+  size_t candidates_len = 0;
>+  lookup_component_fuzzy_find_candidates (component, candidates,
>+					  candidates_len);
>+  return gfc_closest_fuzzy_match (member, candidates);
>+}
>+
>+
> /* Given a derived type node and a component name, try to locate the
>    component structure.  Returns the NULL pointer if the component is
>not found or the components are private.  If noaccess is set, no access
>@@ -2330,8 +2400,16 @@ gfc_find_component (gfc_symbol *sym, const char
>*name,
>     }
> 
>   if (p == NULL && !silent)
>-    gfc_error ("%qs at %C is not a member of the %qs structure",
>-	       name, sym->name);
>+    {
>+      const char *guessed = lookup_component_fuzzy (name,
>sym->components);
>+      if (guessed)
>+	gfc_error ("%qs at %C is not a member of the %qs structure"
>+		   "; did you mean %qs?",
>+		   name, sym->name, guessed);
>+      else
>+	gfc_error ("%qs at %C is not a member of the %qs structure",
>+		   name, sym->name);
>+    }
> 
>   /* Component was found; build the ultimate component reference. */
>   if (p != NULL && ref)
>diff --git a/gcc/testsuite/gfortran.dg/spellcheck-operator.f90
>b/gcc/testsuite/gfortran.dg/spellcheck-operator.f90
>new file mode 100644
>index 0000000..810a770
>--- /dev/null
>+++ b/gcc/testsuite/gfortran.dg/spellcheck-operator.f90
>@@ -0,0 +1,30 @@
>+! { dg-do compile }
>+! test levenshtein based spelling suggestions
>+
>+module mymod1
>+  implicit none
>+  contains
>+    function something_good (iarg1)
>+      integer :: something_good
>+      integer, intent(in) :: iarg1
>+      something_good = iarg1 + 42
>+    end function something_good
>+end module mymod1
>+
>+program spellchekc
>+  use mymod1
>+  implicit none
>+
>+  interface operator (.mywrong.)
>+    module procedure something_wring ! { dg-error "Procedure
>.something_wring. in operator interface .mywrong. at .1. is neither
>function nor subroutine; did you mean .something_good.\\?|User operator
>procedure .something_wring. at .1. must be a FUNCTION" }
>+  end interface
>+
>+  interface operator (.mygood.)
>+    module procedure something_good
>+  end interface
>+
>+  integer :: i, j, added
>+  i = 0
>+  j = 0
>+  added = .mygoof. j ! { dg-error "Unknown operator .mygoof. at .1.;
>did you mean .mygood.\\?" }
>+end program spellchekc
>diff --git a/gcc/testsuite/gfortran.dg/spellcheck-parameter.f90
>b/gcc/testsuite/gfortran.dg/spellcheck-parameter.f90
>new file mode 100644
>index 0000000..715c5ab
>--- /dev/null
>+++ b/gcc/testsuite/gfortran.dg/spellcheck-parameter.f90
>@@ -0,0 +1,15 @@
>+! { dg-do compile }
>+! Contributed by Joost VandeVondele
>+! test levenshtein based spelling suggestions for keyword arguments
>+
>+module test
>+contains
>+  subroutine mysub(iarg1)
>+    integer :: iarg1
>+  end subroutine
>+end module
>+
>+use test
>+call mysub(iarg=1) ! { dg-error "Keyword argument .iarg. at .1. is not
>in the procedure; did you mean .iarg1.\\?" }
>+
>+end
>diff --git a/gcc/testsuite/gfortran.dg/spellcheck-procedure_1.f90
>b/gcc/testsuite/gfortran.dg/spellcheck-procedure_1.f90
>new file mode 100644
>index 0000000..3b7f716
>--- /dev/null
>+++ b/gcc/testsuite/gfortran.dg/spellcheck-procedure_1.f90
>@@ -0,0 +1,41 @@
>+! { dg-do compile }
>+! test levenshtein based spelling suggestions
>+
>+module mymod1
>+  implicit none
>+  contains
>+    function something_else (iarg1)
>+      integer :: something_else
>+      integer, intent(in) :: iarg1
>+      something_else = iarg1 + 42
>+    end function something_else
>+    function add_fourtytwo (iarg1)
>+      integer :: add_fourtytwo
>+      integer, intent(in) :: iarg1
>+      add_fourtytwo = iarg1 + 42
>+    end function add_fourtytwo
>+end module mymod1
>+
>+function myadd(iarg1, iarg2)
>+  implicit none
>+  integer :: myadd
>+  integer, intent(in) :: iarg1, iarg2
>+  myadd = iarg1 + iarg2
>+end function myadd
>+
>+program spellchekc
>+  use mymod1, something_good => something_else
>+  implicit none
>+
>+  integer :: myadd, i, j, myvar
>+  i = 0
>+  j = 0
>+
>+  j = something_goof(j) ! { dg-error "no IMPLICIT type; did you mean
>.something_good.\\?" }
>+  j = myaddd(i, j) ! { dg-error "no IMPLICIT type; did you mean
>.myadd.\\?" }
>+  if (j /= 42) call abort
>+  j = add_fourtytow(i, j) ! { dg-error "no IMPLICIT type; did you mean
>.add_fourtytwo.\\?" }
>+  myval = myadd(i, j) ! { dg-error "no IMPLICIT type; did you mean
>.myvar.\\?" }
>+  if (j /= 42 * 2) call abort
>+
>+end program spellchekc
>diff --git a/gcc/testsuite/gfortran.dg/spellcheck-procedure_2.f90
>b/gcc/testsuite/gfortran.dg/spellcheck-procedure_2.f90
>new file mode 100644
>index 0000000..a6ea5f9
>--- /dev/null
>+++ b/gcc/testsuite/gfortran.dg/spellcheck-procedure_2.f90
>@@ -0,0 +1,35 @@
>+! { dg-do compile }
>+! test levenshtein based spelling suggestions
>+
>+
>+program spellchekc
>+  implicit none (external) ! { dg-warning "GNU Extension: IMPORT NONE
>with spec list" }
>+
>+  interface
>+    subroutine bark_unless_zero(iarg)
>+      implicit none
>+      integer, intent(in) :: iarg
>+    end subroutine bark_unless_zero
>+  end interface
>+
>+  integer :: i
>+  i = 0
>+
>+  if (i /= 1) call abort
>+  call bark_unless_0(i) ! { dg-error "not explicitly declared; did you
>mean .bark_unless_zero.\\?" }
>+!  call complain_about_0(i) ! { -dg-error "not explicitly declared;
>did you mean .complain_about_zero.\\?" }
>+
>+contains
>+! We cannot reliably see this ATM, would need an unambiguous bit
>somewhere
>+  subroutine complain_about_zero(iarg)
>+    integer, intent(in) :: iarg
>+    if (iarg /= 0) call abort
>+  end subroutine complain_about_zero
>+
>+end program spellchekc
>+
>+subroutine bark_unless_zero(iarg)
>+  implicit none
>+  integer, intent(in) :: iarg
>+  if (iarg /= 0) call abort
>+end subroutine bark_unless_zero
>diff --git a/gcc/testsuite/gfortran.dg/spellcheck-structure.f90
>b/gcc/testsuite/gfortran.dg/spellcheck-structure.f90
>new file mode 100644
>index 0000000..929e05f
>--- /dev/null
>+++ b/gcc/testsuite/gfortran.dg/spellcheck-structure.f90
>@@ -0,0 +1,35 @@
>+! { dg-do compile }
>+! test levenshtein based spelling suggestions
>+implicit none
>+
>+!!!!!!!!!!!!!! structure tests !!!!!!!!!!!!!!
>+type type1
>+   real :: radius
>+   integer :: i
>+end type type1
>+
>+type type2
>+  integer :: myint
>+  type(type1) :: mytype
>+end type type2
>+
>+type type3
>+  type(type2) :: type_2
>+end type type3
>+type type4
>+  type(type3) :: type_3
>+end type type4
>+
>+type(type1) :: t1
>+t1%radiuz = .0 ! { dg-error ".radiuz. at .1. is not a member of the
>.type1. structure; did you mean .radius.\\?" }
>+t1%x = .0 ! { dg-error ".x. at .1. is not a member of the .type1.
>structure" }
>+type(type2) :: t2
>+t2%mytape%radius = .0 ! { dg-error ".mytape. at .1. is not a member of
>the .type2. structure; did you mean .mytype.\\?" }
>+t2%mytype%radious = .0 ! { dg-error ".radious. at .1. is not a member
>of the .type1. structure; did you mean .radius.\\?" }
>+type(type4) :: t4
>+t4%type_3%type_2%mytype%radium = 88.0 ! { dg-error ".radium. at .1. is
>not a member of the .type1. structure; did you mean .radius.\\?" }
>+
>+!!!!!!!!!!!!!! symbol tests !!!!!!!!!!!!!!
>+integer :: iarg1
>+iarg2 = 1 ! { dg-error "Symbol .iarg2. at .1. has no IMPLICIT type;
>did you mean .iarg1.\\?" }
>+end


  parent reply	other threads:[~2016-07-03 22:46 UTC|newest]

Thread overview: 94+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-12-01 12:55 [PATCH] Use gfc_add_*_component defines where appropriate Bernhard Reutner-Fischer
2015-12-01 12:55 ` [PATCH] Commentary typo fix for gfc_typenode_for_spec() Bernhard Reutner-Fischer
2015-12-01 16:00   ` Steve Kargl
2016-06-18 20:07     ` Bernhard Reutner-Fischer
2015-12-01 12:55 ` [PATCH] Derive interface buffers from max name length Bernhard Reutner-Fischer
2015-12-01 14:52   ` Janne Blomqvist
2015-12-01 16:51     ` Bernhard Reutner-Fischer
2015-12-03  9:46       ` Janne Blomqvist
2016-06-18 19:46         ` Bernhard Reutner-Fischer
2017-10-19  8:03           ` Bernhard Reutner-Fischer
2017-10-20 22:46             ` Bernhard Reutner-Fischer
2017-10-21 15:18               ` Thomas Koenig
2017-10-21 18:11                 ` Bernhard Reutner-Fischer
2017-10-31 20:35                   ` Bernhard Reutner-Fischer
2018-09-03 16:05                     ` Bernhard Reutner-Fischer
2018-09-05 14:57                       ` [PATCH,FORTRAN 02/29] Use stringpool for gfc_match_defined_op_name() Bernhard Reutner-Fischer
2018-09-05 14:57                       ` [PATCH,FORTRAN 04/29] Use stringpool for gfc_match_generic_spec Bernhard Reutner-Fischer
2018-09-05 14:57                       ` [PATCH,FORTRAN 01/29] gdbinit: break on gfc_internal_error Bernhard Reutner-Fischer
2021-10-29 18:58                         ` Bernhard Reutner-Fischer
2021-10-29 22:13                           ` Jerry D
2021-10-30 18:25                             ` Bernhard Reutner-Fischer
2018-09-05 14:57                       ` [PATCH,FORTRAN 09/29] Use stringpool for modules Bernhard Reutner-Fischer
2018-09-05 18:44                         ` Janne Blomqvist
2018-09-05 20:59                           ` Bernhard Reutner-Fischer
2018-09-05 14:57                       ` [PATCH,FORTRAN 06/29] Use stringpool for association_list Bernhard Reutner-Fischer
2018-09-05 14:57                       ` [PATCH,FORTRAN 00/29] Move towards stringpool, part 1 Bernhard Reutner-Fischer
2018-09-05 18:57                         ` Janne Blomqvist
2018-09-07  8:09                           ` Bernhard Reutner-Fischer
2018-09-19 14:40                             ` Bernhard Reutner-Fischer
2023-04-13 21:04                               ` Bernhard Reutner-Fischer
     [not found]                         ` <cba81495-832c-2b95-3c30-d2ef819ea9fb@charter.net>
     [not found]                           ` <CAC1BbcThL4Cj=mVRuGg2p8jUipwLOeosB7kwoVD27myRnKcgZA@mail.gmail.com>
2021-04-18 21:30                             ` Bernhard Reutner-Fischer
2018-09-05 14:57                       ` [PATCH,FORTRAN 13/29] Use stringpool for intrinsics and common Bernhard Reutner-Fischer
2018-09-05 14:57                       ` [PATCH,FORTRAN 07/29] Use stringpool for some gfc_code2string return values Bernhard Reutner-Fischer
2018-09-05 14:57                       ` [PATCH,FORTRAN 03/29] Use stringpool for gfc_get_name Bernhard Reutner-Fischer
2018-09-05 14:57                       ` [PATCH,FORTRAN 08/29] Add uop/name helpers Bernhard Reutner-Fischer
2018-09-05 14:58                       ` [PATCH,FORTRAN 29/29] PR87103: Remove max symbol length check from gfc_new_symbol Bernhard Reutner-Fischer
2018-09-05 14:58                       ` [PATCH,FORTRAN 23/29] Use stringpool for module binding_label Bernhard Reutner-Fischer
2018-09-05 14:58                       ` [PATCH,FORTRAN 10/29] Do not copy name for check_function_name Bernhard Reutner-Fischer
2018-09-05 14:58                       ` [PATCH,FORTRAN 27/29] Use stringpool for OMP clause reduction code Bernhard Reutner-Fischer
2018-09-05 14:58                       ` [PATCH,FORTRAN 25/29] Use stringpool on loading module symbols Bernhard Reutner-Fischer
2018-09-19 22:55                         ` [PATCH,FORTRAN v2] " Bernhard Reutner-Fischer
2018-09-05 14:58                       ` [PATCH,FORTRAN 21/29] Use stringpool for module tbp Bernhard Reutner-Fischer
2018-09-05 14:58                       ` [PATCH,FORTRAN 05/29] Use stringpool for gfc_match("%n") Bernhard Reutner-Fischer
2018-09-05 14:58                       ` [PATCH,FORTRAN 24/29] Use stringpool for intrinsic functions Bernhard Reutner-Fischer
2018-09-05 14:58                       ` [PATCH,FORTRAN 14/29] Fix write_omp_udr for user-operator REDUCTIONs Bernhard Reutner-Fischer
2018-09-05 14:58                       ` [PATCH,FORTRAN 22/29] Use stringpool in class and procedure-pointer result Bernhard Reutner-Fischer
2018-09-05 14:58                       ` [PATCH,FORTRAN 11/29] Do pointer comparison instead of strcmp Bernhard Reutner-Fischer
2018-09-05 14:58                       ` [PATCH,FORTRAN 26/29] Use stringpool for mangled common names Bernhard Reutner-Fischer
2018-09-05 14:58                       ` [PATCH,FORTRAN 12/29] Use stringpool for remaining names Bernhard Reutner-Fischer
2018-09-05 15:02                       ` [PATCH,FORTRAN 28/29] Free type-bound procedure structs Bernhard Reutner-Fischer
2021-10-29  0:05                         ` Bernhard Reutner-Fischer
2021-10-29 14:54                           ` Jerry D
2021-10-29 16:42                             ` Bernhard Reutner-Fischer
     [not found]                           ` <slhifq$rlb$1@ciao.gmane.io>
2021-10-29 20:09                             ` Bernhard Reutner-Fischer
2021-10-31 22:35                               ` Bernhard Reutner-Fischer
2018-09-05 15:02                       ` [PATCH,FORTRAN 20/29] Use stringpool in class et al Bernhard Reutner-Fischer
2018-09-05 15:02                       ` [PATCH,FORTRAN 15/29] Use stringpool for iso_c_binding module names Bernhard Reutner-Fischer
2018-09-05 15:02                       ` [PATCH,FORTRAN 16/29] Do pointer comparison in iso_c_binding_module Bernhard Reutner-Fischer
2018-09-05 15:02                       ` [PATCH,FORTRAN 18/29] Use stringpool for charkind Bernhard Reutner-Fischer
2018-09-05 15:02                       ` [PATCH,FORTRAN 19/29] Use stringpool and unified uppercase handling for types Bernhard Reutner-Fischer
2018-09-05 15:02                       ` [PATCH,FORTRAN 17/29] Use stringpool for iso_fortran_env Bernhard Reutner-Fischer
2015-12-01 12:56 ` [PATCH] RFC: Use Levenshtein spelling suggestions in Fortran FE Bernhard Reutner-Fischer
2015-12-01 15:02   ` Steve Kargl
2015-12-01 16:13     ` Bernhard Reutner-Fischer
2015-12-01 16:41       ` Steve Kargl
2015-12-01 17:35         ` Bernhard Reutner-Fischer
2015-12-01 19:49           ` Steve Kargl
2015-12-01 17:28   ` David Malcolm
2015-12-01 17:51     ` Bernhard Reutner-Fischer
2015-12-01 17:58       ` David Malcolm
2015-12-01 20:00         ` Steve Kargl
2015-12-03  9:29       ` Janne Blomqvist
2015-12-03 13:53         ` Mikael Morin
2015-12-04  0:08           ` Steve Kargl
2015-12-05 19:53   ` Mikael Morin
2015-12-09  1:07     ` [PATCH] v2 " David Malcolm
2015-12-10 16:15       ` Tobias Burnus
2015-12-22 13:57         ` Fortran release notes (was: [PATCH] v2 ...) Gerald Pfeifer
2015-12-12 17:02       ` [PATCH] v2 Re: [PATCH] RFC: Use Levenshtein spelling suggestions in Fortran FE Bernhard Reutner-Fischer
2015-12-27 21:43   ` [PATCH, RFC, v2] " Bernhard Reutner-Fischer
2016-03-05 22:46     ` [PATCH, fortran, v3] " Bernhard Reutner-Fischer
2016-03-07 14:57       ` David Malcolm
2016-04-23 18:22         ` Bernhard Reutner-Fischer
2016-04-25 17:07           ` David Malcolm
2016-06-18 19:59             ` [PATCH, fortran, v4] " Bernhard Reutner-Fischer
2016-06-20 10:26               ` VandeVondele  Joost
2016-07-03 22:46               ` Bernhard Reutner-Fischer [this message]
2016-07-04  3:31                 ` Ping: [Re: [PATCH, fortran, v4] Use Levenshtein spelling suggestions in Fortran FE] Jerry DeLisle
2016-07-04  5:03                   ` Janne Blomqvist
2017-10-19  7:26                     ` Bernhard Reutner-Fischer
2017-10-19  7:51               ` [PATCH, fortran, v4] Use Levenshtein spelling suggestions in Fortran FE Bernhard Reutner-Fischer
2016-06-18 19:47 ` [PATCH] Use gfc_add_*_component defines where appropriate Bernhard Reutner-Fischer
2016-06-19  9:18   ` Paul Richard Thomas
2016-06-19 10:39     ` Bernhard Reutner-Fischer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=6C3ABDCF-FBB7-45E2-9AFD-5C0082FC27D7@gmail.com \
    --to=rep.dot.nop@gmail.com \
    --cc=dmalcolm@redhat.com \
    --cc=fortran@gcc.gnu.org \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=joost.vandevondele@mat.ethz.ch \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).