Explicit fallthrough on switch

Fixes failed compile with [-Werror=implicit-fallthrough=], which is
default on gcc-7.x on distributions like fedora.

Enabling no implicit fallthrough for more than just clang as well to
catch this going forward.

Change-Id: I6cd880dac70ec126bd7812e2d9e5ff804d32cadd
Signed-off-by: Vincent Batts <vbatts@redhat.com>
Reviewed-on: https://boringssl-review.googlesource.com/20564
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c32b707..0b95a81 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -38,6 +38,7 @@
 
 if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
   set(C_CXX_FLAGS "-Wall -Werror -Wformat=2 -Wsign-compare -Wmissing-field-initializers -Wwrite-strings -ggdb -fvisibility=hidden -fno-common")
+
   if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
     set(C_CXX_FLAGS "${C_CXX_FLAGS} -Wnewline-eof -fcolor-diagnostics")
   else()
@@ -45,6 +46,12 @@
     # and declare that the code is trying to free a stack pointer.
     set(C_CXX_FLAGS "${C_CXX_FLAGS} -Wno-free-nonheap-object")
   endif()
+
+  if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR
+     NOT "7.0.0" VERSION_GREATER CMAKE_C_COMPILER_VERSION)
+    set(C_CXX_FLAGS "${C_CXX_FLAGS} -Wimplicit-fallthrough")
+  endif()
+
   set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_CXX_FLAGS} -Wmissing-prototypes -Wold-style-definition -Wstrict-prototypes")
   set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ${C_CXX_FLAGS} -Wmissing-declarations")
 
@@ -60,7 +67,7 @@
   # https://clang.llvm.org/docs/DiagnosticsReference.html#wmissing-prototypes
   # https://clang.llvm.org/docs/DiagnosticsReference.html#wmissing-declarations
   if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
-    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wmissing-prototypes -Wimplicit-fallthrough")
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wmissing-prototypes")
   endif()
 elseif(MSVC)
   set(MSVC_DISABLED_WARNINGS_LIST
diff --git a/crypto/bio/fd.c b/crypto/bio/fd.c
index 37840a7..ea5bfd8 100644
--- a/crypto/bio/fd.c
+++ b/crypto/bio/fd.c
@@ -190,6 +190,7 @@
   switch (cmd) {
     case BIO_CTRL_RESET:
       num = 0;
+      OPENSSL_FALLTHROUGH;
     case BIO_C_FILE_SEEK:
       ret = 0;
       if (b->init) {
diff --git a/crypto/bio/file.c b/crypto/bio/file.c
index 25c1dbd..278be18 100644
--- a/crypto/bio/file.c
+++ b/crypto/bio/file.c
@@ -183,6 +183,7 @@
   switch (cmd) {
     case BIO_CTRL_RESET:
       num = 0;
+      OPENSSL_FALLTHROUGH;
     case BIO_C_FILE_SEEK:
       ret = (long)fseek(fp, num, 0);
       break;
diff --git a/crypto/cipher_extra/e_rc2.c b/crypto/cipher_extra/e_rc2.c
index dc42dd5..0b2caf5 100644
--- a/crypto/cipher_extra/e_rc2.c
+++ b/crypto/cipher_extra/e_rc2.c
@@ -73,18 +73,25 @@
     switch (n) {                               \
       case 8:                                  \
         (l2) = ((uint32_t)(*(--(c)))) << 24L;  \
+        OPENSSL_FALLTHROUGH;                   \
       case 7:                                  \
         (l2) |= ((uint32_t)(*(--(c)))) << 16L; \
+        OPENSSL_FALLTHROUGH;                   \
       case 6:                                  \
         (l2) |= ((uint32_t)(*(--(c)))) << 8L;  \
+        OPENSSL_FALLTHROUGH;                   \
       case 5:                                  \
         (l2) |= ((uint32_t)(*(--(c))));        \
+        OPENSSL_FALLTHROUGH;                   \
       case 4:                                  \
         (l1) = ((uint32_t)(*(--(c)))) << 24L;  \
+        OPENSSL_FALLTHROUGH;                   \
       case 3:                                  \
         (l1) |= ((uint32_t)(*(--(c)))) << 16L; \
+        OPENSSL_FALLTHROUGH;                   \
       case 2:                                  \
         (l1) |= ((uint32_t)(*(--(c)))) << 8L;  \
+        OPENSSL_FALLTHROUGH;                   \
       case 1:                                  \
         (l1) |= ((uint32_t)(*(--(c))));        \
     }                                          \
@@ -104,18 +111,25 @@
     switch (n) {                                    \
       case 8:                                       \
         *(--(c)) = (uint8_t)(((l2) >> 24L) & 0xff); \
+        OPENSSL_FALLTHROUGH;                        \
       case 7:                                       \
         *(--(c)) = (uint8_t)(((l2) >> 16L) & 0xff); \
+        OPENSSL_FALLTHROUGH;                        \
       case 6:                                       \
         *(--(c)) = (uint8_t)(((l2) >> 8L) & 0xff);  \
+        OPENSSL_FALLTHROUGH;                        \
       case 5:                                       \
         *(--(c)) = (uint8_t)(((l2)) & 0xff);        \
+        OPENSSL_FALLTHROUGH;                        \
       case 4:                                       \
         *(--(c)) = (uint8_t)(((l1) >> 24L) & 0xff); \
+        OPENSSL_FALLTHROUGH;                        \
       case 3:                                       \
         *(--(c)) = (uint8_t)(((l1) >> 16L) & 0xff); \
+        OPENSSL_FALLTHROUGH;                        \
       case 2:                                       \
         *(--(c)) = (uint8_t)(((l1) >> 8L) & 0xff);  \
+        OPENSSL_FALLTHROUGH;                        \
       case 1:                                       \
         *(--(c)) = (uint8_t)(((l1)) & 0xff);        \
     }                                               \
diff --git a/crypto/fipsmodule/bn/mul.c b/crypto/fipsmodule/bn/mul.c
index 7cc0e3c..a4e27f2 100644
--- a/crypto/fipsmodule/bn/mul.c
+++ b/crypto/fipsmodule/bn/mul.c
@@ -230,11 +230,13 @@
             if (--dl <= 0) {
               break;
             }
+            OPENSSL_FALLTHROUGH;
           case 2:
             r[2] = a[2];
             if (--dl <= 0) {
               break;
             }
+            OPENSSL_FALLTHROUGH;
           case 3:
             r[3] = a[3];
             if (--dl <= 0) {
diff --git a/crypto/fipsmodule/des/internal.h b/crypto/fipsmodule/des/internal.h
index 7bfc45b..4d65ff1 100644
--- a/crypto/fipsmodule/des/internal.h
+++ b/crypto/fipsmodule/des/internal.h
@@ -88,18 +88,25 @@
     switch (n) {                               \
       case 8:                                  \
         (l2) = ((uint32_t)(*(--(c)))) << 24L;  \
+        OPENSSL_FALLTHROUGH;                   \
       case 7:                                  \
         (l2) |= ((uint32_t)(*(--(c)))) << 16L; \
+        OPENSSL_FALLTHROUGH;                   \
       case 6:                                  \
         (l2) |= ((uint32_t)(*(--(c)))) << 8L;  \
+        OPENSSL_FALLTHROUGH;                   \
       case 5:                                  \
         (l2) |= ((uint32_t)(*(--(c))));        \
+        OPENSSL_FALLTHROUGH;                   \
       case 4:                                  \
         (l1) = ((uint32_t)(*(--(c)))) << 24L;  \
+        OPENSSL_FALLTHROUGH;                   \
       case 3:                                  \
         (l1) |= ((uint32_t)(*(--(c)))) << 16L; \
+        OPENSSL_FALLTHROUGH;                   \
       case 2:                                  \
         (l1) |= ((uint32_t)(*(--(c)))) << 8L;  \
+        OPENSSL_FALLTHROUGH;                   \
       case 1:                                  \
         (l1) |= ((uint32_t)(*(--(c))));        \
     }                                          \
@@ -112,18 +119,25 @@
     switch (n) {                                          \
       case 8:                                             \
         *(--(c)) = (unsigned char)(((l2) >> 24L) & 0xff); \
+        OPENSSL_FALLTHROUGH;                              \
       case 7:                                             \
         *(--(c)) = (unsigned char)(((l2) >> 16L) & 0xff); \
+        OPENSSL_FALLTHROUGH;                              \
       case 6:                                             \
         *(--(c)) = (unsigned char)(((l2) >> 8L) & 0xff);  \
+        OPENSSL_FALLTHROUGH;                              \
       case 5:                                             \
         *(--(c)) = (unsigned char)(((l2)) & 0xff);        \
+        OPENSSL_FALLTHROUGH;                              \
       case 4:                                             \
         *(--(c)) = (unsigned char)(((l1) >> 24L) & 0xff); \
+        OPENSSL_FALLTHROUGH;                              \
       case 3:                                             \
         *(--(c)) = (unsigned char)(((l1) >> 16L) & 0xff); \
+        OPENSSL_FALLTHROUGH;                              \
       case 2:                                             \
         *(--(c)) = (unsigned char)(((l1) >> 8L) & 0xff);  \
+        OPENSSL_FALLTHROUGH;                              \
       case 1:                                             \
         *(--(c)) = (unsigned char)(((l1)) & 0xff);        \
     }                                                     \
diff --git a/decrepit/macros.h b/decrepit/macros.h
index 6c598d4..c4ebeec 100644
--- a/decrepit/macros.h
+++ b/decrepit/macros.h
@@ -66,18 +66,25 @@
     switch (n) {                                 \
       case 8:                                    \
         l2 = ((unsigned long)(*(--(c))));        \
+	OPENSSL_FALLTHROUGH;                     \
       case 7:                                    \
         l2 |= ((unsigned long)(*(--(c)))) << 8;  \
+	OPENSSL_FALLTHROUGH;                     \
       case 6:                                    \
         l2 |= ((unsigned long)(*(--(c)))) << 16; \
+	OPENSSL_FALLTHROUGH;                     \
       case 5:                                    \
         l2 |= ((unsigned long)(*(--(c)))) << 24; \
+	OPENSSL_FALLTHROUGH;                     \
       case 4:                                    \
         l1 = ((unsigned long)(*(--(c))));        \
+	OPENSSL_FALLTHROUGH;                     \
       case 3:                                    \
         l1 |= ((unsigned long)(*(--(c)))) << 8;  \
+	OPENSSL_FALLTHROUGH;                     \
       case 2:                                    \
         l1 |= ((unsigned long)(*(--(c)))) << 16; \
+	OPENSSL_FALLTHROUGH;                     \
       case 1:                                    \
         l1 |= ((unsigned long)(*(--(c)))) << 24; \
     }                                            \
@@ -90,18 +97,25 @@
     switch (n) {                                         \
       case 8:                                            \
         *(--(c)) = (unsigned char)(((l2)) & 0xff);       \
+	OPENSSL_FALLTHROUGH;                             \
       case 7:                                            \
         *(--(c)) = (unsigned char)(((l2) >> 8) & 0xff);  \
+	OPENSSL_FALLTHROUGH;                             \
       case 6:                                            \
         *(--(c)) = (unsigned char)(((l2) >> 16) & 0xff); \
+	OPENSSL_FALLTHROUGH;                             \
       case 5:                                            \
         *(--(c)) = (unsigned char)(((l2) >> 24) & 0xff); \
+	OPENSSL_FALLTHROUGH;                             \
       case 4:                                            \
         *(--(c)) = (unsigned char)(((l1)) & 0xff);       \
+	OPENSSL_FALLTHROUGH;                             \
       case 3:                                            \
         *(--(c)) = (unsigned char)(((l1) >> 8) & 0xff);  \
+	OPENSSL_FALLTHROUGH;                             \
       case 2:                                            \
         *(--(c)) = (unsigned char)(((l1) >> 16) & 0xff); \
+	OPENSSL_FALLTHROUGH;                             \
       case 1:                                            \
         *(--(c)) = (unsigned char)(((l1) >> 24) & 0xff); \
     }                                                    \
diff --git a/include/openssl/base.h b/include/openssl/base.h
index a796c73..2be5ed0 100644
--- a/include/openssl/base.h
+++ b/include/openssl/base.h
@@ -219,6 +219,19 @@
 #endif
 #endif
 
+// Have a generic fall-through for different versions of C/C++.
+#if defined(__cplusplus) && __cplusplus >= 201703L
+#define OPENSSL_FALLTHROUGH [[fallthrough]]
+#elif defined(__cplusplus) && __cplusplus >= 201103L && defined(__clang__)
+#define OPENSSL_FALLTHROUGH [[clang::fallthrough]]
+#elif defined(__cplusplus) && __cplusplus >= 201103L && __GNUC__ >= 7
+#define OPENSSL_FALLTHROUGH [[gnu::fallthrough]]
+#elif  __GNUC__ >= 7 // gcc 7
+#define OPENSSL_FALLTHROUGH __attribute__ ((fallthrough))
+#else // C++11 on gcc 6, and all other cases
+#define OPENSSL_FALLTHROUGH
+#endif
+
 // CRYPTO_THREADID is a dummy value.
 typedef int CRYPTO_THREADID;
 
diff --git a/ssl/internal.h b/ssl/internal.h
index 9e67457..89f9046 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -2396,16 +2396,6 @@
 // ssl_reset_error_state resets state for |SSL_get_error|.
 void ssl_reset_error_state(SSL *ssl);
 
-
-// Utility macros
-
-#if defined(__clang__)
-// SSL_FALLTHROUGH annotates a fallthough case in a switch statement.
-#define SSL_FALLTHROUGH [[clang::fallthrough]]
-#else
-#define SSL_FALLTHROUGH
-#endif
-
 }  // namespace bssl