diff options
author | Bernhard Reutner-Fischer <aldot@gcc.gnu.org> | 2017-10-19 09:24:33 +0200 |
---|---|---|
committer | Bernhard Reutner-Fischer <aldot@gcc.gnu.org> | 2017-10-19 09:24:33 +0200 |
commit | bcc478b9647e2af4b715fda6676d98f1e129d16b (patch) | |
tree | 78eb982a4151306d46381aacdf1b5298544bdac2 /gcc/fortran/interface.c | |
parent | fba832054d9467a296d126754cc3a5efca707bdf (diff) | |
download | gcc-bcc478b9647e2af4b715fda6676d98f1e129d16b.zip gcc-bcc478b9647e2af4b715fda6676d98f1e129d16b.tar.gz gcc-bcc478b9647e2af4b715fda6676d98f1e129d16b.tar.bz2 |
Use Levenshtein spelling suggestions in Fortran FE
gcc/fortran/ChangeLog
2017-10-19 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
2017-10-19 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.
From-SVN: r253877
Diffstat (limited to 'gcc/fortran/interface.c')
-rw-r--r-- | gcc/fortran/interface.c | 72 |
1 files changed, 63 insertions, 9 deletions
diff --git a/gcc/fortran/interface.c b/gcc/fortran/interface.c index f8ef33f..b4f5a4d 100644 --- a/gcc/fortran/interface.c +++ b/gcc/fortran/interface.c @@ -1793,13 +1793,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 true; } @@ -2778,6 +2792,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 @@ -2831,8 +2870,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 false; } @@ -3552,8 +3599,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) |