Discussion:
[C PATCH] Print header hints (PR c/59717)
Marek Polacek
2014-10-07 12:53:39 UTC
Permalink
PR59717 is a request for hints which header to include if the compiler warns
about incompatible implicit declarations. E.g., if one uses abort
without declaring it first, we now say
note: include ‘<stdlib.h>’ or provide a declaration of ‘abort’
I've added hints only for standard functions which means we won't display
the hint for functions such as mempcpy.

The implementation is based on a function that just maps built_in_function
codes to header names.

Two remarks:
* header_for_builtin_fn is long and I don't want to unnecessarily
inflate already big c-decl.c file, so it might make sense to move
the function into c-errors.c;
* we don't issue "incompatible implicit declaration of built-in function"
warning for functions that return int and whose parameter types don't need
default promotions - for instance putc, fputs, ilogb, strcmp, vprintf, isnan,
isalpha, ... Therefore for such functions we don't print the hint neither.
header_for_builtin_fn is ready for them, though. (The cases for <ctype.h>
and <wctype.h> could be removed.)

Bootstrapped/regtested on x86_64-linux, ok for trunk?

2014-10-07 Marek Polacek <***@redhat.com>

PR c/59717
* c-decl.c (header_for_builtin_fn): New function.
(implicitly_declare): Suggest which header to include.

* gcc.dg/pr59717.c: New test.

diff --git gcc/c/c-decl.c gcc/c/c-decl.c
index ce5a8de..e23284a 100644
--- gcc/c/c-decl.c
+++ gcc/c/c-decl.c
@@ -2968,6 +2968,189 @@ implicit_decl_warning (location_t loc, tree id, tree olddecl)
}
}

+/* This function represents mapping of a function code FCODE
+ to its respective header. */
+
+static const char *
+header_for_builtin_fn (enum built_in_function fcode)
+{
+ switch (fcode)
+ {
+ CASE_FLT_FN (BUILT_IN_ACOS):
+ CASE_FLT_FN (BUILT_IN_ACOSH):
+ CASE_FLT_FN (BUILT_IN_ASIN):
+ CASE_FLT_FN (BUILT_IN_ASINH):
+ CASE_FLT_FN (BUILT_IN_ATAN):
+ CASE_FLT_FN (BUILT_IN_ATANH):
+ CASE_FLT_FN (BUILT_IN_ATAN2):
+ CASE_FLT_FN (BUILT_IN_CBRT):
+ CASE_FLT_FN (BUILT_IN_CEIL):
+ CASE_FLT_FN (BUILT_IN_COPYSIGN):
+ CASE_FLT_FN (BUILT_IN_COS):
+ CASE_FLT_FN (BUILT_IN_COSH):
+ CASE_FLT_FN (BUILT_IN_ERF):
+ CASE_FLT_FN (BUILT_IN_ERFC):
+ CASE_FLT_FN (BUILT_IN_EXP):
+ CASE_FLT_FN (BUILT_IN_EXP2):
+ CASE_FLT_FN (BUILT_IN_EXPM1):
+ CASE_FLT_FN (BUILT_IN_FABS):
+ CASE_FLT_FN (BUILT_IN_FDIM):
+ CASE_FLT_FN (BUILT_IN_FLOOR):
+ CASE_FLT_FN (BUILT_IN_FMA):
+ CASE_FLT_FN (BUILT_IN_FMAX):
+ CASE_FLT_FN (BUILT_IN_FMIN):
+ CASE_FLT_FN (BUILT_IN_FMOD):
+ CASE_FLT_FN (BUILT_IN_FREXP):
+ CASE_FLT_FN (BUILT_IN_HYPOT):
+ CASE_FLT_FN (BUILT_IN_ILOGB):
+ CASE_FLT_FN (BUILT_IN_LDEXP):
+ CASE_FLT_FN (BUILT_IN_LGAMMA):
+ CASE_FLT_FN (BUILT_IN_LLRINT):
+ CASE_FLT_FN (BUILT_IN_LLROUND):
+ CASE_FLT_FN (BUILT_IN_LOG):
+ CASE_FLT_FN (BUILT_IN_LOG10):
+ CASE_FLT_FN (BUILT_IN_LOG1P):
+ CASE_FLT_FN (BUILT_IN_LOG2):
+ CASE_FLT_FN (BUILT_IN_LOGB):
+ CASE_FLT_FN (BUILT_IN_LRINT):
+ CASE_FLT_FN (BUILT_IN_LROUND):
+ CASE_FLT_FN (BUILT_IN_MODF):
+ CASE_FLT_FN (BUILT_IN_NAN):
+ CASE_FLT_FN (BUILT_IN_NEARBYINT):
+ CASE_FLT_FN (BUILT_IN_NEXTAFTER):
+ CASE_FLT_FN (BUILT_IN_NEXTTOWARD):
+ CASE_FLT_FN (BUILT_IN_POW):
+ CASE_FLT_FN (BUILT_IN_REMAINDER):
+ CASE_FLT_FN (BUILT_IN_REMQUO):
+ CASE_FLT_FN (BUILT_IN_RINT):
+ CASE_FLT_FN (BUILT_IN_ROUND):
+ CASE_FLT_FN (BUILT_IN_SCALBLN):
+ CASE_FLT_FN (BUILT_IN_SCALBN):
+ CASE_FLT_FN (BUILT_IN_SIN):
+ CASE_FLT_FN (BUILT_IN_SINH):
+ CASE_FLT_FN (BUILT_IN_SINCOS):
+ CASE_FLT_FN (BUILT_IN_SQRT):
+ CASE_FLT_FN (BUILT_IN_TAN):
+ CASE_FLT_FN (BUILT_IN_TANH):
+ CASE_FLT_FN (BUILT_IN_TGAMMA):
+ CASE_FLT_FN (BUILT_IN_TRUNC):
+ case BUILT_IN_ISINF:
+ case BUILT_IN_ISNAN:
+ return "<math.h>";
+ CASE_FLT_FN (BUILT_IN_CABS):
+ CASE_FLT_FN (BUILT_IN_CACOS):
+ CASE_FLT_FN (BUILT_IN_CACOSH):
+ CASE_FLT_FN (BUILT_IN_CARG):
+ CASE_FLT_FN (BUILT_IN_CASIN):
+ CASE_FLT_FN (BUILT_IN_CASINH):
+ CASE_FLT_FN (BUILT_IN_CATAN):
+ CASE_FLT_FN (BUILT_IN_CATANH):
+ CASE_FLT_FN (BUILT_IN_CCOS):
+ CASE_FLT_FN (BUILT_IN_CCOSH):
+ CASE_FLT_FN (BUILT_IN_CEXP):
+ CASE_FLT_FN (BUILT_IN_CIMAG):
+ CASE_FLT_FN (BUILT_IN_CLOG):
+ CASE_FLT_FN (BUILT_IN_CONJ):
+ CASE_FLT_FN (BUILT_IN_CPOW):
+ CASE_FLT_FN (BUILT_IN_CPROJ):
+ CASE_FLT_FN (BUILT_IN_CREAL):
+ CASE_FLT_FN (BUILT_IN_CSIN):
+ CASE_FLT_FN (BUILT_IN_CSINH):
+ CASE_FLT_FN (BUILT_IN_CSQRT):
+ CASE_FLT_FN (BUILT_IN_CTAN):
+ CASE_FLT_FN (BUILT_IN_CTANH):
+ return "<complex.h>";
+ case BUILT_IN_MEMCHR:
+ case BUILT_IN_MEMCMP:
+ case BUILT_IN_MEMCPY:
+ case BUILT_IN_MEMMOVE:
+ case BUILT_IN_MEMSET:
+ case BUILT_IN_STRCAT:
+ case BUILT_IN_STRCHR:
+ case BUILT_IN_STRCMP:
+ case BUILT_IN_STRCPY:
+ case BUILT_IN_STRCSPN:
+ case BUILT_IN_STRLEN:
+ case BUILT_IN_STRNCAT:
+ case BUILT_IN_STRNCMP:
+ case BUILT_IN_STRNCPY:
+ case BUILT_IN_STRPBRK:
+ case BUILT_IN_STRRCHR:
+ case BUILT_IN_STRSPN:
+ case BUILT_IN_STRSTR:
+ return "<string.h>";
+ case BUILT_IN_FPRINTF:
+ case BUILT_IN_PUTC:
+ case BUILT_IN_FPUTC:
+ case BUILT_IN_FPUTS:
+ case BUILT_IN_FSCANF:
+ case BUILT_IN_FWRITE:
+ case BUILT_IN_PRINTF:
+ case BUILT_IN_PUTCHAR:
+ case BUILT_IN_PUTS:
+ case BUILT_IN_SCANF:
+ case BUILT_IN_SNPRINTF:
+ case BUILT_IN_SPRINTF:
+ case BUILT_IN_SSCANF:
+ case BUILT_IN_VFPRINTF:
+ case BUILT_IN_VFSCANF:
+ case BUILT_IN_VPRINTF:
+ case BUILT_IN_VSCANF:
+ case BUILT_IN_VSNPRINTF:
+ case BUILT_IN_VSPRINTF:
+ case BUILT_IN_VSSCANF:
+ return "<stdio.h>";
+ case BUILT_IN_ISALNUM:
+ case BUILT_IN_ISALPHA:
+ case BUILT_IN_ISBLANK:
+ case BUILT_IN_ISCNTRL:
+ case BUILT_IN_ISDIGIT:
+ case BUILT_IN_ISGRAPH:
+ case BUILT_IN_ISLOWER:
+ case BUILT_IN_ISPRINT:
+ case BUILT_IN_ISPUNCT:
+ case BUILT_IN_ISSPACE:
+ case BUILT_IN_ISUPPER:
+ case BUILT_IN_ISXDIGIT:
+ case BUILT_IN_TOLOWER:
+ case BUILT_IN_TOUPPER:
+ return "<ctype.h>";
+ case BUILT_IN_ISWALNUM:
+ case BUILT_IN_ISWALPHA:
+ case BUILT_IN_ISWBLANK:
+ case BUILT_IN_ISWCNTRL:
+ case BUILT_IN_ISWDIGIT:
+ case BUILT_IN_ISWGRAPH:
+ case BUILT_IN_ISWLOWER:
+ case BUILT_IN_ISWPRINT:
+ case BUILT_IN_ISWPUNCT:
+ case BUILT_IN_ISWSPACE:
+ case BUILT_IN_ISWUPPER:
+ case BUILT_IN_ISWXDIGIT:
+ case BUILT_IN_TOWLOWER:
+ case BUILT_IN_TOWUPPER:
+ return "<wctype.h>";
+ case BUILT_IN_ABORT:
+ case BUILT_IN_ABS:
+ case BUILT_IN_CALLOC:
+ case BUILT_IN_EXIT:
+ case BUILT_IN_FREE:
+ case BUILT_IN_LABS:
+ case BUILT_IN_LLABS:
+ case BUILT_IN_MALLOC:
+ case BUILT_IN_REALLOC:
+ case BUILT_IN__EXIT2:
+ case BUILT_IN_ALIGNED_ALLOC:
+ return "<stdlib.h>";
+ case BUILT_IN_IMAXABS:
+ return "<inttypes.h>";
+ case BUILT_IN_STRFTIME:
+ return "<time.h>";
+ default:
+ return NULL;
+ }
+}
+
/* Generate an implicit declaration for identifier FUNCTIONID at LOC as a
function of type int (). */

@@ -3025,8 +3208,15 @@ implicitly_declare (location_t loc, tree functionid)
(TREE_TYPE (decl)));
if (!comptypes (newtype, TREE_TYPE (decl)))
{
- warning_at (loc, 0, "incompatible implicit declaration of "
- "built-in function %qD", decl);
+ bool warned = warning_at (loc, 0, "incompatible implicit "
+ "declaration of built-in "
+ "function %qD", decl);
+ /* See if we can hint which header to include. */
+ const char *header
+ = header_for_builtin_fn (DECL_FUNCTION_CODE (decl));
+ if (header != NULL && warned)
+ inform (loc, "include %qs or provide a declaration of %qD",
+ header, decl);
newtype = TREE_TYPE (decl);
}
}
@@ -3034,7 +3224,8 @@ implicitly_declare (location_t loc, tree functionid)
{
if (!comptypes (newtype, TREE_TYPE (decl)))
{
- error_at (loc, "incompatible implicit declaration of function %qD", decl);
+ error_at (loc, "incompatible implicit declaration of "
+ "function %qD", decl);
locate_old_decl (decl);
}
}
diff --git gcc/testsuite/gcc.dg/pr59717.c gcc/testsuite/gcc.dg/pr59717.c
index e69de29..948180c 100644
--- gcc/testsuite/gcc.dg/pr59717.c
+++ gcc/testsuite/gcc.dg/pr59717.c
@@ -0,0 +1,277 @@
+/* PR c/59717 */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu11 -Wno-implicit-function-declaration" } */
+
+void
+math (double d, int *ex, double *dp)
+{
+ acos (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 8 } */
+ acosh (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 10 } */
+ asin (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 12 } */
+ asinh (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 14 } */
+ atan (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 16 } */
+ atanh (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 18 } */
+ atan2 (d, d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 20 } */
+ cbrt (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 22 } */
+ ceil (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 24 } */
+ copysign (d, d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 26 } */
+ cos (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 28 } */
+ cosh (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 30 } */
+ erf (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 32 } */
+ erfc (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 34 } */
+ exp (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 36 } */
+ exp2 (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 38 } */
+ expm1 (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 40 } */
+ fabs (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 42 } */
+ fdim (d, d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 44 } */
+ floor (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 46 } */
+ fma (d, d, d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 48 } */
+ fmax (d, d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 50 } */
+ fmin (d, d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 52 } */
+ fmod (d, d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 54 } */
+ frexp (d, ex); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 56 } */
+ hypot (d, d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 58 } */
+ /* We don't generate the warning for ilogb. */
+ ilogb (d);
+ ldexp (d, *ex); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 62 } */
+ lgamma (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 64 } */
+ llrint (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 66 } */
+ llround (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 68 } */
+ log (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 70 } */
+ log10 (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 72 } */
+ log1p (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 74 } */
+ log2 (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 76 } */
+ logb (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 78 } */
+ lrint (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 80 } */
+ lround (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 82 } */
+ modf (d, dp); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 84 } */
+ nan (""); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 86 } */
+ nearbyint (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 88 } */
+ nextafter (d, d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 90 } */
+ nexttoward (d, 20.0L); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 92 } */
+ pow (d, d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 94 } */
+ remainder (d, d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 96 } */
+ remquo (d, d, ex); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 98 } */
+ rint (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 100 } */
+ round (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 102 } */
+ scalbln (d, 100L); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 104 } */
+ scalbn (d, 100); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 106 } */
+ sin (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 108 } */
+ sinh (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 110 } */
+ sincos (d, dp, dp); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 112 } */
+ sqrt (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 114 } */
+ tan (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 116 } */
+ tanh (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 118 } */
+ tgamma (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 120 } */
+ trunc (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 122 } */
+}
+
+void
+cmplx (double _Complex z)
+{
+ cabs (z); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..complex.h.." "" { target *-*-* } 129 } */
+ cacos (z); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..complex.h.." "" { target *-*-* } 131 } */
+ cacosh (z); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..complex.h.." "" { target *-*-* } 133 } */
+ carg (z); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..complex.h.." "" { target *-*-* } 135 } */
+ casin (z); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..complex.h.." "" { target *-*-* } 137 } */
+ casinh (z); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..complex.h.." "" { target *-*-* } 139 } */
+ catan (z); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..complex.h.." "" { target *-*-* } 141 } */
+ catanh (z); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..complex.h.." "" { target *-*-* } 143 } */
+ ccos (z); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..complex.h.." "" { target *-*-* } 145 } */
+ ccosh (z); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..complex.h.." "" { target *-*-* } 147 } */
+ cexp (z); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..complex.h.." "" { target *-*-* } 149 } */
+ cimag (z); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..complex.h.." "" { target *-*-* } 151 } */
+ clog (z); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..complex.h.." "" { target *-*-* } 153 } */
+ conj (z); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..complex.h.." "" { target *-*-* } 155 } */
+ cpow (z, z); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..complex.h.." "" { target *-*-* } 157 } */
+ cproj (z); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..complex.h.." "" { target *-*-* } 159 } */
+ creal (z); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..complex.h.." "" { target *-*-* } 161 } */
+ csin (z); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..complex.h.." "" { target *-*-* } 163 } */
+ csinh (z); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..complex.h.." "" { target *-*-* } 165 } */
+ csqrt (z); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..complex.h.." "" { target *-*-* } 167 } */
+ ctan (z); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..complex.h.." "" { target *-*-* } 169 } */
+ ctanh (z); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..complex.h.." "" { target *-*-* } 171 } */
+}
+
+void
+string (void *p, void *q, __SIZE_TYPE__ sz)
+{
+ memchr (p, 2, sz); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..string.h.." "" { target *-*-* } 178 } */
+ /* We don't generate the warning for memcmp. */
+ memcmp (p, q, sz);
+ memcpy (p, q, sz); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..string.h.." "" { target *-*-* } 182 } */
+ memmove (p, q, sz); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..string.h.." "" { target *-*-* } 184 } */
+ memset (p, 0, sz); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..string.h.." "" { target *-*-* } 186 } */
+ strcat (p, q); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..string.h.." "" { target *-*-* } 188 } */
+ strchr (p, 'a'); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..string.h.." "" { target *-*-* } 190 } */
+ /* We don't generate the warning for strcmp. */
+ strcmp (p, q);
+ strcpy (p, q); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..string.h.." "" { target *-*-* } 194 } */
+ strcspn (p, q); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..string.h.." "" { target *-*-* } 196 } */
+ strlen (p); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..string.h.." "" { target *-*-* } 198 } */
+ strncat (p, q, sz); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..string.h.." "" { target *-*-* } 200 } */
+ /* We don't generate the warning for strncmp. */
+ strncmp (p, q, sz);
+ strncpy (p, q, sz); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..string.h.." "" { target *-*-* } 204 } */
+ strpbrk (p, q); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..string.h.." "" { target *-*-* } 206 } */
+ strrchr (p, 'q'); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..string.h.." "" { target *-*-* } 208 } */
+ strspn (p, q); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..string.h.." "" { target *-*-* } 210 } */
+ strstr (p, q); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..string.h.." "" { target *-*-* } 212 } */
+}
+
+/* Fake FILE. */
+typedef struct { int i; } FILE;
+
+void
+stdio (FILE *fp, void *p, __SIZE_TYPE__ sz)
+{
+ fprintf (fp, ""); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..stdio.h.." "" { target *-*-* } 222 } */
+ fscanf (fp, ""); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..stdio.h.." "" { target *-*-* } 224 } */
+ fwrite (p, sz, sz, fp); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..stdio.h.." "" { target *-*-* } 226 } */
+ printf (""); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..stdio.h.." "" { target *-*-* } 228 } */
+ scanf (""); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..stdio.h.." "" { target *-*-* } 230 } */
+ snprintf ("", sz, ""); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..stdio.h.." "" { target *-*-* } 232 } */
+ sprintf ("", ""); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..stdio.h.." "" { target *-*-* } 234 } */
+ sscanf ("", ""); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..stdio.h.." "" { target *-*-* } 236 } */
+}
+
+void
+stdlib (void *p, void *q, __SIZE_TYPE__ sz)
+{
+ abort (); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..stdlib.h.." "" { target *-*-* } 243 } */
+ calloc (sz, 1); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..stdlib.h.." "" { target *-*-* } 245 } */
+ exit (1); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..stdlib.h.." "" { target *-*-* } 247 } */
+ free (p); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..stdlib.h.." "" { target *-*-* } 249 } */
+ labs (1L); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..stdlib.h.." "" { target *-*-* } 251 } */
+ llabs (1LL); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..stdlib.h.." "" { target *-*-* } 253 } */
+ malloc (sz); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..stdlib.h.." "" { target *-*-* } 255 } */
+ realloc (p, sz); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..stdlib.h.." "" { target *-*-* } 257 } */
+ aligned_alloc (sz, sz); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..stdlib.h.." "" { target *-*-* } 259 } */
+}
+
+void
+inttypes (__INTMAX_TYPE__ j)
+{
+ imaxabs (j); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..inttypes.h.." "" { target *-*-* } 266 } */
+}
+
+struct tm;
+
+void
+timeh (char *s, __SIZE_TYPE__ sz, struct tm *tm)
+{
+ strftime (s, sz, "", tm); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..time.h.." "" { target *-*-* } 275 } */
+}

Marek
Richard Biener
2014-10-07 14:39:55 UTC
Permalink
Post by Marek Polacek
PR59717 is a request for hints which header to include if the compiler warns
about incompatible implicit declarations. E.g., if one uses abort
without declaring it first, we now say
note: include ‘<stdlib.h>’ or provide a declaration of ‘abort’
I've added hints only for standard functions which means we won't display
the hint for functions such as mempcpy.
The implementation is based on a function that just maps built_in_function
codes to header names.
* header_for_builtin_fn is long and I don't want to unnecessarily
inflate already big c-decl.c file, so it might make sense to move
the function into c-errors.c;
* we don't issue "incompatible implicit declaration of built-in function"
warning for functions that return int and whose parameter types don't need
default promotions - for instance putc, fputs, ilogb, strcmp, vprintf, isnan,
isalpha, ... Therefore for such functions we don't print the hint neither.
header_for_builtin_fn is ready for them, though. (The cases for <ctype.h>
and <wctype.h> could be removed.)
Bootstrapped/regtested on x86_64-linux, ok for trunk?
Why not annotate builtins.def with the info?

Richard.
Post by Marek Polacek
PR c/59717
* c-decl.c (header_for_builtin_fn): New function.
(implicitly_declare): Suggest which header to include.
* gcc.dg/pr59717.c: New test.
diff --git gcc/c/c-decl.c gcc/c/c-decl.c
index ce5a8de..e23284a 100644
--- gcc/c/c-decl.c
+++ gcc/c/c-decl.c
@@ -2968,6 +2968,189 @@ implicit_decl_warning (location_t loc, tree id, tree olddecl)
}
}
+/* This function represents mapping of a function code FCODE
+ to its respective header. */
+
+static const char *
+header_for_builtin_fn (enum built_in_function fcode)
+{
+ switch (fcode)
+ {
+ return "<math.h>";
+ return "<complex.h>";
+ return "<string.h>";
+ return "<stdio.h>";
+ return "<ctype.h>";
+ return "<wctype.h>";
+ return "<stdlib.h>";
+ return "<inttypes.h>";
+ return "<time.h>";
+ return NULL;
+ }
+}
+
/* Generate an implicit declaration for identifier FUNCTIONID at LOC as a
function of type int (). */
@@ -3025,8 +3208,15 @@ implicitly_declare (location_t loc, tree functionid)
(TREE_TYPE (decl)));
if (!comptypes (newtype, TREE_TYPE (decl)))
{
- warning_at (loc, 0, "incompatible implicit declaration of "
- "built-in function %qD", decl);
+ bool warned = warning_at (loc, 0, "incompatible implicit "
+ "declaration of built-in "
+ "function %qD", decl);
+ /* See if we can hint which header to include. */
+ const char *header
+ = header_for_builtin_fn (DECL_FUNCTION_CODE (decl));
+ if (header != NULL && warned)
+ inform (loc, "include %qs or provide a declaration of %qD",
+ header, decl);
newtype = TREE_TYPE (decl);
}
}
@@ -3034,7 +3224,8 @@ implicitly_declare (location_t loc, tree functionid)
{
if (!comptypes (newtype, TREE_TYPE (decl)))
{
- error_at (loc, "incompatible implicit declaration of function %qD", decl);
+ error_at (loc, "incompatible implicit declaration of "
+ "function %qD", decl);
locate_old_decl (decl);
}
}
diff --git gcc/testsuite/gcc.dg/pr59717.c gcc/testsuite/gcc.dg/pr59717.c
index e69de29..948180c 100644
--- gcc/testsuite/gcc.dg/pr59717.c
+++ gcc/testsuite/gcc.dg/pr59717.c
@@ -0,0 +1,277 @@
+/* PR c/59717 */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu11 -Wno-implicit-function-declaration" } */
+
+void
+math (double d, int *ex, double *dp)
+{
+ acos (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 8 } */
+ acosh (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 10 } */
+ asin (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 12 } */
+ asinh (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 14 } */
+ atan (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 16 } */
+ atanh (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 18 } */
+ atan2 (d, d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 20 } */
+ cbrt (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 22 } */
+ ceil (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 24 } */
+ copysign (d, d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 26 } */
+ cos (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 28 } */
+ cosh (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 30 } */
+ erf (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 32 } */
+ erfc (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 34 } */
+ exp (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 36 } */
+ exp2 (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 38 } */
+ expm1 (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 40 } */
+ fabs (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 42 } */
+ fdim (d, d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 44 } */
+ floor (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 46 } */
+ fma (d, d, d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 48 } */
+ fmax (d, d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 50 } */
+ fmin (d, d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 52 } */
+ fmod (d, d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 54 } */
+ frexp (d, ex); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 56 } */
+ hypot (d, d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 58 } */
+ /* We don't generate the warning for ilogb. */
+ ilogb (d);
+ ldexp (d, *ex); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 62 } */
+ lgamma (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 64 } */
+ llrint (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 66 } */
+ llround (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 68 } */
+ log (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 70 } */
+ log10 (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 72 } */
+ log1p (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 74 } */
+ log2 (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 76 } */
+ logb (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 78 } */
+ lrint (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 80 } */
+ lround (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 82 } */
+ modf (d, dp); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 84 } */
+ nan (""); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 86 } */
+ nearbyint (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 88 } */
+ nextafter (d, d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 90 } */
+ nexttoward (d, 20.0L); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 92 } */
+ pow (d, d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 94 } */
+ remainder (d, d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 96 } */
+ remquo (d, d, ex); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 98 } */
+ rint (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 100 } */
+ round (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 102 } */
+ scalbln (d, 100L); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 104 } */
+ scalbn (d, 100); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 106 } */
+ sin (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 108 } */
+ sinh (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 110 } */
+ sincos (d, dp, dp); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 112 } */
+ sqrt (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 114 } */
+ tan (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 116 } */
+ tanh (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 118 } */
+ tgamma (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 120 } */
+ trunc (d); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..math.h.." "" { target *-*-* } 122 } */
+}
+
+void
+cmplx (double _Complex z)
+{
+ cabs (z); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..complex.h.." "" { target *-*-* } 129 } */
+ cacos (z); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..complex.h.." "" { target *-*-* } 131 } */
+ cacosh (z); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..complex.h.." "" { target *-*-* } 133 } */
+ carg (z); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..complex.h.." "" { target *-*-* } 135 } */
+ casin (z); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..complex.h.." "" { target *-*-* } 137 } */
+ casinh (z); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..complex.h.." "" { target *-*-* } 139 } */
+ catan (z); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..complex.h.." "" { target *-*-* } 141 } */
+ catanh (z); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..complex.h.." "" { target *-*-* } 143 } */
+ ccos (z); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..complex.h.." "" { target *-*-* } 145 } */
+ ccosh (z); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..complex.h.." "" { target *-*-* } 147 } */
+ cexp (z); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..complex.h.." "" { target *-*-* } 149 } */
+ cimag (z); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..complex.h.." "" { target *-*-* } 151 } */
+ clog (z); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..complex.h.." "" { target *-*-* } 153 } */
+ conj (z); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..complex.h.." "" { target *-*-* } 155 } */
+ cpow (z, z); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..complex.h.." "" { target *-*-* } 157 } */
+ cproj (z); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..complex.h.." "" { target *-*-* } 159 } */
+ creal (z); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..complex.h.." "" { target *-*-* } 161 } */
+ csin (z); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..complex.h.." "" { target *-*-* } 163 } */
+ csinh (z); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..complex.h.." "" { target *-*-* } 165 } */
+ csqrt (z); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..complex.h.." "" { target *-*-* } 167 } */
+ ctan (z); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..complex.h.." "" { target *-*-* } 169 } */
+ ctanh (z); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..complex.h.." "" { target *-*-* } 171 } */
+}
+
+void
+string (void *p, void *q, __SIZE_TYPE__ sz)
+{
+ memchr (p, 2, sz); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..string.h.." "" { target *-*-* } 178 } */
+ /* We don't generate the warning for memcmp. */
+ memcmp (p, q, sz);
+ memcpy (p, q, sz); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..string.h.." "" { target *-*-* } 182 } */
+ memmove (p, q, sz); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..string.h.." "" { target *-*-* } 184 } */
+ memset (p, 0, sz); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..string.h.." "" { target *-*-* } 186 } */
+ strcat (p, q); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..string.h.." "" { target *-*-* } 188 } */
+ strchr (p, 'a'); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..string.h.." "" { target *-*-* } 190 } */
+ /* We don't generate the warning for strcmp. */
+ strcmp (p, q);
+ strcpy (p, q); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..string.h.." "" { target *-*-* } 194 } */
+ strcspn (p, q); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..string.h.." "" { target *-*-* } 196 } */
+ strlen (p); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..string.h.." "" { target *-*-* } 198 } */
+ strncat (p, q, sz); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..string.h.." "" { target *-*-* } 200 } */
+ /* We don't generate the warning for strncmp. */
+ strncmp (p, q, sz);
+ strncpy (p, q, sz); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..string.h.." "" { target *-*-* } 204 } */
+ strpbrk (p, q); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..string.h.." "" { target *-*-* } 206 } */
+ strrchr (p, 'q'); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..string.h.." "" { target *-*-* } 208 } */
+ strspn (p, q); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..string.h.." "" { target *-*-* } 210 } */
+ strstr (p, q); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..string.h.." "" { target *-*-* } 212 } */
+}
+
+/* Fake FILE. */
+typedef struct { int i; } FILE;
+
+void
+stdio (FILE *fp, void *p, __SIZE_TYPE__ sz)
+{
+ fprintf (fp, ""); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..stdio.h.." "" { target *-*-* } 222 } */
+ fscanf (fp, ""); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..stdio.h.." "" { target *-*-* } 224 } */
+ fwrite (p, sz, sz, fp); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..stdio.h.." "" { target *-*-* } 226 } */
+ printf (""); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..stdio.h.." "" { target *-*-* } 228 } */
+ scanf (""); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..stdio.h.." "" { target *-*-* } 230 } */
+ snprintf ("", sz, ""); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..stdio.h.." "" { target *-*-* } 232 } */
+ sprintf ("", ""); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..stdio.h.." "" { target *-*-* } 234 } */
+ sscanf ("", ""); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..stdio.h.." "" { target *-*-* } 236 } */
+}
+
+void
+stdlib (void *p, void *q, __SIZE_TYPE__ sz)
+{
+ abort (); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..stdlib.h.." "" { target *-*-* } 243 } */
+ calloc (sz, 1); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..stdlib.h.." "" { target *-*-* } 245 } */
+ exit (1); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..stdlib.h.." "" { target *-*-* } 247 } */
+ free (p); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..stdlib.h.." "" { target *-*-* } 249 } */
+ labs (1L); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..stdlib.h.." "" { target *-*-* } 251 } */
+ llabs (1LL); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..stdlib.h.." "" { target *-*-* } 253 } */
+ malloc (sz); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..stdlib.h.." "" { target *-*-* } 255 } */
+ realloc (p, sz); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..stdlib.h.." "" { target *-*-* } 257 } */
+ aligned_alloc (sz, sz); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..stdlib.h.." "" { target *-*-* } 259 } */
+}
+
+void
+inttypes (__INTMAX_TYPE__ j)
+{
+ imaxabs (j); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..inttypes.h.." "" { target *-*-* } 266 } */
+}
+
+struct tm;
+
+void
+timeh (char *s, __SIZE_TYPE__ sz, struct tm *tm)
+{
+ strftime (s, sz, "", tm); /* { dg-warning "incompatible implicit" } */
+ /* { dg-message "include ..time.h.." "" { target *-*-* } 275 } */
+}
Marek
Marek Polacek
2014-10-07 14:51:31 UTC
Permalink
Post by Richard Biener
Why not annotate builtins.def with the info?
Because I think that would be more hairy, I'd have to change DEF_BUILTIN
and all the builtins. That seemed superfluous given that this hint is
only for a C FE...

Marek
Jakub Jelinek
2014-10-07 15:00:05 UTC
Permalink
Post by Marek Polacek
Post by Richard Biener
Why not annotate builtins.def with the info?
Because I think that would be more hairy, I'd have to change DEF_BUILTIN
and all the builtins. That seemed superfluous given that this hint is
only for a C FE...
Guess it depends on how many DEF_*_BUILTIN classes would this affect,
if just a couple, you could add DEF_*_BUILTIN_WITH_C_HINT, with an extra
arg. But as the builtins.def info already has quite long lines, making them
even longer might not be best. So perhaps the switch is good enough.

Jakub
Marek Polacek
2014-10-07 15:09:18 UTC
Permalink
Post by Jakub Jelinek
Post by Marek Polacek
Post by Richard Biener
Why not annotate builtins.def with the info?
Because I think that would be more hairy, I'd have to change DEF_BUILTIN
and all the builtins. That seemed superfluous given that this hint is
only for a C FE...
Guess it depends on how many DEF_*_BUILTIN classes would this affect,
At least the following:
DEF_LIB_BUILTIN
DEF_C94_BUILTIN
DEF_C99_BUILTIN
DEF_C11_BUILTIN
DEF_C99_COMPL_BUILTIN
DEF_C99_C90RES_BUILTIN
I think that is quite a lot.
Post by Jakub Jelinek
if just a couple, you could add DEF_*_BUILTIN_WITH_C_HINT, with an extra
arg. But as the builtins.def info already has quite long lines, making them
even longer might not be best. So perhaps the switch is good enough.
Yeah, that the lines are long enough already was one of the things
that discouraged me from tweaking builtins.def.

Marek
Richard Biener
2014-10-07 15:00:26 UTC
Permalink
Post by Marek Polacek
Post by Richard Biener
Why not annotate builtins.def with the info?
Because I think that would be more hairy, I'd have to change DEF_BUILTIN
and all the builtins. That seemed superfluous given that this hint is
only for a C FE...
All C family frontends, no? And builtins.def is used by (and only by)
all C family frontends...

Well - just a suggestion ;)

I'd like to see some easier to grok specification of the number of arguments
expected to the builtins for example (for the match-and-simplify work).

Richard.
Post by Marek Polacek
Marek
Jakub Jelinek
2014-10-07 15:04:08 UTC
Permalink
Post by Richard Biener
Post by Marek Polacek
Post by Richard Biener
Why not annotate builtins.def with the info?
Because I think that would be more hairy, I'd have to change DEF_BUILTIN
and all the builtins. That seemed superfluous given that this hint is
only for a C FE...
All C family frontends, no? And builtins.def is used by (and only by)
all C family frontends...
Well, the C++ FE on say:
void
bar (void)
{
abort ();
}

just errors out:
/tmp/a.c: In function ‘void bar()’:
/tmp/a.c:4:10: error: ‘abort’ was not declared in this scope
abort ();
^
adding a hint in this case is less obvious than in the C case, because,
what if this wasn't supposed to be ::abort (), but std::abort (), or
some other namespace abort, or some class abort () method etc.?

Jakub
Jason Merrill
2014-10-07 17:57:33 UTC
Permalink
Post by Jakub Jelinek
adding a hint in this case is less obvious than in the C case, because,
what if this wasn't supposed to be ::abort (), but std::abort (), or
some other namespace abort, or some class abort () method etc.?
It still seems reasonable to offer a hint if no declaration was found.

Jason

Marek Polacek
2014-10-07 15:13:50 UTC
Permalink
Post by Richard Biener
Post by Marek Polacek
Post by Richard Biener
Why not annotate builtins.def with the info?
Because I think that would be more hairy, I'd have to change DEF_BUILTIN
and all the builtins. That seemed superfluous given that this hint is
only for a C FE...
All C family frontends, no? And builtins.def is used by (and only by)
all C family frontends...
As Jakub pointed out, only C and ObjC for now.
Post by Richard Biener
Well - just a suggestion ;)
Thanks - builtins.def was where I originally started.

Marek
Joseph S. Myers
2014-10-07 17:41:10 UTC
Permalink
Post by Marek Polacek
PR c/59717
* c-decl.c (header_for_builtin_fn): New function.
(implicitly_declare): Suggest which header to include.
* gcc.dg/pr59717.c: New test.
OK.
--
Joseph S. Myers
***@codesourcery.com
Loading...