Enable -Wimplicit-fallthrough.

Falling through switch cases on a clang build must now annotate the fallthrough
with the FALLTHROUGH_INTENDED macro.
Bug: 17731372

Change-Id: I836451cd5f96b01d1ababdbf9eef677fe8fa8324
diff --git a/runtime/arch/x86/fault_handler_x86.cc b/runtime/arch/x86/fault_handler_x86.cc
index 17310b6..6715fd3 100644
--- a/runtime/arch/x86/fault_handler_x86.cc
+++ b/runtime/arch/x86/fault_handler_x86.cc
@@ -113,7 +113,7 @@
       // Group 3
       case 0x66:
         operand_size_prefix = true;
-        // fallthrough
+        FALLTHROUGH_INTENDED;
 
       // Group 1
       case 0xf0:
diff --git a/runtime/base/macros.h b/runtime/base/macros.h
index b66d528..f5a38bb 100644
--- a/runtime/base/macros.h
+++ b/runtime/base/macros.h
@@ -181,6 +181,48 @@
 template<typename T> void UNUSED(const T&) {}
 #define UNREACHABLE  __builtin_unreachable
 
+// The FALLTHROUGH_INTENDED macro can be used to annotate implicit fall-through
+// between switch labels:
+//  switch (x) {
+//    case 40:
+//    case 41:
+//      if (truth_is_out_there) {
+//        ++x;
+//        FALLTHROUGH_INTENDED;  // Use instead of/along with annotations in
+//                               // comments.
+//      } else {
+//        return x;
+//      }
+//    case 42:
+//      ...
+//
+//  As shown in the example above, the FALLTHROUGH_INTENDED macro should be
+//  followed by a semicolon. It is designed to mimic control-flow statements
+//  like 'break;', so it can be placed in most places where 'break;' can, but
+//  only if there are no statements on the execution path between it and the
+//  next switch label.
+//
+//  When compiled with clang in C++11 mode, the FALLTHROUGH_INTENDED macro is
+//  expanded to [[clang::fallthrough]] attribute, which is analysed when
+//  performing switch labels fall-through diagnostic ('-Wimplicit-fallthrough').
+//  See clang documentation on language extensions for details:
+//  http://clang.llvm.org/docs/LanguageExtensions.html#clang__fallthrough
+//
+//  When used with unsupported compilers, the FALLTHROUGH_INTENDED macro has no
+//  effect on diagnostics.
+//
+//  In either case this macro has no effect on runtime behavior and performance
+//  of code.
+#if defined(__clang__) && __cplusplus >= 201103L && defined(__has_warning)
+#if __has_feature(cxx_attributes) && __has_warning("-Wimplicit-fallthrough")
+#define FALLTHROUGH_INTENDED [[clang::fallthrough]]  // NOLINT
+#endif
+#endif
+
+#ifndef FALLTHROUGH_INTENDED
+#define FALLTHROUGH_INTENDED do { } while (0)
+#endif
+
 // Annotalysis thread-safety analysis support.
 #if defined(__SUPPORT_TS_ANNOTATION__) || defined(__clang__)
 #define THREAD_ANNOTATION_ATTRIBUTE__(x)   __attribute__((x))
diff --git a/runtime/check_jni.cc b/runtime/check_jni.cc
index bfe44a2..fec1824 100644
--- a/runtime/check_jni.cc
+++ b/runtime/check_jni.cc
@@ -1128,7 +1128,7 @@
           *errorKind = "continuation";
           return utf8;
         }
-        // Fall through to take care of the final byte.
+        FALLTHROUGH_INTENDED;  // Fall-through to take care of the final byte.
       case 0x0c:
       case 0x0d:
         // Bit pattern 110x, so there is one additional byte.
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index 96b44bf..c53f6b2 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -3504,6 +3504,7 @@
   switch (tag) {
     default:
       LOG(FATAL) << "unknown JDWP tag: " << PrintableChar(tag);
+      UNREACHABLE();
 
     // Primitives.
     case JDWP::JT_BYTE:    return 'B';
diff --git a/runtime/dex_file_verifier.cc b/runtime/dex_file_verifier.cc
index 0597253..a3f3de8 100644
--- a/runtime/dex_file_verifier.cc
+++ b/runtime/dex_file_verifier.cc
@@ -142,7 +142,7 @@
         ErrorStringPrintf("Invalid use of void");
         return false;
       }
-      // Intentional fallthrough.
+      FALLTHROUGH_INTENDED;
     case 'B':
     case 'C':
     case 'D':
diff --git a/runtime/dex_instruction-inl.h b/runtime/dex_instruction-inl.h
index ad9491f..dd65f2c 100644
--- a/runtime/dex_instruction-inl.h
+++ b/runtime/dex_instruction-inl.h
@@ -460,11 +460,21 @@
    * copies of those.) Note that cases 5..2 fall through.
    */
   switch (count) {
-    case 5: arg[4] = InstA(inst_data);
-    case 4: arg[3] = (regList >> 12) & 0x0f;
-    case 3: arg[2] = (regList >> 8) & 0x0f;
-    case 2: arg[1] = (regList >> 4) & 0x0f;
-    case 1: arg[0] = regList & 0x0f; break;
+    case 5:
+      arg[4] = InstA(inst_data);
+      FALLTHROUGH_INTENDED;
+    case 4:
+      arg[3] = (regList >> 12) & 0x0f;
+      FALLTHROUGH_INTENDED;
+    case 3:
+      arg[2] = (regList >> 8) & 0x0f;
+      FALLTHROUGH_INTENDED;
+    case 2:
+      arg[1] = (regList >> 4) & 0x0f;
+      FALLTHROUGH_INTENDED;
+    case 1:
+      arg[0] = regList & 0x0f;
+      break;
     default:  // case 0
       break;  // Valid, but no need to do anything.
   }
diff --git a/runtime/dex_instruction.cc b/runtime/dex_instruction.cc
index 0a71d62..7e775f4 100644
--- a/runtime/dex_instruction.cc
+++ b/runtime/dex_instruction.cc
@@ -111,7 +111,7 @@
       if ((*insns & 0xFF) == 0) {
         return 1;  // NOP.
       } else {
-        LOG(FATAL) << "Unreachable: " << DumpString(NULL);
+        LOG(FATAL) << "Unreachable: " << DumpString(nullptr);
         return 0;
       }
   }
@@ -161,21 +161,23 @@
     case k21c: {
       switch (Opcode()) {
         case CONST_STRING:
-          if (file != NULL) {
+          if (file != nullptr) {
             uint32_t string_idx = VRegB_21c();
             os << StringPrintf("const-string v%d, %s // string@%d", VRegA_21c(),
                                PrintableString(file->StringDataByIdx(string_idx)).c_str(), string_idx);
             break;
-          }  // else fall-through
+          }
+          FALLTHROUGH_INTENDED;
         case CHECK_CAST:
         case CONST_CLASS:
         case NEW_INSTANCE:
-          if (file != NULL) {
+          if (file != nullptr) {
             uint32_t type_idx = VRegB_21c();
             os << opcode << " v" << static_cast<int>(VRegA_21c()) << ", " << PrettyType(type_idx, *file)
                << " // type@" << type_idx;
             break;
-          }  // else fall-through
+          }
+          FALLTHROUGH_INTENDED;
         case SGET:
         case SGET_WIDE:
         case SGET_OBJECT:
@@ -183,12 +185,13 @@
         case SGET_BYTE:
         case SGET_CHAR:
         case SGET_SHORT:
-          if (file != NULL) {
+          if (file != nullptr) {
             uint32_t field_idx = VRegB_21c();
             os << opcode << "  v" << static_cast<int>(VRegA_21c()) << ", " << PrettyField(field_idx, *file, true)
                << " // field@" << field_idx;
             break;
-          }  // else fall-through
+          }
+          FALLTHROUGH_INTENDED;
         case SPUT:
         case SPUT_WIDE:
         case SPUT_OBJECT:
@@ -196,12 +199,13 @@
         case SPUT_BYTE:
         case SPUT_CHAR:
         case SPUT_SHORT:
-          if (file != NULL) {
+          if (file != nullptr) {
             uint32_t field_idx = VRegB_21c();
             os << opcode << " v" << static_cast<int>(VRegA_21c()) << ", " << PrettyField(field_idx, *file, true)
                << " // field@" << field_idx;
             break;
-          }  // else fall-through
+          }
+          FALLTHROUGH_INTENDED;
         default:
           os << StringPrintf("%s v%d, thing@%d", opcode, VRegA_21c(), VRegB_21c());
           break;
@@ -221,20 +225,22 @@
         case IGET_BYTE:
         case IGET_CHAR:
         case IGET_SHORT:
-          if (file != NULL) {
+          if (file != nullptr) {
             uint32_t field_idx = VRegC_22c();
             os << opcode << " v" << static_cast<int>(VRegA_22c()) << ", v" << static_cast<int>(VRegB_22c()) << ", "
                << PrettyField(field_idx, *file, true) << " // field@" << field_idx;
             break;
-          }  // else fall-through
+          }
+          FALLTHROUGH_INTENDED;
         case IGET_QUICK:
         case IGET_OBJECT_QUICK:
-          if (file != NULL) {
+          if (file != nullptr) {
             uint32_t field_idx = VRegC_22c();
             os << opcode << " v" << static_cast<int>(VRegA_22c()) << ", v" << static_cast<int>(VRegB_22c()) << ", "
                << "// offset@" << field_idx;
             break;
-          }  // else fall-through
+          }
+          FALLTHROUGH_INTENDED;
         case IPUT:
         case IPUT_WIDE:
         case IPUT_OBJECT:
@@ -242,34 +248,38 @@
         case IPUT_BYTE:
         case IPUT_CHAR:
         case IPUT_SHORT:
-          if (file != NULL) {
+          if (file != nullptr) {
             uint32_t field_idx = VRegC_22c();
             os << opcode << " v" << static_cast<int>(VRegA_22c()) << ", v" << static_cast<int>(VRegB_22c()) << ", "
                << PrettyField(field_idx, *file, true) << " // field@" << field_idx;
             break;
-          }  // else fall-through
+          }
+          FALLTHROUGH_INTENDED;
         case IPUT_QUICK:
         case IPUT_OBJECT_QUICK:
-          if (file != NULL) {
+          if (file != nullptr) {
             uint32_t field_idx = VRegC_22c();
             os << opcode << " v" << static_cast<int>(VRegA_22c()) << ", v" << static_cast<int>(VRegB_22c()) << ", "
                << "// offset@" << field_idx;
             break;
-          }  // else fall-through
+          }
+          FALLTHROUGH_INTENDED;
         case INSTANCE_OF:
-          if (file != NULL) {
+          if (file != nullptr) {
             uint32_t type_idx = VRegC_22c();
             os << opcode << " v" << static_cast<int>(VRegA_22c()) << ", v" << static_cast<int>(VRegB_22c()) << ", "
                << PrettyType(type_idx, *file) << " // type@" << type_idx;
             break;
           }
+          FALLTHROUGH_INTENDED;
         case NEW_ARRAY:
-          if (file != NULL) {
+          if (file != nullptr) {
             uint32_t type_idx = VRegC_22c();
             os << opcode << " v" << static_cast<int>(VRegA_22c()) << ", v" << static_cast<int>(VRegB_22c()) << ", "
                << PrettyType(type_idx, *file) << " // type@" << type_idx;
             break;
-          }  // else fall-through
+          }
+          FALLTHROUGH_INTENDED;
         default:
           os << StringPrintf("%s v%d, v%d, thing@%d", opcode, VRegA_22c(), VRegB_22c(), VRegC_22c());
           break;
@@ -283,7 +293,7 @@
     case k31c:
       if (Opcode() == CONST_STRING_JUMBO) {
         uint32_t string_idx = VRegB_31c();
-        if (file != NULL) {
+        if (file != nullptr) {
           os << StringPrintf("%s v%d, %s // string@%d", opcode, VRegA_31c(),
                              PrintableString(file->StringDataByIdx(string_idx)).c_str(),
                              string_idx);
@@ -317,7 +327,7 @@
         case INVOKE_DIRECT:
         case INVOKE_STATIC:
         case INVOKE_INTERFACE:
-          if (file != NULL) {
+          if (file != nullptr) {
             os << opcode << " {";
             uint32_t method_idx = VRegB_35c();
             for (size_t i = 0; i < VRegA_35c(); ++i) {
@@ -328,9 +338,10 @@
             }
             os << "}, " << PrettyMethod(method_idx, *file) << " // method@" << method_idx;
             break;
-          }  // else fall-through
+          }
+          FALLTHROUGH_INTENDED;
         case INVOKE_VIRTUAL_QUICK:
-          if (file != NULL) {
+          if (file != nullptr) {
             os << opcode << " {";
             uint32_t method_idx = VRegB_35c();
             for (size_t i = 0; i < VRegA_35c(); ++i) {
@@ -341,7 +352,8 @@
             }
             os << "},  // vtable@" << method_idx;
             break;
-          }  // else fall-through
+          }
+          FALLTHROUGH_INTENDED;
         default:
           os << opcode << " {v" << arg[0] << ", v" << arg[1] << ", v" << arg[2]
                        << ", v" << arg[3] << ", v" << arg[4] << "}, thing@" << VRegB_35c();
@@ -356,19 +368,21 @@
         case INVOKE_DIRECT_RANGE:
         case INVOKE_STATIC_RANGE:
         case INVOKE_INTERFACE_RANGE:
-          if (file != NULL) {
+          if (file != nullptr) {
             uint32_t method_idx = VRegB_3rc();
             os << StringPrintf("%s, {v%d .. v%d}, ", opcode, VRegC_3rc(), (VRegC_3rc() + VRegA_3rc() - 1))
                << PrettyMethod(method_idx, *file) << " // method@" << method_idx;
             break;
-          }  // else fall-through
+          }
+          FALLTHROUGH_INTENDED;
         case INVOKE_VIRTUAL_RANGE_QUICK:
-          if (file != NULL) {
+          if (file != nullptr) {
             uint32_t method_idx = VRegB_3rc();
             os << StringPrintf("%s, {v%d .. v%d}, ", opcode, VRegC_3rc(), (VRegC_3rc() + VRegA_3rc() - 1))
                << "// vtable@" << method_idx;
             break;
-          }  // else fall-through
+          }
+          FALLTHROUGH_INTENDED;
         default:
           os << StringPrintf("%s, {v%d .. v%d}, thing@%d", opcode, VRegC_3rc(),
                              (VRegC_3rc() + VRegA_3rc() - 1), VRegB_3rc());
diff --git a/runtime/gc/allocator/rosalloc.cc b/runtime/gc/allocator/rosalloc.cc
index a3408cf..0cea89d 100644
--- a/runtime/gc/allocator/rosalloc.cc
+++ b/runtime/gc/allocator/rosalloc.cc
@@ -507,13 +507,12 @@
           --pm_idx;
           DCHECK_LT(pm_idx, capacity_ / kPageSize);
         } while (page_map_[pm_idx] != kPageMapRun);
-        // Fall-through.
+        FALLTHROUGH_INTENDED;
       case kPageMapRun:
         run = reinterpret_cast<Run*>(base_ + pm_idx * kPageSize);
         DCHECK_EQ(run->magic_num_, kMagicNum);
         break;
       case kPageMapReleased:
-        // Fall-through.
       case kPageMapEmpty:
         LOG(FATAL) << "Unreachable - page map type: " << page_map_[pm_idx];
         return 0;
@@ -2138,7 +2137,7 @@
             break;
           }
         }
-        // Fall through.
+        FALLTHROUGH_INTENDED;
       }
       case kPageMapLargeObject:      // Fall through.
       case kPageMapLargeObjectPart:  // Fall through.
diff --git a/runtime/hprof/hprof.cc b/runtime/hprof/hprof.cc
index fd67197..a2d37b3 100644
--- a/runtime/hprof/hprof.cc
+++ b/runtime/hprof/hprof.cc
@@ -719,9 +719,9 @@
   case 'D': ret = hprof_basic_double;  size = 8; break;
   case 'B': ret = hprof_basic_byte;    size = 1; break;
   case 'S': ret = hprof_basic_short;   size = 2; break;
-  default: CHECK(false);
   case 'I': ret = hprof_basic_int;     size = 4; break;
   case 'J': ret = hprof_basic_long;    size = 8; break;
+  default: LOG(FATAL) << "UNREACHABLE"; UNREACHABLE();
   }
 
   if (sizeOut != NULL) {
@@ -742,9 +742,9 @@
   case Primitive::kPrimDouble:  ret = hprof_basic_double;  size = 8; break;
   case Primitive::kPrimByte:    ret = hprof_basic_byte;    size = 1; break;
   case Primitive::kPrimShort:   ret = hprof_basic_short;   size = 2; break;
-  default: CHECK(false);
   case Primitive::kPrimInt:     ret = hprof_basic_int;     size = 4; break;
   case Primitive::kPrimLong:    ret = hprof_basic_long;    size = 8; break;
+  default: LOG(FATAL) << "UNREACHABLE"; UNREACHABLE();
   }
 
   if (sizeOut != NULL) {
diff --git a/runtime/native/java_lang_reflect_Field.cc b/runtime/native/java_lang_reflect_Field.cc
index d166be0..7f5a611 100644
--- a/runtime/native/java_lang_reflect_Field.cc
+++ b/runtime/native/java_lang_reflect_Field.cc
@@ -268,6 +268,7 @@
       break;
     }
     // Else fall through to report an error.
+    FALLTHROUGH_INTENDED;
   case Primitive::kPrimVoid:
     // Never okay.
     ThrowIllegalArgumentException(nullptr, StringPrintf("Not a primitive field: %s",