diff --git a/CODING_STYLE.md b/CODING_STYLE.md index 80d4096d8..54ac6d4ad 100644 --- a/CODING_STYLE.md +++ b/CODING_STYLE.md @@ -633,3 +633,32 @@ string. Unless you have a valid reason to accept truncation you must check whether truncation has occurred, treat it as an error, and handle the error appropriately. + +## 25) Use `__fallthrough__` in switch statements + +If LXC detects that the compiler is new enough it will tell it to check +`switch` statements for non-documented fallthroughs. Please always place +a `__fallthrough__` after a `case` which falls through the next one. + +```c +int lxc_attach_run_command(void *payload) +{ + int ret = -1; + lxc_attach_command_t *cmd = payload; + + ret = execvp(cmd->program, cmd->argv); + if (ret < 0) { + switch (errno) { + case ENOEXEC: + ret = 126; + break; + case ENOENT: + ret = 127; + break; + } + } + + SYSERROR("Failed to exec \"%s\"", cmd->program); + return ret; +} +``` diff --git a/config/ax_check_compile_flag.m4 b/config/ax_check_compile_flag.m4 new file mode 100644 index 000000000..bd753b34d --- /dev/null +++ b/config/ax_check_compile_flag.m4 @@ -0,0 +1,53 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) +# +# DESCRIPTION +# +# Check whether the given FLAG works with the current language's compiler +# or gives an error. (Warnings, however, are ignored) +# +# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on +# success/failure. +# +# If EXTRA-FLAGS is defined, it is added to the current language's default +# flags (e.g. CFLAGS) when the check is done. The check is thus made with +# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to +# force the compiler to issue an error when a bad flag is given. +# +# INPUT gives an alternative input source to AC_COMPILE_IFELSE. +# +# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this +# macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. +# +# LICENSE +# +# Copyright (c) 2008 Guido U. Draheim +# Copyright (c) 2011 Maarten Bosmans +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 6 + +AC_DEFUN([AX_CHECK_COMPILE_FLAG], +[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF +AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl +AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ + ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS + _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" + AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], + [AS_VAR_SET(CACHEVAR,[yes])], + [AS_VAR_SET(CACHEVAR,[no])]) + _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) +AS_VAR_IF(CACHEVAR,yes, + [m4_default([$2], :)], + [m4_default([$3], :)]) +AS_VAR_POPDEF([CACHEVAR])dnl +])dnl AX_CHECK_COMPILE_FLAGS diff --git a/configure.ac b/configure.ac index 92d6601d7..542885767 100644 --- a/configure.ac +++ b/configure.ac @@ -683,6 +683,9 @@ AC_PROG_SED # See if we support thread-local storage. LXC_CHECK_TLS +AX_CHECK_COMPILE_FLAG([-fdiagnostics-color], [CFLAGS="$CFLAGS -fdiagnostics-color"],,[-Werror]) +AX_CHECK_COMPILE_FLAG([-fdiagnostics-color], [CFLAGS="$CFLAGS -Wimplicit-fallthrough"],,[-Werror]) + CFLAGS="$CFLAGS -Wvla -std=gnu11" if test "x$enable_werror" = "xyes"; then CFLAGS="$CFLAGS -Werror" diff --git a/src/lxc/attach.c b/src/lxc/attach.c index e109c4640..4c01dea18 100644 --- a/src/lxc/attach.c +++ b/src/lxc/attach.c @@ -1520,8 +1520,10 @@ int lxc_attach_run_command(void *payload) switch (errno) { case ENOEXEC: ret = 126; + break; case ENOENT: ret = 127; + break; } } diff --git a/src/lxc/cmd/lxc_init.c b/src/lxc/cmd/lxc_init.c index 362f5b495..388b82173 100644 --- a/src/lxc/cmd/lxc_init.c +++ b/src/lxc/cmd/lxc_init.c @@ -39,6 +39,7 @@ #include #include +#include "compiler.h" #include "error.h" #include "initutils.h" #include "log.h" @@ -466,7 +467,7 @@ out: exit(exit_with); } -static void print_usage(const struct option longopts[]) +__noreturn__ static void print_usage_exit(const struct option longopts[]) { fprintf(stderr, "Usage: lxc-init [-n|--name=NAME] [-h|--help] [--usage] [--version]\n\ @@ -474,7 +475,7 @@ static void print_usage(const struct option longopts[]) exit(0); } -static void print_version(void) +__noreturn__ static void print_version_exit(void) { printf("%s\n", LXC_VERSION); exit(0); @@ -531,9 +532,9 @@ static int arguments_parse(struct arguments *args, int argc, args->lxcpath = optarg; break; case OPT_USAGE: - print_usage(args->options); + print_usage_exit(args->options); case OPT_VERSION: - print_version(); + print_version_exit(); case '?': print_help(); exit(EXIT_FAILURE); diff --git a/src/lxc/compiler.h b/src/lxc/compiler.h index cda44c987..f29ecbed2 100644 --- a/src/lxc/compiler.h +++ b/src/lxc/compiler.h @@ -32,4 +32,18 @@ #endif #endif +#if defined(__GNUC__) && __GNUC__ >= 7 || defined(__clang__) +#define __fallthrough__ __attribute__((fallthrough)) +#else +#define __fallthrough__ +#endif + +#ifndef _noreturn_ +#if __STDC_VERSION__ >= 201112L +#define __noreturn__ _Noreturn +#else +#define __noreturn__ __attribute__((noreturn)) +#endif +#endif + #endif /* __LXC_COMPILER_H */ diff --git a/src/lxc/tools/arguments.c b/src/lxc/tools/arguments.c index f6ee123dc..e1e4c6e49 100644 --- a/src/lxc/tools/arguments.c +++ b/src/lxc/tools/arguments.c @@ -37,6 +37,7 @@ #include #include "arguments.h" +#include "compiler.h" #include "namespace.h" #include "initutils.h" @@ -87,8 +88,8 @@ is2big: return -1; } -static void print_usage_exit(const struct option longopts[], - const struct lxc_arguments *a_args) +__noreturn__ static void print_usage_exit(const struct option longopts[], + const struct lxc_arguments *a_args) { int i; @@ -134,13 +135,14 @@ static void print_usage_exit(const struct option longopts[], exit(0); } -static void print_version_exit() +__noreturn__ static void print_version_exit() { printf("%s\n", lxc_get_version()); exit(0); } -static void print_help_exit(const struct lxc_arguments *args, int code) +__noreturn__ static void print_help_exit(const struct lxc_arguments *args, + int code) { fprintf(stderr, "\ Usage: %s %s\