diff options
29 files changed, 202 insertions, 106 deletions
diff --git a/build/Android.common_build.mk b/build/Android.common_build.mk index 976a66e..d2d6d23 100644 --- a/build/Android.common_build.mk +++ b/build/Android.common_build.mk @@ -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 diff --git a/compiler/dex/local_value_numbering.cc b/compiler/dex/local_value_numbering.cc index e411164..eb98916 100644 --- a/compiler/dex/local_value_numbering.cc +++ b/compiler/dex/local_value_numbering.cc @@ -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: diff --git a/compiler/dex/mir_graph.cc b/compiler/dex/mir_graph.cc index 7dfdc76..f0c9858 100644 --- a/compiler/dex/mir_graph.cc +++ b/compiler/dex/mir_graph.cc @@ -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; diff --git a/compiler/dex/quick/arm/assemble_arm.cc b/compiler/dex/quick/arm/assemble_arm.cc index cf34948..4e20d76 100644 --- a/compiler/dex/quick/arm/assemble_arm.cc +++ b/compiler/dex/quick/arm/assemble_arm.cc @@ -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 diff --git a/compiler/dex/quick/arm/int_arm.cc b/compiler/dex/quick/arm/int_arm.cc index 8f1261d..018dc1c 100644 --- a/compiler/dex/quick/arm/int_arm.cc +++ b/compiler/dex/quick/arm/int_arm.cc @@ -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))); diff --git a/compiler/dex/quick/arm/utility_arm.cc b/compiler/dex/quick/arm/utility_arm.cc index bba1a8c..e833c9a 100644 --- a/compiler/dex/quick/arm/utility_arm.cc +++ b/compiler/dex/quick/arm/utility_arm.cc @@ -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) diff --git a/compiler/dex/quick/arm64/assemble_arm64.cc b/compiler/dex/quick/arm64/assemble_arm64.cc index 7c663a9..e2ff090 100644 --- a/compiler/dex/quick/arm64/assemble_arm64.cc +++ b/compiler/dex/quick/arm64/assemble_arm64.cc @@ -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; diff --git a/compiler/dex/quick/arm64/utility_arm64.cc b/compiler/dex/quick/arm64/utility_arm64.cc index 38670ff..0883694 100644 --- a/compiler/dex/quick/arm64/utility_arm64.cc +++ b/compiler/dex/quick/arm64/utility_arm64.cc @@ -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) { diff --git a/compiler/dex/quick/gen_common.cc b/compiler/dex/quick/gen_common.cc index 3a3821f..12ca065 100644 --- a/compiler/dex/quick/gen_common.cc +++ b/compiler/dex/quick/gen_common.cc @@ -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: diff --git a/compiler/dex/quick/gen_invoke.cc b/compiler/dex/quick/gen_invoke.cc index 408c73d..2bef7c5 100755 --- a/compiler/dex/quick/gen_invoke.cc +++ b/compiler/dex/quick/gen_invoke.cc @@ -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; } diff --git a/compiler/dex/quick/mips/assemble_mips.cc b/compiler/dex/quick/mips/assemble_mips.cc index c7e9190..01d1a1e 100644 --- a/compiler/dex/quick/mips/assemble_mips.cc +++ b/compiler/dex/quick/mips/assemble_mips.cc @@ -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) { diff --git a/compiler/dex/quick/mir_to_lir.cc b/compiler/dex/quick/mir_to_lir.cc index 0ac1299..4399981 100644 --- a/compiler/dex/quick/mir_to_lir.cc +++ b/compiler/dex/quick/mir_to_lir.cc @@ -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: diff --git a/compiler/dex/quick/x86/int_x86.cc b/compiler/dex/quick/x86/int_x86.cc index 5177176..07034cb 100755 --- a/compiler/dex/quick/x86/int_x86.cc +++ b/compiler/dex/quick/x86/int_x86.cc @@ -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; diff --git a/compiler/dex/quick/x86/utility_x86.cc b/compiler/dex/quick/x86/utility_x86.cc index 6898b50..8d5dabc 100644 --- a/compiler/dex/quick/x86/utility_x86.cc +++ b/compiler/dex/quick/x86/utility_x86.cc @@ -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: diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc index d555a0d..eb0158b 100644 --- a/compiler/optimizing/code_generator_arm.cc +++ b/compiler/optimizing/code_generator_arm.cc @@ -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(); } } diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc index 5f6d458..6ad627a 100644 --- a/compiler/optimizing/code_generator_x86.cc +++ b/compiler/optimizing/code_generator_x86.cc @@ -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(); } } diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc index 393eb1a..c15cca6 100644 --- a/compiler/optimizing/code_generator_x86_64.cc +++ b/compiler/optimizing/code_generator_x86_64.cc @@ -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(); } } diff --git a/disassembler/disassembler_arm.cc b/disassembler/disassembler_arm.cc index 6f8e08b..ac883fe 100644 --- a/disassembler/disassembler_arm.cc +++ b/disassembler/disassembler_arm.cc @@ -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; } diff --git a/disassembler/disassembler_x86.cc b/disassembler/disassembler_x86.cc index 195c45f..63a74c7 100644 --- a/disassembler/disassembler_x86.cc +++ b/disassembler/disassembler_x86.cc @@ -412,7 +412,7 @@ DISASSEMBLER_ENTRY(cmp, break; case 0x2E: opcode << "u"; - // FALLTHROUGH + FALLTHROUGH_INTENDED; case 0x2F: if (prefix[2] == 0x66) { opcode << "comisd"; 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 @@ static uint32_t GetInstructionSize(const uint8_t* pc) { // 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 @@ 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)) 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 @@ 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. 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 @@ static char JdwpTagToShortyChar(JDWP::JdwpTag tag) { 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 @@ 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': 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 @@ 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. } 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 @@ 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()); 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 @@ 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. 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 @@ 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) { 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 @@ 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", |