From 3ce62ef897dfb1e76fc4a34505c19f339359d2b1 Mon Sep 17 00:00:00 2001
From: Roman Tsisyk <roman@tarantool.org>
Date: Tue, 12 Sep 2017 16:41:41 +0300
Subject: [PATCH] Add FALLTHROUGH macro

The fallthrough attribute with a null statement serves as a fallthrough
statement. It hints to the compiler that a statement that falls through
to another case label, or user-defined label in a switch statement is
intentional and thus the -Wimplicit-fallthrough warning must not trigger.
The fallthrough attribute may appear at most once in each attribute list,
and may not be mixed with other attributes. It can only be used in a switch
statement (the compiler will issue an error otherwise), after a preceding
statement and before a logically succeeding case label, or user-defined
label.

https://developers.redhat.com/blog/2017/03/10/wimplicit-fallthrough-in-gcc-7/
---
 cmake/BuildMisc.cmake |  6 ------
 src/trivia/util.h     | 23 +++++++++++++++++++++++
 third_party/base64.c  |  4 ++++
 3 files changed, 27 insertions(+), 6 deletions(-)

diff --git a/cmake/BuildMisc.cmake b/cmake/BuildMisc.cmake
index fee02227e4..20ecb4f630 100644
--- a/cmake/BuildMisc.cmake
+++ b/cmake/BuildMisc.cmake
@@ -8,12 +8,6 @@ macro(libmisc_build)
         ${PROJECT_SOURCE_DIR}/third_party/qsort_arg.c
     )
 
-    if (CC_HAS_WNO_IMPLICIT_FALLTHROUGH)
-        # Disable false-positive warnings in switch() {} block
-        set_source_files_properties(${PROJECT_SOURCE_DIR}/third_party/base64.c
-            PROPERTIES COMPILE_FLAGS -Wno-implicit-fallthrough)
-    endif()
-
     if (NOT HAVE_MEMMEM)
         list(APPEND misc_src
             ${PROJECT_SOURCE_DIR}/third_party/memmem.c
diff --git a/src/trivia/util.h b/src/trivia/util.h
index e85b2b1141..12406cca0c 100644
--- a/src/trivia/util.h
+++ b/src/trivia/util.h
@@ -364,6 +364,29 @@ strindex(const char **haystack, const char *needle, uint32_t hmax);
 
 /** Function Attributes }}} */
 
+/** {{{ Statement Attributes */
+
+/**
+ * The fallthrough attribute with a null statement serves as a fallthrough
+ * statement. It hints to the compiler that a statement that falls through
+ * to another case label, or user-defined label in a switch statement is
+ * intentional and thus the -Wimplicit-fallthrough warning must not trigger.
+ * The fallthrough attribute may appear at most once in each attribute list,
+ * and may not be mixed with other attributes. It can only be used in a switch
+ * statement (the compiler will issue an error otherwise), after a preceding
+ * statement and before a logically succeeding case label, or user-defined
+ * label.
+ */
+#if defined(__cplusplus) && __has_cpp_attribute(fallthrough)
+#  define FALLTHROUGH [[fallthrough]]
+#elif __has_attribute(fallthrough) || (defined(__GNUC__) && __GNUC__ >= 7)
+#  define FALLTHROUGH __attribute__((fallthrough))
+#else
+#  define FALLTHROUGH
+#endif
+
+/** Statement Attributes }}} */
+
 /** \endcond public */
 
 void close_all_xcpt(int fdc, ...);
diff --git a/third_party/base64.c b/third_party/base64.c
index d58aa0a4c8..7df485f9fe 100644
--- a/third_party/base64.c
+++ b/third_party/base64.c
@@ -27,6 +27,8 @@
  * SUCH DAMAGE.
  */
 #include "third_party/base64.h"
+#include <trivia/util.h>
+
 /*
  * This is part of the libb64 project, and has been placed in the
  * public domain. For details, see
@@ -92,6 +94,7 @@ base64_encode_block(const char *in_bin, int in_len,
 			result = (fragment & 0x0fc) >> 2;
 			*out_pos++ = base64_encode_value(result);
 			result = (fragment & 0x003) << 4;
+			FALLTHROUGH;
 	case step_B:
 			if (in_pos == in_end || out_pos >= out_end) {
 				state->result = result;
@@ -102,6 +105,7 @@ base64_encode_block(const char *in_bin, int in_len,
 			result |= (fragment & 0x0f0) >> 4;
 			*out_pos++ = base64_encode_value(result);
 			result = (fragment & 0x00f) << 2;
+			FALLTHROUGH;
 	case step_C:
 			if (in_pos == in_end || out_pos + 2 >= out_end) {
 				state->result = result;
-- 
GitLab