summaryrefslogtreecommitdiffstats
path: root/lib/error.in.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--lib/error.in.h103
1 files changed, 98 insertions, 5 deletions
diff --git a/lib/error.in.h b/lib/error.in.h
index 9a520f1..51f8caf 100644
--- a/lib/error.in.h
+++ b/lib/error.in.h
@@ -1,5 +1,5 @@
/* Declarations for error-reporting functions.
- Copyright (C) 1995-1997, 2003, 2006, 2008-2023 Free Software Foundation,
+ Copyright (C) 1995-1997, 2003, 2006, 2008-2024 Free Software Foundation,
Inc.
This file is part of the GNU C Library.
@@ -18,9 +18,9 @@
#ifndef _@GUARD_PREFIX@_ERROR_H
-#if __GNUC__ >= 3
-@PRAGMA_SYSTEM_HEADER@
-#endif
+/* No @PRAGMA_SYSTEM_HEADER@ here, because it would prevent
+ -Wimplicit-fallthrough warnings for missing FALLTHROUGH after error(...)
+ or error_at_line(...) invocations. */
/* The include_next requires a split double-inclusion guard. */
#if @HAVE_ERROR_H@
@@ -30,11 +30,15 @@
#ifndef _@GUARD_PREFIX@_ERROR_H
#define _@GUARD_PREFIX@_ERROR_H
-/* This file uses _GL_ATTRIBUTE_FORMAT. */
+/* This file uses _GL_ATTRIBUTE_ALWAYS_INLINE, _GL_ATTRIBUTE_FORMAT,
+ _GL_ATTRIBUTE_MAYBE_UNUSED. */
#if !_GL_CONFIG_H_INCLUDED
#error "Please include config.h first."
#endif
+/* Get 'unreachable'. */
+#include <stddef.h>
+
/* Get _GL_ATTRIBUTE_SPEC_PRINTF_STANDARD, _GL_ATTRIBUTE_SPEC_PRINTF_SYSTEM. */
#include <stdio.h>
@@ -46,6 +50,35 @@
# define _GL_ATTRIBUTE_SPEC_PRINTF_ERROR _GL_ATTRIBUTE_SPEC_PRINTF_SYSTEM
#endif
+/* Helper macro for supporting the compiler's control flow analysis better.
+ It evaluates its arguments only once.
+ Test case: Compile copy-file.c with "gcc -Wimplicit-fallthrough". */
+#if defined __GNUC__ || defined __clang__
+/* Use 'unreachable' to tell the compiler when the function call does not
+ return. */
+# define __gl_error_call1(function, status, ...) \
+ ((function) (status, __VA_ARGS__), \
+ (status) != 0 ? unreachable () : (void) 0)
+/* If STATUS is a not a constant, the function call may or may not return;
+ therefore -Wimplicit-fallthrough will produce a warning. Use a compound
+ statement in order to evaluate STATUS only once.
+ If STATUS is a constant, we don't use a compound statement, because that
+ would trigger a -Wimplicit-fallthrough warning even when STATUS is != 0,
+ when not optimizing. This causes STATUS to be evaluated twice, but
+ that's OK since it does not have side effects. */
+# define __gl_error_call(function, status, ...) \
+ (__builtin_constant_p (status) \
+ ? __gl_error_call1 (function, status, __VA_ARGS__) \
+ : __extension__ \
+ ({ \
+ int const __errstatus = status; \
+ __gl_error_call1 (function, __errstatus, __VA_ARGS__); \
+ }))
+#else
+# define __gl_error_call(function, status, ...) \
+ (function) (status, __VA_ARGS__)
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -63,6 +96,11 @@ _GL_FUNCDECL_RPL (error, void,
_GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_PRINTF_ERROR, 3, 4)));
_GL_CXXALIAS_RPL (error, void,
(int __status, int __errnum, const char *__format, ...));
+# ifndef _GL_NO_INLINE_ERROR
+# undef error
+# define error(status, ...) \
+ __gl_error_call (rpl_error, status, __VA_ARGS__)
+# endif
#else
# if ! @HAVE_ERROR@
_GL_FUNCDECL_SYS (error, void,
@@ -71,6 +109,30 @@ _GL_FUNCDECL_SYS (error, void,
# endif
_GL_CXXALIAS_SYS (error, void,
(int __status, int __errnum, const char *__format, ...));
+# ifndef _GL_NO_INLINE_ERROR
+# ifdef error
+/* Only gcc ≥ 4.7 has __builtin_va_arg_pack. */
+# if _GL_GNUC_PREREQ (4, 7)
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wattributes"
+_GL_ATTRIBUTE_MAYBE_UNUSED
+static void
+_GL_ATTRIBUTE_ALWAYS_INLINE
+_GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_PRINTF_ERROR, 3, 4))
+_gl_inline_error (int __status, int __errnum, const char *__format, ...)
+{
+ return error (__status, __errnum, __format, __builtin_va_arg_pack ());
+}
+# pragma GCC diagnostic pop
+# undef error
+# define error(status, ...) \
+ __gl_error_call (_gl_inline_error, status, __VA_ARGS__)
+# endif
+# else
+# define error(status, ...) \
+ __gl_error_call (error, status, __VA_ARGS__)
+# endif
+# endif
#endif
#if __GLIBC__ >= 2
_GL_CXXALIASWARN (error);
@@ -90,6 +152,11 @@ _GL_FUNCDECL_RPL (error_at_line, void,
_GL_CXXALIAS_RPL (error_at_line, void,
(int __status, int __errnum, const char *__filename,
unsigned int __lineno, const char *__format, ...));
+# ifndef _GL_NO_INLINE_ERROR
+# undef error_at_line
+# define error_at_line(status, ...) \
+ __gl_error_call (rpl_error_at_line, status, __VA_ARGS__)
+# endif
#else
# if ! @HAVE_ERROR_AT_LINE@
_GL_FUNCDECL_SYS (error_at_line, void,
@@ -100,6 +167,32 @@ _GL_FUNCDECL_SYS (error_at_line, void,
_GL_CXXALIAS_SYS (error_at_line, void,
(int __status, int __errnum, const char *__filename,
unsigned int __lineno, const char *__format, ...));
+# ifndef _GL_NO_INLINE_ERROR
+# ifdef error_at_line
+/* Only gcc ≥ 4.7 has __builtin_va_arg_pack. */
+# if _GL_GNUC_PREREQ (4, 7)
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wattributes"
+_GL_ATTRIBUTE_MAYBE_UNUSED
+static void
+_GL_ATTRIBUTE_ALWAYS_INLINE
+_GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_PRINTF_ERROR, 5, 6))
+_gl_inline_error_at_line (int __status, int __errnum, const char *__filename,
+ unsigned int __lineno, const char *__format, ...)
+{
+ return error_at_line (__status, __errnum, __filename, __lineno, __format,
+ __builtin_va_arg_pack ());
+}
+# pragma GCC diagnostic pop
+# undef error_at_line
+# define error_at_line(status, ...) \
+ __gl_error_call (_gl_inline_error_at_line, status, __VA_ARGS__)
+# endif
+# else
+# define error_at_line(status, ...) \
+ __gl_error_call (error_at_line, status, __VA_ARGS__)
+# endif
+# endif
#endif
_GL_CXXALIASWARN (error_at_line);