Hi! When implicit_decl_warning is called, we know we are interested in a function or function pointer (or macro), C doesn't support int () like C++, or var () when var doesn't have function pointer type.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2016-07-14 Jakub Jelinek <ja...@redhat.com> PR c/71858 * c-common.h (enum lookup_name_fuzzy_kind): Add FUZZY_LOOKUP_FUNCTION_NAME. * c-decl.c (implicit_decl_warning): Use FUZZY_LOOKUP_FUNCTION_NAME instead of FUZZY_LOOKUP_NAME. (lookup_name_fuzzy): For FUZZY_LOOKUP_FUNCTION_NAME consider FUNCTION_DECLs, {VAR,PARM}_DECLs function pointers and macros. * gcc.dg/spellcheck-identifiers-3.c: New test. --- gcc/c-family/c-common.h.jj 2016-06-24 12:59:21.000000000 +0200 +++ gcc/c-family/c-common.h 2016-07-14 10:07:18.526594783 +0200 @@ -994,6 +994,9 @@ enum lookup_name_fuzzy_kind { /* Names of types. */ FUZZY_LOOKUP_TYPENAME, + /* Names of function decls. */ + FUZZY_LOOKUP_FUNCTION_NAME, + /* Any name. */ FUZZY_LOOKUP_NAME }; --- gcc/c/c-decl.c.jj 2016-07-13 22:40:23.000000000 +0200 +++ gcc/c/c-decl.c 2016-07-14 10:29:31.548376306 +0200 @@ -3090,7 +3090,7 @@ implicit_decl_warning (location_t loc, t bool warned; tree hint = NULL_TREE; if (!olddecl) - hint = lookup_name_fuzzy (id, FUZZY_LOOKUP_NAME); + hint = lookup_name_fuzzy (id, FUZZY_LOOKUP_FUNCTION_NAME); if (flag_isoc99) if (hint) @@ -4028,9 +4028,30 @@ lookup_name_fuzzy (tree name, enum looku if (TREE_CODE (binding->decl) == FUNCTION_DECL) if (C_DECL_IMPLICIT (binding->decl)) continue; - if (kind == FUZZY_LOOKUP_TYPENAME) - if (TREE_CODE (binding->decl) != TYPE_DECL) - continue; + switch (kind) + { + case FUZZY_LOOKUP_TYPENAME: + if (TREE_CODE (binding->decl) != TYPE_DECL) + continue; + break; + + case FUZZY_LOOKUP_FUNCTION_NAME: + if (TREE_CODE (binding->decl) != FUNCTION_DECL) + { + /* Allow function pointers. */ + if ((VAR_P (binding->decl) + || TREE_CODE (binding->decl) == PARM_DECL) + && TREE_CODE (TREE_TYPE (binding->decl)) == POINTER_TYPE + && (TREE_CODE (TREE_TYPE (TREE_TYPE (binding->decl))) + == FUNCTION_TYPE)) + break; + continue; + } + break; + + default: + break; + } bm.consider (binding->id); } --- gcc/testsuite/gcc.dg/spellcheck-identifiers-3.c.jj 2016-07-14 10:18:17.790090780 +0200 +++ gcc/testsuite/gcc.dg/spellcheck-identifiers-3.c 2016-07-14 10:39:14.392829944 +0200 @@ -0,0 +1,45 @@ +/* PR c/71858 */ +/* Only consider function names, function pointers and macros for implicit function declarations. */ +/* { dg-do compile } */ +/* { dg-options "-Wimplicit-function-declaration -fdiagnostics-show-caret" } */ + +void fn1abcd (void); + +void +test_1 (int fn1bacd) +{ + fn1badc (); /* { dg-warning "3: implicit declaration of function .fn1badc.; did you mean .fn1abcd.?" } */ + /* { dg-begin-multiline-output "" } + fn1badc (); + ^~~~~~~ + fn1abcd + { dg-end-multiline-output "" } */ +} + +void fn2efgh (void); +void (*fn2efhg) (void); + +void +test_2 (void) +{ + fn2fehg (); /* { dg-warning "3: implicit declaration of function .fn2fehg.; did you mean .fn2efhg.?" } */ + /* { dg-begin-multiline-output "" } + fn2fehg (); + ^~~~~~~ + fn2efhg + { dg-end-multiline-output "" } */ +} + +void fn3ijkl (void); +typedef int fn3ijlk; + +void +test_3 (void) +{ + fn3jilk (); /* { dg-warning "3: implicit declaration of function .fn3jilk.; did you mean .fn3ijkl.?" } */ + /* { dg-begin-multiline-output "" } + fn3jilk (); + ^~~~~~~ + fn3ijkl + { dg-end-multiline-output "" } */ +} Jakub