autoconf-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: AC_CHECK_DECLS vs. Clang


From: Noah Misch
Subject: Re: AC_CHECK_DECLS vs. Clang
Date: Mon, 13 Apr 2015 21:12:52 -0400
User-agent: Mutt/1.5.23 (2014-03-12)

On Sun, Mar 08, 2015 at 12:13:44AM -0500, Noah Misch wrote:
> The Clang compiler furnishes implicit declarations for built-in functions,
> even when the identifier in question is not used as a function designator.
> This thwarts AC_CHECK_DECLS:
> 
> configure:11565: checking whether strlcpy is declared
> configure:11565: clang -c -Wall -Wmissing-prototypes -Wpointer-arith 
> -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute 
> -Wformat-security -fno-strict-aliasing -fwrapv -g -O2  -D_GNU_SOURCE 
> -I/usr/include/libxml2  conftest.c >&5
> conftest.c:166:10: warning: implicitly declaring library function 'strlcpy' 
> with type 'unsigned long (char *, const char *, unsigned long)'
>   (void) strlcpy;
>          ^
> conftest.c:166:10: note: please include the header <string.h> or explicitly 
> provide a declaration for 'strlcpy'
> 1 warning generated.
> configure:11565: $? = 0
> configure:11565: result: yes
> 
> 
> Full config.log:
> http://buildfarm.postgresql.org/cgi-bin/show_stage_log.pl?nm=treepie&dt=2015-03-07%2006%3A22%3A38&stg=config
> 
> Clang has always behaved this way, but strlcpy() and strlcat() were unaffected
> until Clang 3.0 added them as builtins.  To fix this, I plan to introduce
> ac_c_decl_warn_flag by analogy to ac_c_preproc_warn_flag.  With no explicit
> declarations, a typical compiler (ac_c_decl_warn_flag='') reports an error for
> "(void) strchr;".  Clang (ac_c_decl_warn_flag=yes) reports a warning, but
> adding a declaration silences the warning.  A compiler that emits some warning
> with or without a declaration is unusable.

Here is the patch.  There's a risk that incidental warnings will make
AC_CHECK_DECL wrongly report a declaration missing.  If, for example, an
AC_CHECK_DECL test includes a header that elicits a deprecation warning, that
test will report any declaration missing.  The Autoconf test suite does pass
under "clang -Weverything -Wno-unused-macros -Wno-main" or "clang -Wno-main".
"-Wno-unused-macros" suppresses warnings about unused confdefs.h macros like
PACKAGE_URL, warnings which would otherwise snag on one of the new sanity
checks.  (Unrelated to AC_CHECK_DECL, the "C unit tests" group needs
"-Wno-main".)  I considered -fno-builtin instead of checking for warnings, but
the loss of realism outweighs the benefit of mitigating this risk.

The new code caches its test results.  _AC_PROG_PREPROC_WORKS_IFELSE, which
inspired the new code, does not cache.  Did I overlook a good reason for not
caching the results of tests like these?

I manually tested with C, C++, Objective C and Objective C++ languages.

Thanks,
nm


commit aaf9aba (HEAD, master)
Author:     Noah Misch <address@hidden>
AuthorDate: Mon Apr 13 01:38:15 2015 -0400
Commit:     Noah Misch <address@hidden>
CommitDate: Mon Apr 13 01:38:15 2015 -0400

    AC_CHECK_DECL, AC_CHECK_DECLS: port to the Clang compiler
    
    * lib/autoconf/general.m4 (_AC_UNDECLARED_WARNING): New macro.
    (_AC_CHECK_DECL_BODY): Call it once per language; treat warnings as
    errors when its verdict indicates that.
    * tests/semantics.at (AC_CHECK_DECLS): Add a macro call that relies on
    the new semantics.  Avoid -Wmissing-variable-declarations warnings.
    * doc/autoconf.texi (Generic Declarations): Document the implications.
    * NEWS: Mention this change.

diff --git a/NEWS b/NEWS
index 2df5a80..f691179 100644
--- a/NEWS
+++ b/NEWS
@@ -61,6 +61,9 @@ GNU Autoconf NEWS - User visible changes.
 - AC_USE_SYSTEM_EXTENSIONS now enables more system extensions on HP-UX,
   MINIX 3, and OS X.
 
+- AC_CHECK_DECL and AC_CHECK_DECLS can now report missing declarations for
+  functions that are also Clang compiler builtins.
+
 - AC_FUNC_VFORK now checks for the signal-handling bug in Solaris 2.4 'vfork'.
   Formerly, it ignored this bug, so that Emacs could use some tricky
   code on that platform.  Solaris 2.4 has not been supported since
diff --git a/doc/autoconf.texi b/doc/autoconf.texi
index d9e833d..350855b 100644
--- a/doc/autoconf.texi
+++ b/doc/autoconf.texi
@@ -6315,6 +6315,12 @@ parentheses for types which can be zero-initialized:
 AC_CHECK_DECL([basename(char *)])
 @end example
 
+Some compilers don't indicate every missing declaration by the error
+status.  This macro checks the standard error from such compilers and
+considers a declaration missing if any warnings have been reported.  For
+most compilers, though, warnings do not affect this macro's outcome
+unless @code{AC_LANG_WERROR} is also specified.
+
 This macro caches its result in the @address@hidden
 variable, with characters not suitable for a variable name mapped to
 underscores.
@@ -6375,6 +6381,12 @@ You fall into the second category only in extreme 
situations: either
 your files may be used without being configured, or they are used during
 the configuration.  In most cases the traditional approach is enough.
 
+Some compilers don't indicate every missing declaration by the error
+status.  This macro checks the standard error from such compilers and
+considers a declaration missing if any warnings have been reported.  For
+most compilers, though, warnings do not affect this macro's outcome
+unless @code{AC_LANG_WERROR} is also specified.
+
 This macro caches its results in @address@hidden
 variables, with characters not suitable for a variable name mapped to
 underscores.
diff --git a/lib/autoconf/general.m4 b/lib/autoconf/general.m4
index 2d1a291..09896e2 100644
--- a/lib/autoconf/general.m4
+++ b/lib/autoconf/general.m4
@@ -2864,15 +2864,72 @@ AC_DEFUN([AC_CHECK_FILES],
 ## ------------------------------- ##
 
 
+# _AC_UNDECLARED_WARNING
+# ----------------------
+# Set ac_[]_AC_LANG_ABBREV[]_decl_warn_flag=yes if the compiler uses a warning,
+# not a more-customary error, to report some undeclared identifiers.  Fail when
+# an affected compiler warns also on valid input.  
_AC_PROG_PREPROC_WORKS_IFELSE
+# solves a related problem.
+AC_DEFUN([_AC_UNDECLARED_WARNING],
+[# The Clang compiler raises a warning for an undeclared identifier that 
matches
+# a compiler builtin function.  All extant Clang versions are affected, as of
+# Clang 3.6.0.  Test a builtin known to every version.  This problem affects 
the
+# C and Objective C languages, but Clang does report an error under C++ and
+# Objective C++.
+#
+# Passing -fno-builtin to the compiler would suppress this problem.  That
+# strategy would have the advantage of being insensitive to stray warnings, but
+# it would make tests less realistic.
+AC_CACHE_CHECK([how $[]_AC_CC[] reports undeclared, standard C functions],
+[ac_cv_[]_AC_LANG_ABBREV[]_decl_report],
+[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [(void) strchr;])],
+  [AS_IF([test -s conftest.err], [dnl
+    # For AC_CHECK_DECL to react to warnings, the compiler must be silent on
+    # valid AC_CHECK_DECL input.  No library function is consistently available
+    # on freestanding implementations, so test against a dummy declaration.
+    # Include always-available headers on the off chance that they somehow
+    # elicit warnings.
+    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([dnl
+#include <float.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stddef.h>
+extern void ac_decl (int, char *);],
address@hidden:@ifdef __cplusplus
+  (void) ac_decl ((int) 0, (char *) 0);
+  (void) ac_decl;
address@hidden:@else
+  (void) ac_decl;
address@hidden:@endif
+])],
+      [AS_IF([test -s conftest.err],
+       [AC_MSG_FAILURE([cannot detect from compiler exit status or warnings])],
+       [ac_cv_[]_AC_LANG_ABBREV[]_decl_report=warning])],
+      [AC_MSG_FAILURE([cannot compile a simple declaration test])])],
+    [AC_MSG_FAILURE([compiler does not report undeclared identifiers])])],
+  [ac_cv_[]_AC_LANG_ABBREV[]_decl_report=error])])
+
+case $ac_cv_[]_AC_LANG_ABBREV[]_decl_report in
+  warning) ac_[]_AC_LANG_ABBREV[]_decl_warn_flag=yes ;;
+  *) ac_[]_AC_LANG_ABBREV[]_decl_warn_flag= ;;
+esac
+])# _AC_UNDECLARED_WARNING
+
 # _AC_CHECK_DECL_BODY
 # -------------------
 # Shell function body for AC_CHECK_DECL.
 m4_define([_AC_CHECK_DECL_BODY],
 [  AS_LINENO_PUSH([$[]1])
+  # Initialize each $ac_[]_AC_LANG_ABBREV[]_decl_warn_flag once.
+  AC_DEFUN([_AC_UNDECLARED_WARNING_]_AC_LANG_ABBREV,
+          [_AC_UNDECLARED_WARNING])dnl
+  AC_REQUIRE([_AC_UNDECLARED_WARNING_]_AC_LANG_ABBREV)dnl
   [as_decl_name=`echo $][2|sed 's/ *(.*//'`]
   [as_decl_use=`echo $][2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`]
   AC_CACHE_CHECK([whether $as_decl_name is declared], [$[]3],
-  [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([$[]4],
+  [ac_save_werror_flag=$ac_[]_AC_LANG_ABBREV[]_werror_flag
+  
ac_[]_AC_LANG_ABBREV[]_werror_flag="$ac_[]_AC_LANG_ABBREV[]_decl_warn_flag$ac_[]_AC_LANG_ABBREV[]_werror_flag"
+  AC_COMPILE_IFELSE([AC_LANG_PROGRAM([$[]4],
 address@hidden:@ifndef $[]as_decl_name
 @%:@ifdef __cplusplus
   (void) $[]as_decl_use;
@@ -2883,6 +2940,7 @@ m4_define([_AC_CHECK_DECL_BODY],
 ])],
                   [AS_VAR_SET([$[]3], [yes])],
                   [AS_VAR_SET([$[]3], [no])])])
+  ac_[]_AC_LANG_ABBREV[]_werror_flag=$ac_save_werror_flag
   AS_LINENO_POP
 ])# _AC_CHECK_DECL_BODY
 
diff --git a/tests/semantics.at b/tests/semantics.at
index a7abd52..1294545 100644
--- a/tests/semantics.at
+++ b/tests/semantics.at
@@ -101,15 +101,18 @@ esac
 
 # AC_CHECK_DECLS
 # --------------
-# Check that it performs the correct actions:
+# For the benefit of _AC_UNDECLARED_WARNING compilers, these INCLUDES sections
+# should not elicit warnings.
 AT_CHECK_MACRO([AC_CHECK_DECLS],
 [[AC_CHECK_DECLS([yes, no, myenum, mystruct, myfunc, mymacro1, mymacro2],,,
-                [[int yes = 1;
+                [[extern int yes;
                   enum { myenum };
-                  struct { int x[20]; } mystruct;
+                  extern struct { int x[20]; } mystruct;
                   extern int myfunc();
                   #define mymacro1(arg) arg
                   #define mymacro2]])
+  # Clang reports a warning for an undeclared builtin.
+  AC_CHECK_DECLS([strerror],,, [[]])
   # The difference in space-before-open-paren is intentional.
   AC_CHECK_DECLS([basenam (char *), dirnam(char *),
                  [moreargs (char, short, int, long, void *, char [], float, 
double)]],,,
@@ -148,6 +151,7 @@ AT_CHECK_MACRO([AC_CHECK_DECLS],
 #define HAVE_DECL_MYMACRO2 1
 #define HAVE_DECL_MYSTRUCT 1
 #define HAVE_DECL_NO 0
+#define HAVE_DECL_STRERROR 0
 #define HAVE_DECL_YES 1
 ])])
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]