OSDN Git Service

Enable -Wimplicit-fallthrough.
authorIan Rogers <irogers@google.com>
Fri, 10 Oct 2014 04:56:44 +0000 (21:56 -0700)
committerIan Rogers <irogers@google.com>
Fri, 10 Oct 2014 05:22:46 +0000 (22:22 -0700)
Falling through switch cases on a clang build must now annotate the fallthrough
with the FALLTHROUGH_INTENDED macro.
Bug: 17731372

Change-Id: I836451cd5f96b01d1ababdbf9eef677fe8fa8324

29 files changed:
build/Android.common_build.mk
compiler/dex/local_value_numbering.cc
compiler/dex/mir_graph.cc
compiler/dex/quick/arm/assemble_arm.cc
compiler/dex/quick/arm/int_arm.cc
compiler/dex/quick/arm/utility_arm.cc
compiler/dex/quick/arm64/assemble_arm64.cc
compiler/dex/quick/arm64/utility_arm64.cc
compiler/dex/quick/gen_common.cc
compiler/dex/quick/gen_invoke.cc
compiler/dex/quick/mips/assemble_mips.cc
compiler/dex/quick/mir_to_lir.cc
compiler/dex/quick/x86/int_x86.cc
compiler/dex/quick/x86/utility_x86.cc
compiler/optimizing/code_generator_arm.cc
compiler/optimizing/code_generator_x86.cc
compiler/optimizing/code_generator_x86_64.cc
disassembler/disassembler_arm.cc
disassembler/disassembler_x86.cc
runtime/arch/x86/fault_handler_x86.cc
runtime/base/macros.h
runtime/check_jni.cc
runtime/debugger.cc
runtime/dex_file_verifier.cc
runtime/dex_instruction-inl.h
runtime/dex_instruction.cc
runtime/gc/allocator/rosalloc.cc
runtime/hprof/hprof.cc
runtime/native/java_lang_reflect_Field.cc

index 976a66e..d2d6d23 100644 (file)
@@ -231,13 +231,20 @@ ART_TARGET_CFLAGS += -DART_BASE_ADDRESS_MIN_DELTA=$(LIBART_IMG_TARGET_MIN_BASE_A
 ART_TARGET_CFLAGS += -DART_BASE_ADDRESS_MAX_DELTA=$(LIBART_IMG_TARGET_MAX_BASE_ADDRESS_DELTA)
 
 # Colorize clang compiler warnings.
+art_clang_cflags := -fcolor-diagnostics
+
+# Warn if switch fallthroughs aren't annotated.
+art_clang_cflags += -Wimplicit-fallthrough
+
 ifeq ($(ART_HOST_CLANG),true)
-  ART_HOST_CFLAGS += -fcolor-diagnostics
+  ART_HOST_CFLAGS += $(art_clang_cflags)
 endif
 ifeq ($(ART_TARGET_CLANG),true)
-  ART_TARGET_CFLAGS += -fcolor-diagnostics
+  ART_TARGET_CFLAGS += $(art_clang_cflags)
 endif
 
+art_clang_cflags :=
+
 ART_TARGET_LDFLAGS :=
 ifeq ($(TARGET_CPU_SMP),true)
   ART_TARGET_CFLAGS += -DANDROID_SMP=1
index e411164..eb98916 100644 (file)
@@ -1460,7 +1460,7 @@ uint16_t LocalValueNumbering::GetValueNumber(MIR* mir) {
         uint16_t reg = GetOperandValue(mir->ssa_rep->uses[0]);
         HandleNullCheck(mir, reg);
       }
-      // Intentional fall-through.
+      FALLTHROUGH_INTENDED;
     case Instruction::INVOKE_STATIC:
     case Instruction::INVOKE_STATIC_RANGE:
       // Make ref args aliasing.
@@ -1583,7 +1583,7 @@ uint16_t LocalValueNumbering::GetValueNumber(MIR* mir) {
         uint16_t reg = GetOperandValue(mir->ssa_rep->uses[0]);
         HandleNullCheck(mir, reg);
       }
-      // Intentional fall-through.
+      FALLTHROUGH_INTENDED;
     case Instruction::NEG_INT:
     case Instruction::NOT_INT:
     case Instruction::NEG_FLOAT:
@@ -1610,7 +1610,6 @@ uint16_t LocalValueNumbering::GetValueNumber(MIR* mir) {
       }
       break;
 
-
     case Instruction::DOUBLE_TO_LONG:
     case Instruction::LONG_TO_DOUBLE:
     case Instruction::NEG_LONG:
@@ -1782,7 +1781,7 @@ uint16_t LocalValueNumbering::GetValueNumber(MIR* mir) {
 
     case Instruction::APUT_OBJECT:
       HandlePutObject(mir);
-      // Intentional fall-through.
+      FALLTHROUGH_INTENDED;
     case Instruction::APUT:
     case Instruction::APUT_WIDE:
     case Instruction::APUT_BYTE:
@@ -1804,7 +1803,7 @@ uint16_t LocalValueNumbering::GetValueNumber(MIR* mir) {
 
     case Instruction::IPUT_OBJECT:
       HandlePutObject(mir);
-      // Intentional fall-through.
+      FALLTHROUGH_INTENDED;
     case Instruction::IPUT:
     case Instruction::IPUT_WIDE:
     case Instruction::IPUT_BOOLEAN:
@@ -1826,7 +1825,7 @@ uint16_t LocalValueNumbering::GetValueNumber(MIR* mir) {
 
     case Instruction::SPUT_OBJECT:
       HandlePutObject(mir);
-      // Intentional fall-through.
+      FALLTHROUGH_INTENDED;
     case Instruction::SPUT:
     case Instruction::SPUT_WIDE:
     case Instruction::SPUT_BOOLEAN:
index 7dfdc76..f0c9858 100644 (file)
@@ -391,7 +391,7 @@ bool MIRGraph::IsBadMonitorExitCatch(NarrowDexOffset monitor_exit_offset,
     switch (check_insn->Opcode()) {
       case Instruction::MOVE_WIDE:
         wide = true;
-        // Intentional fall-through.
+        FALLTHROUGH_INTENDED;
       case Instruction::MOVE_OBJECT:
       case Instruction::MOVE:
         dest = check_insn->VRegA_12x();
@@ -399,7 +399,7 @@ bool MIRGraph::IsBadMonitorExitCatch(NarrowDexOffset monitor_exit_offset,
 
       case Instruction::MOVE_WIDE_FROM16:
         wide = true;
-        // Intentional fall-through.
+        FALLTHROUGH_INTENDED;
       case Instruction::MOVE_OBJECT_FROM16:
       case Instruction::MOVE_FROM16:
         dest = check_insn->VRegA_22x();
@@ -407,7 +407,7 @@ bool MIRGraph::IsBadMonitorExitCatch(NarrowDexOffset monitor_exit_offset,
 
       case Instruction::MOVE_WIDE_16:
         wide = true;
-        // Intentional fall-through.
+        FALLTHROUGH_INTENDED;
       case Instruction::MOVE_OBJECT_16:
       case Instruction::MOVE_16:
         dest = check_insn->VRegA_32x();
@@ -417,7 +417,7 @@ bool MIRGraph::IsBadMonitorExitCatch(NarrowDexOffset monitor_exit_offset,
       case Instruction::GOTO_16:
       case Instruction::GOTO_32:
         check_insn = check_insn->RelativeAt(check_insn->GetTargetOffset());
-        // Intentional fall-through.
+        FALLTHROUGH_INTENDED;
       default:
         return check_insn->Opcode() == Instruction::MONITOR_EXIT &&
             check_insn->VRegA_11x() == monitor_reg;
index cf34948..4e20d76 100644 (file)
@@ -1265,7 +1265,7 @@ void ArmMir2Lir::AssembleLIR() {
           if (lir->operands[1] != rs_r15pc.GetReg()) {
             break;
           }
-          // NOTE: intentional fallthrough.
+          FALLTHROUGH_INTENDED;
         case kFixupLoad: {
           /*
            * PC-relative loads are mostly used to load immediates
index 8f1261d..018dc1c 100644 (file)
@@ -49,12 +49,13 @@ LIR* ArmMir2Lir::OpIT(ConditionCode ccode, const char* guide) {
   int cond_bit = code & 1;
   int alt_bit = cond_bit ^ 1;
 
-  // Note: case fallthroughs intentional
   switch (strlen(guide)) {
     case 3:
       mask1 = (guide[2] == 'T') ? cond_bit : alt_bit;
+      FALLTHROUGH_INTENDED;
     case 2:
       mask2 = (guide[1] == 'T') ? cond_bit : alt_bit;
+      FALLTHROUGH_INTENDED;
     case 1:
       mask3 = (guide[0] == 'T') ? cond_bit : alt_bit;
       break;
@@ -62,6 +63,7 @@ LIR* ArmMir2Lir::OpIT(ConditionCode ccode, const char* guide) {
       break;
     default:
       LOG(FATAL) << "OAT: bad case in OpIT";
+      UNREACHABLE();
   }
   mask = (mask3 << 3) | (mask2 << 2) | (mask1 << 1) |
        (1 << (3 - strlen(guide)));
@@ -77,12 +79,13 @@ void ArmMir2Lir::UpdateIT(LIR* it, const char* new_guide) {
   int cond_bit = code & 1;
   int alt_bit = cond_bit ^ 1;
 
-  // Note: case fallthroughs intentional
   switch (strlen(new_guide)) {
     case 3:
       mask1 = (new_guide[2] == 'T') ? cond_bit : alt_bit;
+      FALLTHROUGH_INTENDED;
     case 2:
       mask2 = (new_guide[1] == 'T') ? cond_bit : alt_bit;
+      FALLTHROUGH_INTENDED;
     case 1:
       mask3 = (new_guide[0] == 'T') ? cond_bit : alt_bit;
       break;
@@ -90,6 +93,7 @@ void ArmMir2Lir::UpdateIT(LIR* it, const char* new_guide) {
       break;
     default:
       LOG(FATAL) << "OAT: bad case in UpdateIT";
+      UNREACHABLE();
   }
   mask = (mask3 << 3) | (mask2 << 2) | (mask1 << 1) |
       (1 << (3 - strlen(new_guide)));
index bba1a8c..e833c9a 100644 (file)
@@ -494,7 +494,7 @@ LIR* ArmMir2Lir::OpRegRegImm(OpKind op, RegStorage r_dest, RegStorage r_src1, in
           (value <= 1020) && ((value & 0x3) == 0)) {
         return NewLIR3(kThumbAddPcRel, r_dest.GetReg(), r_src1.GetReg(), value >> 2);
       }
-      // Note: intentional fallthrough
+      FALLTHROUGH_INTENDED;
     case kOpSub:
       if (all_low_regs && ((abs_value & 0x7) == abs_value)) {
         if (op == kOpAdd)
index 7c663a9..e2ff090 100644 (file)
@@ -705,16 +705,16 @@ uint8_t* Arm64Mir2Lir::EncodeLIRs(uint8_t* write_pos, LIR* lir) {
               switch (kind) {
                 case kFmtRegX:
                   want_64_bit = true;
-                  // Intentional fall-through.
+                  FALLTHROUGH_INTENDED;
                 case kFmtRegW:
                   want_var_size = false;
-                  // Intentional fall-through.
+                  FALLTHROUGH_INTENDED;
                 case kFmtRegR:
                   want_zero = true;
                   break;
                 case kFmtRegXOrSp:
                   want_64_bit = true;
-                  // Intentional fall-through.
+                  FALLTHROUGH_INTENDED;
                 case kFmtRegWOrSp:
                   want_var_size = false;
                   break;
@@ -722,10 +722,10 @@ uint8_t* Arm64Mir2Lir::EncodeLIRs(uint8_t* write_pos, LIR* lir) {
                   break;
                 case kFmtRegD:
                   want_64_bit = true;
-                  // Intentional fall-through.
+                  FALLTHROUGH_INTENDED;
                 case kFmtRegS:
                   want_var_size = false;
-                  // Intentional fall-through.
+                  FALLTHROUGH_INTENDED;
                 case kFmtRegF:
                   want_float = true;
                   break;
index 38670ff..0883694 100644 (file)
@@ -833,7 +833,7 @@ LIR* Arm64Mir2Lir::OpRegRegImm64(OpKind op, RegStorage r_dest, RegStorage r_src1
                      value);
     case kOpAdd:
       neg = !neg;
-      // Note: intentional fallthrough
+      FALLTHROUGH_INTENDED;
     case kOpSub:
       // Add and sub below read/write sp rather than xzr.
       if (abs_value < 0x1000) {
index 3a3821f..12ca065 100644 (file)
@@ -1785,7 +1785,7 @@ void Mir2Lir::GenArithOpIntLit(Instruction::Code opcode, RegLocation rl_dest, Re
     case Instruction::SUB_INT:
     case Instruction::SUB_INT_2ADDR:
       lit = -lit;
-      // Intended fallthrough
+      FALLTHROUGH_INTENDED;
     case Instruction::ADD_INT:
     case Instruction::ADD_INT_2ADDR:
     case Instruction::ADD_INT_LIT8:
index 408c73d..2bef7c5 100755 (executable)
@@ -552,7 +552,8 @@ static int NextSDCallInsn(CompilationUnit* cu, CallInfo* info,
       } else {
         break;
       }
-      // Intentional fallthrough for x86
+      DCHECK(cu->instruction_set == kX86 || cu->instruction_set == kX86_64);
+      FALLTHROUGH_INTENDED;
     default:
       return -1;
     }
@@ -596,7 +597,8 @@ static int NextVCallInsn(CompilationUnit* cu, CallInfo* info,
       if (CommonCallCodeLoadCodePointerIntoInvokeTgt(info, nullptr, cu, cg)) {
         break;                                    // kInvokeTgt := kArg0->entrypoint
       }
-      // Intentional fallthrough for X86
+      DCHECK(cu->instruction_set == kX86 || cu->instruction_set == kX86_64);
+      FALLTHROUGH_INTENDED;
     default:
       return -1;
   }
@@ -641,7 +643,8 @@ static int NextInterfaceCallInsn(CompilationUnit* cu, CallInfo* info, int state,
       if (CommonCallCodeLoadCodePointerIntoInvokeTgt(info, nullptr, cu, cg)) {
         break;                                    // kInvokeTgt := kArg0->entrypoint
       }
-      // Intentional fallthrough for X86
+      DCHECK(cu->instruction_set == kX86 || cu->instruction_set == kX86_64);
+      FALLTHROUGH_INTENDED;
     default:
       return -1;
   }
index c7e9190..01d1a1e 100644 (file)
@@ -465,6 +465,7 @@ void MipsMir2Lir::ConvertShortToLongBranch(LIR* lir) {
   switch (opcode) {
     case kMipsBal:
       LOG(FATAL) << "long branch and link unsupported";
+      UNREACHABLE();
     case kMipsB:
       unconditional = true;
       break;
@@ -478,6 +479,7 @@ void MipsMir2Lir::ConvertShortToLongBranch(LIR* lir) {
     case kMipsBnez: opcode = kMipsBeqz; break;
     default:
       LOG(FATAL) << "Unexpected branch kind " << opcode;
+      UNREACHABLE();
   }
   LIR* hop_target = NULL;
   if (!unconditional) {
index 0ac1299..4399981 100644 (file)
@@ -482,7 +482,7 @@ void Mir2Lir::CompileDalvikInstruction(MIR* mir, BasicBlock* bb, LIR* label_list
 
     case Instruction::RETURN_OBJECT:
       DCHECK(rl_src[0].ref);
-      // Intentional fallthrough.
+      FALLTHROUGH_INTENDED;
     case Instruction::RETURN:
       if (!kLeafOptimization || !mir_graph_->MethodIsLeaf()) {
         GenSuspendTest(opt_flags);
@@ -1031,8 +1031,7 @@ void Mir2Lir::CompileDalvikInstruction(MIR* mir, BasicBlock* bb, LIR* label_list
         GenArithImmOpLong(opcode, rl_dest, rl_src[0], rl_src[1]);
         break;
       }
-      // Note: intentional fallthrough.
-
+      FALLTHROUGH_INTENDED;
     case Instruction::MUL_LONG:
     case Instruction::DIV_LONG:
     case Instruction::REM_LONG:
index 5177176..07034cb 100755 (executable)
@@ -2930,25 +2930,25 @@ void X86Mir2Lir::GenArithOpInt(Instruction::Code opcode, RegLocation rl_dest,
       break;
     case Instruction::ADD_INT_2ADDR:
       is_two_addr = true;
-      // Fallthrough
+      FALLTHROUGH_INTENDED;
     case Instruction::ADD_INT:
       op = kOpAdd;
       break;
     case Instruction::SUB_INT_2ADDR:
       is_two_addr = true;
-      // Fallthrough
+      FALLTHROUGH_INTENDED;
     case Instruction::SUB_INT:
       op = kOpSub;
       break;
     case Instruction::MUL_INT_2ADDR:
       is_two_addr = true;
-      // Fallthrough
+      FALLTHROUGH_INTENDED;
     case Instruction::MUL_INT:
       op = kOpMul;
       break;
     case Instruction::DIV_INT_2ADDR:
       is_two_addr = true;
-      // Fallthrough
+      FALLTHROUGH_INTENDED;
     case Instruction::DIV_INT:
       op = kOpDiv;
       is_div_rem = true;
@@ -2956,46 +2956,46 @@ void X86Mir2Lir::GenArithOpInt(Instruction::Code opcode, RegLocation rl_dest,
     /* NOTE: returns in kArg1 */
     case Instruction::REM_INT_2ADDR:
       is_two_addr = true;
-      // Fallthrough
+      FALLTHROUGH_INTENDED;
     case Instruction::REM_INT:
       op = kOpRem;
       is_div_rem = true;
       break;
     case Instruction::AND_INT_2ADDR:
       is_two_addr = true;
-      // Fallthrough
+      FALLTHROUGH_INTENDED;
     case Instruction::AND_INT:
       op = kOpAnd;
       break;
     case Instruction::OR_INT_2ADDR:
       is_two_addr = true;
-      // Fallthrough
+      FALLTHROUGH_INTENDED;
     case Instruction::OR_INT:
       op = kOpOr;
       break;
     case Instruction::XOR_INT_2ADDR:
       is_two_addr = true;
-      // Fallthrough
+      FALLTHROUGH_INTENDED;
     case Instruction::XOR_INT:
       op = kOpXor;
       break;
     case Instruction::SHL_INT_2ADDR:
       is_two_addr = true;
-      // Fallthrough
+      FALLTHROUGH_INTENDED;
     case Instruction::SHL_INT:
       shift_op = true;
       op = kOpLsl;
       break;
     case Instruction::SHR_INT_2ADDR:
       is_two_addr = true;
-      // Fallthrough
+      FALLTHROUGH_INTENDED;
     case Instruction::SHR_INT:
       shift_op = true;
       op = kOpAsr;
       break;
     case Instruction::USHR_INT_2ADDR:
       is_two_addr = true;
-      // Fallthrough
+      FALLTHROUGH_INTENDED;
     case Instruction::USHR_INT:
       shift_op = true;
       op = kOpLsr;
@@ -3245,19 +3245,19 @@ void X86Mir2Lir::GenShiftOpLong(Instruction::Code opcode, RegLocation rl_dest,
   switch (opcode) {
     case Instruction::SHL_LONG_2ADDR:
       is_two_addr = true;
-      // Fallthrough
+      FALLTHROUGH_INTENDED;
     case Instruction::SHL_LONG:
       op = kOpLsl;
       break;
     case Instruction::SHR_LONG_2ADDR:
       is_two_addr = true;
-      // Fallthrough
+      FALLTHROUGH_INTENDED;
     case Instruction::SHR_LONG:
       op = kOpAsr;
       break;
     case Instruction::USHR_LONG_2ADDR:
       is_two_addr = true;
-      // Fallthrough
+      FALLTHROUGH_INTENDED;
     case Instruction::USHR_LONG:
       op = kOpLsr;
       break;
index 6898b50..8d5dabc 100644 (file)
@@ -657,7 +657,8 @@ LIR* X86Mir2Lir::LoadBaseIndexedDisp(RegStorage r_base, RegStorage r_index, int
         CHECK_EQ(is_array, false);
         CHECK_EQ(r_dest.IsFloat(), false);
         break;
-      }  // else fall-through to k32 case
+      }
+      FALLTHROUGH_INTENDED;  // else fall-through to k32 case
     case k32:
     case kSingle:
     case kReference:  // TODO: update for reference decompression on 64-bit targets.
@@ -791,7 +792,7 @@ LIR* X86Mir2Lir::StoreBaseIndexedDisp(RegStorage r_base, RegStorage r_index, int
   switch (size) {
     case k64:
       consider_non_temporal = true;
-      // Fall through!
+      FALLTHROUGH_INTENDED;
     case kDouble:
       if (r_src.IsFloat()) {
         opcode = is_array ? kX86MovsdAR : kX86MovsdMR;
@@ -810,7 +811,8 @@ LIR* X86Mir2Lir::StoreBaseIndexedDisp(RegStorage r_base, RegStorage r_index, int
         CHECK_EQ(r_src.IsFloat(), false);
         consider_non_temporal = true;
         break;
-      }  // else fall-through to k32 case
+      }
+      FALLTHROUGH_INTENDED;  // else fall-through to k32 case
     case k32:
     case kSingle:
     case kReference:
index d555a0d..eb0158b 100644 (file)
@@ -1288,9 +1288,10 @@ void InstructionCodeGeneratorARM::VisitInstanceFieldSet(HInstanceFieldSet* instr
     case Primitive::kPrimFloat:
     case Primitive::kPrimDouble:
       LOG(FATAL) << "Unimplemented register type " << field_type;
-
+      UNREACHABLE();
     case Primitive::kPrimVoid:
       LOG(FATAL) << "Unreachable type " << field_type;
+      UNREACHABLE();
   }
 }
 
@@ -1348,9 +1349,10 @@ void InstructionCodeGeneratorARM::VisitInstanceFieldGet(HInstanceFieldGet* instr
     case Primitive::kPrimFloat:
     case Primitive::kPrimDouble:
       LOG(FATAL) << "Unimplemented register type " << instruction->GetType();
-
+      UNREACHABLE();
     case Primitive::kPrimVoid:
       LOG(FATAL) << "Unreachable type " << instruction->GetType();
+      UNREACHABLE();
   }
 }
 
@@ -1478,9 +1480,10 @@ void InstructionCodeGeneratorARM::VisitArrayGet(HArrayGet* instruction) {
     case Primitive::kPrimFloat:
     case Primitive::kPrimDouble:
       LOG(FATAL) << "Unimplemented register type " << instruction->GetType();
-
+      UNREACHABLE();
     case Primitive::kPrimVoid:
       LOG(FATAL) << "Unreachable type " << instruction->GetType();
+      UNREACHABLE();
   }
 }
 
@@ -1575,9 +1578,10 @@ void InstructionCodeGeneratorARM::VisitArraySet(HArraySet* instruction) {
     case Primitive::kPrimFloat:
     case Primitive::kPrimDouble:
       LOG(FATAL) << "Unimplemented register type " << instruction->GetType();
-
+      UNREACHABLE();
     case Primitive::kPrimVoid:
       LOG(FATAL) << "Unreachable type " << instruction->GetType();
+      UNREACHABLE();
   }
 }
 
index 5f6d458..6ad627a 100644 (file)
@@ -1276,9 +1276,10 @@ void InstructionCodeGeneratorX86::VisitInstanceFieldSet(HInstanceFieldSet* instr
     case Primitive::kPrimFloat:
     case Primitive::kPrimDouble:
       LOG(FATAL) << "Unimplemented register type " << field_type;
-
+      UNREACHABLE();
     case Primitive::kPrimVoid:
       LOG(FATAL) << "Unreachable type " << field_type;
+      UNREACHABLE();
   }
 }
 
@@ -1348,9 +1349,10 @@ void InstructionCodeGeneratorX86::VisitInstanceFieldGet(HInstanceFieldGet* instr
     case Primitive::kPrimFloat:
     case Primitive::kPrimDouble:
       LOG(FATAL) << "Unimplemented register type " << instruction->GetType();
-
+      UNREACHABLE();
     case Primitive::kPrimVoid:
       LOG(FATAL) << "Unreachable type " << instruction->GetType();
+      UNREACHABLE();
   }
 }
 
@@ -1478,9 +1480,10 @@ void InstructionCodeGeneratorX86::VisitArrayGet(HArrayGet* instruction) {
     case Primitive::kPrimFloat:
     case Primitive::kPrimDouble:
       LOG(FATAL) << "Unimplemented register type " << instruction->GetType();
-
+      UNREACHABLE();
     case Primitive::kPrimVoid:
       LOG(FATAL) << "Unreachable type " << instruction->GetType();
+      UNREACHABLE();
   }
 }
 
@@ -1631,9 +1634,10 @@ void InstructionCodeGeneratorX86::VisitArraySet(HArraySet* instruction) {
     case Primitive::kPrimFloat:
     case Primitive::kPrimDouble:
       LOG(FATAL) << "Unimplemented register type " << instruction->GetType();
-
+      UNREACHABLE();
     case Primitive::kPrimVoid:
       LOG(FATAL) << "Unreachable type " << instruction->GetType();
+      UNREACHABLE();
   }
 }
 
index 393eb1a..c15cca6 100644 (file)
@@ -1158,9 +1158,10 @@ void InstructionCodeGeneratorX86_64::VisitInstanceFieldSet(HInstanceFieldSet* in
     case Primitive::kPrimFloat:
     case Primitive::kPrimDouble:
       LOG(FATAL) << "Unimplemented register type " << field_type;
-
+      UNREACHABLE();
     case Primitive::kPrimVoid:
       LOG(FATAL) << "Unreachable type " << field_type;
+      UNREACHABLE();
   }
 }
 
@@ -1212,9 +1213,10 @@ void InstructionCodeGeneratorX86_64::VisitInstanceFieldGet(HInstanceFieldGet* in
     case Primitive::kPrimFloat:
     case Primitive::kPrimDouble:
       LOG(FATAL) << "Unimplemented register type " << instruction->GetType();
-
+      UNREACHABLE();
     case Primitive::kPrimVoid:
       LOG(FATAL) << "Unreachable type " << instruction->GetType();
+      UNREACHABLE();
   }
 }
 
@@ -1339,9 +1341,10 @@ void InstructionCodeGeneratorX86_64::VisitArrayGet(HArrayGet* instruction) {
     case Primitive::kPrimFloat:
     case Primitive::kPrimDouble:
       LOG(FATAL) << "Unimplemented register type " << instruction->GetType();
-
+      UNREACHABLE();
     case Primitive::kPrimVoid:
       LOG(FATAL) << "Unreachable type " << instruction->GetType();
+      UNREACHABLE();
   }
 }
 
@@ -1465,9 +1468,10 @@ void InstructionCodeGeneratorX86_64::VisitArraySet(HArraySet* instruction) {
     case Primitive::kPrimFloat:
     case Primitive::kPrimDouble:
       LOG(FATAL) << "Unimplemented register type " << instruction->GetType();
-
+      UNREACHABLE();
     case Primitive::kPrimVoid:
       LOG(FATAL) << "Unreachable type " << instruction->GetType();
+      UNREACHABLE();
   }
 }
 
index 6f8e08b..ac883fe 100644 (file)
@@ -407,11 +407,11 @@ uint64_t AdvSIMDExpand(uint32_t op, uint32_t cmode, uint32_t imm8) {
   }
   uint64_t imm = imm8;
   switch (cmode321) {
-    case 3: imm <<= 8;  // Fall through.
-    case 2: imm <<= 8;  // Fall through.
-    case 1: imm <<= 8;  // Fall through.
+    case 3: imm <<= 8; FALLTHROUGH_INTENDED;
+    case 2: imm <<= 8; FALLTHROUGH_INTENDED;
+    case 1: imm <<= 8; FALLTHROUGH_INTENDED;
     case 0: return static_cast<int64_t>((imm << 32) | imm);
-    case 5: imm <<= 8;  // Fall through.
+    case 5: imm <<= 8; FALLTHROUGH_INTENDED;
     case 4: return static_cast<int64_t>((imm << 48) | (imm << 32) | (imm << 16) | imm);
     case 6:
       imm = ((imm + 1u) << ((cmode & 1) != 0 ? 16 : 8)) - 1u;  // Add 8 or 16 ones.
@@ -1196,7 +1196,7 @@ size_t DisassemblerArm::DumpThumb32(std::ostream& os, const uint8_t* instr_ptr)
               }
               break;
             }
-            // Else deliberate fall-through to B.
+            FALLTHROUGH_INTENDED;  // Else deliberate fall-through to B.
           case 1: case 3: {
             // B
             // |111|11|1|0000|000000|11|1 |1|1 |10000000000|
@@ -1597,6 +1597,7 @@ size_t DisassemblerArm::DumpThumb32(std::ostream& os, const uint8_t* instr_ptr)
           }
         }
       }
+      break;
     default:
       break;
   }
index 195c45f..63a74c7 100644 (file)
@@ -412,7 +412,7 @@ DISASSEMBLER_ENTRY(cmp,
         break;
       case 0x2E:
         opcode << "u";
-        // FALLTHROUGH
+        FALLTHROUGH_INTENDED;
       case 0x2F:
         if (prefix[2] == 0x66) {
           opcode << "comisd";
index 17310b6..6715fd3 100644 (file)
@@ -113,7 +113,7 @@ static uint32_t GetInstructionSize(const uint8_t* pc) {
       // Group 3
       case 0x66:
         operand_size_prefix = true;
-        // fallthrough
+        FALLTHROUGH_INTENDED;
 
       // Group 1
       case 0xf0:
index b66d528..f5a38bb 100644 (file)
@@ -181,6 +181,48 @@ char (&ArraySizeHelper(T (&array)[N]))[N];
 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))
index bfe44a2..fec1824 100644 (file)
@@ -1128,7 +1128,7 @@ class ScopedCheck {
           *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.
index 96b44bf..c53f6b2 100644 (file)
@@ -3504,6 +3504,7 @@ static char JdwpTagToShortyChar(JDWP::JdwpTag tag) {
   switch (tag) {
     default:
       LOG(FATAL) << "unknown JDWP tag: " << PrintableChar(tag);
+      UNREACHABLE();
 
     // Primitives.
     case JDWP::JT_BYTE:    return 'B';
index 0597253..a3f3de8 100644 (file)
@@ -142,7 +142,7 @@ bool DexFileVerifier::CheckShortyDescriptorMatch(char shorty_char, const char* d
         ErrorStringPrintf("Invalid use of void");
         return false;
       }
-      // Intentional fallthrough.
+      FALLTHROUGH_INTENDED;
     case 'B':
     case 'C':
     case 'D':
index ad9491f..dd65f2c 100644 (file)
@@ -460,11 +460,21 @@ inline void Instruction::GetVarArgs(uint32_t arg[5], uint16_t inst_data) const {
    * 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.
   }
index 0a71d62..7e775f4 100644 (file)
@@ -111,7 +111,7 @@ size_t Instruction::SizeInCodeUnitsComplexOpcode() const {
       if ((*insns & 0xFF) == 0) {
         return 1;  // NOP.
       } else {
-        LOG(FATAL) << "Unreachable: " << DumpString(NULL);
+        LOG(FATAL) << "Unreachable: " << DumpString(nullptr);
         return 0;
       }
   }
@@ -161,21 +161,23 @@ std::string Instruction::DumpString(const DexFile* file) const {
     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 @@ std::string Instruction::DumpString(const DexFile* file) const {
         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 @@ std::string Instruction::DumpString(const DexFile* file) const {
         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 @@ std::string Instruction::DumpString(const DexFile* file) const {
         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 @@ std::string Instruction::DumpString(const DexFile* file) const {
         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 @@ std::string Instruction::DumpString(const DexFile* file) const {
     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 @@ std::string Instruction::DumpString(const DexFile* file) const {
         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 @@ std::string Instruction::DumpString(const DexFile* file) const {
             }
             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 @@ std::string Instruction::DumpString(const DexFile* file) const {
             }
             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 @@ std::string Instruction::DumpString(const DexFile* file) const {
         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());
index a3408cf..0cea89d 100644 (file)
@@ -507,13 +507,12 @@ size_t RosAlloc::FreeInternal(Thread* self, void* ptr) {
           --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 @@ size_t RosAlloc::ReleasePages() {
             break;
           }
         }
-        // Fall through.
+        FALLTHROUGH_INTENDED;
       }
       case kPageMapLargeObject:      // Fall through.
       case kPageMapLargeObjectPart:  // Fall through.
index fd67197..a2d37b3 100644 (file)
@@ -719,9 +719,9 @@ static HprofBasicType SignatureToBasicTypeAndSize(const char* sig, size_t* sizeO
   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 @@ static HprofBasicType PrimitiveToBasicTypeAndSize(Primitive::Type prim, size_t*
   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) {
index d166be0..7f5a611 100644 (file)
@@ -268,6 +268,7 @@ static void SetFieldValue(ScopedFastNativeObjectAccess& soa, mirror::Object* o,
       break;
     }
     // Else fall through to report an error.
+    FALLTHROUGH_INTENDED;
   case Primitive::kPrimVoid:
     // Never okay.
     ThrowIllegalArgumentException(nullptr, StringPrintf("Not a primitive field: %s",