stage1: make C++ switch fallthrough an error

Make fallthrough an error when compiler supports it. This requires a new
macro that is defined with such compilers to be used as a statement, at
all fallthrough sites:

    switch (...) {
        case 0:
            ...
            ZIG_FALLTHROUGH;
        case 1:
            ...
            break;
        default:
            ...
            break;
    }

If we ever move to C++17 as minimal requirement, then the macro can be
replaced with `[[fallthrough]];` at statement sites.
master
Michael Dusan 2020-04-01 12:47:50 -04:00 committed by Andrew Kelley
parent 0f1f56bb69
commit 212e2354b8
8 changed files with 28 additions and 7 deletions

View File

@ -325,7 +325,7 @@ if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
if(MSVC)
set(EXE_CFLAGS "${EXE_CFLAGS} /w")
else()
set(EXE_CFLAGS "${EXE_CFLAGS} -Werror -Wall")
set(EXE_CFLAGS "${EXE_CFLAGS} -Werror -Wall -Werror=implicit-fallthrough")
endif()
endif()

View File

@ -363,6 +363,7 @@ bool type_is_resolved(ZigType *type_entry, ResolveStatus status) {
case ResolveStatusLLVMFull:
return type_entry->llvm_type != nullptr;
}
zig_unreachable();
case ZigTypeIdOpaque:
return status < ResolveStatusSizeKnown;
case ZigTypeIdPointer:
@ -381,6 +382,7 @@ bool type_is_resolved(ZigType *type_entry, ResolveStatus status) {
case ResolveStatusLLVMFull:
return type_entry->llvm_type != nullptr;
}
zig_unreachable();
case ZigTypeIdMetaType:
case ZigTypeIdVoid:
case ZigTypeIdBool:

View File

@ -3954,8 +3954,9 @@ static void render_async_var_decls(CodeGen *g, Scope *scope) {
if (var->did_the_decl_codegen) {
render_decl_var(g, var);
}
// fallthrough
}
ZIG_FALLTHROUGH;
case ScopeIdDecls:
case ScopeIdBlock:
case ScopeIdDefer:

View File

@ -80,7 +80,7 @@ static void jw_array_elem(JsonWriter *jw) {
zig_unreachable();
case JsonWriterStateArray:
fprintf(jw->f, ",");
// fallthrough
ZIG_FALLTHROUGH;
case JsonWriterStateArrayStart:
jw->state[jw->state_index] = JsonWriterStateArray;
jw_push_state(jw, JsonWriterStateValue);
@ -134,7 +134,7 @@ static void jw_object_field(JsonWriter *jw, const char *name) {
zig_unreachable();
case JsonWriterStateObject:
fprintf(jw->f, ",");
// fallthrough
ZIG_FALLTHROUGH;
case JsonWriterStateObjectStart:
jw->state[jw->state_index] = JsonWriterStateObject;
jw_push_state(jw, JsonWriterStateValue);

View File

@ -19949,6 +19949,7 @@ static IrInstGen *ir_analyze_call_extra(IrAnalyze *ira, IrInst* source_instr,
buf_sprintf("the specified modifier requires a comptime-known function"));
return ira->codegen->invalid_inst_gen;
}
ZIG_FALLTHROUGH;
default:
break;
}
@ -28169,6 +28170,7 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ZigValue *val)
return;
}
}
zig_unreachable();
case ZigTypeIdOptional:
zig_panic("TODO buf_write_value_bytes maybe type");
case ZigTypeIdFn:

View File

@ -624,6 +624,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
case CIntTypeCount:
zig_unreachable();
}
zig_unreachable();
default:
switch (id) {
case CIntTypeShort:
@ -642,6 +643,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
zig_unreachable();
}
}
zig_unreachable();
case OsLinux:
case OsMacOSX:
case OsFreeBSD:
@ -666,6 +668,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
case CIntTypeCount:
zig_unreachable();
}
zig_unreachable();
case OsUefi:
case OsWindows:
switch (id) {
@ -683,6 +686,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
case CIntTypeCount:
zig_unreachable();
}
zig_unreachable();
case OsIOS:
switch (id) {
case CIntTypeShort:
@ -699,6 +703,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
case CIntTypeCount:
zig_unreachable();
}
zig_unreachable();
case OsAnanas:
case OsCloudABI:
case OsKFreeBSD:

View File

@ -840,6 +840,7 @@ void tokenize(Buf *buf, Tokenization *out) {
t.state = TokenizeStateStart;
continue;
}
break;
case TokenizeStateSawSlash:
switch (c) {
case '/':
@ -1209,7 +1210,7 @@ void tokenize(Buf *buf, Tokenization *out) {
t.is_trailing_underscore = false;
t.state = TokenizeStateNumber;
}
// fall through
ZIG_FALLTHROUGH;
case TokenizeStateNumber:
{
if (c == '_') {
@ -1291,7 +1292,7 @@ void tokenize(Buf *buf, Tokenization *out) {
t.is_trailing_underscore = false;
t.state = TokenizeStateFloatFraction;
}
// fall through
ZIG_FALLTHROUGH;
case TokenizeStateFloatFraction:
{
if (c == '_') {
@ -1350,7 +1351,7 @@ void tokenize(Buf *buf, Tokenization *out) {
t.is_trailing_underscore = false;
t.state = TokenizeStateFloatExponentNumber;
}
// fall through
ZIG_FALLTHROUGH;
case TokenizeStateFloatExponentNumber:
{
if (c == '_') {

View File

@ -64,4 +64,14 @@ static inline void zig_assert(bool ok, const char *file, int line, const char *f
#undef assert
#define assert(ok) zig_assert(ok, __FILE__, __LINE__, __func__)
#if defined(_MSC_VER)
#define ZIG_FALLTHROUGH
#elif defined(__clang__)
#define ZIG_FALLTHROUGH [[clang::fallthrough]]
#elif defined(__GNUC__)
#define ZIG_FALLTHROUGH __attribute__((fallthrough))
#else
#define ZIG_FALLTHROUGH
#endif
#endif