Index: boost/config/compiler/clang.hpp =================================================================== --- boost/config/compiler/clang.hpp (revision 83771) +++ boost/config/compiler/clang.hpp (working copy) @@ -38,6 +38,16 @@ # define BOOST_SYMBOL_VISIBLE __attribute__((__visibility__("default"))) #endif +// +// The BOOST_FALLTHROUGH macro can be used to annotate implicit fall-through +// between switch labels. +// +#if __cplusplus >= 201103L && defined(__has_warning) +# if __has_feature(cxx_attributes) && __has_warning("-Wimplicit-fallthrough") +# define BOOST_FALLTHROUGH [[clang::fallthrough]] +# endif +#endif + #if !__has_feature(cxx_auto_type) # define BOOST_NO_CXX11_AUTO_DECLARATIONS # define BOOST_NO_CXX11_AUTO_MULTIDECLARATIONS Index: boost/config/suffix.hpp =================================================================== --- boost/config/suffix.hpp (revision 83771) +++ boost/config/suffix.hpp (working copy) @@ -885,6 +885,15 @@ #endif // +// Helper macro BOOST_FALLTHROUGH +// Fallback definition of BOOST_FALLTHROUGH macro used to mark intended +// fall-through between case labels in a switch statement. +// +#ifndef BOOST_FALLTHROUGH +# define BOOST_FALLTHROUGH do {} while(0) +#endif + +// // constexpr workarounds // #if defined(BOOST_NO_CXX11_CONSTEXPR) Index: boost/container/detail/utilities.hpp =================================================================== --- boost/container/detail/utilities.hpp (revision 83771) +++ boost/container/detail/utilities.hpp (working copy) @@ -1055,18 +1055,21 @@ ::memcpy(short_ptr, stora_ptr, sizeof_storage); large_ptr += sizeof_storage; short_ptr += sizeof_storage; + BOOST_FALLTHROUGH; case 3: ::memcpy(stora_ptr, large_ptr, sizeof_storage); ::memcpy(large_ptr, short_ptr, sizeof_storage); ::memcpy(short_ptr, stora_ptr, sizeof_storage); large_ptr += sizeof_storage; short_ptr += sizeof_storage; + BOOST_FALLTHROUGH; case 2: ::memcpy(stora_ptr, large_ptr, sizeof_storage); ::memcpy(large_ptr, short_ptr, sizeof_storage); ::memcpy(short_ptr, stora_ptr, sizeof_storage); large_ptr += sizeof_storage; short_ptr += sizeof_storage; + BOOST_FALLTHROUGH; case 1: ::memcpy(stora_ptr, large_ptr, sizeof_storage); ::memcpy(large_ptr, short_ptr, sizeof_storage); Index: boost/date_time/time_facet.hpp =================================================================== --- boost/date_time/time_facet.hpp (revision 83771) +++ boost/date_time/time_facet.hpp (working copy) @@ -866,6 +866,7 @@ break; // %s is the same as %S%f so we drop through into %f } + BOOST_FALLTHROUGH; case 'f': { // check for decimal, check special_values if missing @@ -1135,6 +1136,7 @@ break; // %s is the same as %S%f so we drop through into %f } + BOOST_FALLTHROUGH; case 'f': { // check for decimal, check SV if missing Index: boost/format/parsing.hpp =================================================================== --- boost/format/parsing.hpp (revision 83771) +++ boost/format/parsing.hpp (working copy) @@ -267,6 +267,7 @@ switch ( wrap_narrow(fac, *start, 0) ) { case 'X': fpar->fmtstate_.flags_ |= std::ios_base::uppercase; + BOOST_FALLTHROUGH; case 'p': // pointer => set hex. case 'x': fpar->fmtstate_.flags_ &= ~std::ios_base::basefield; @@ -280,6 +281,7 @@ case 'E': fpar->fmtstate_.flags_ |= std::ios_base::uppercase; + BOOST_FALLTHROUGH; case 'e': fpar->fmtstate_.flags_ &= ~std::ios_base::floatfield; fpar->fmtstate_.flags_ |= std::ios_base::scientific; @@ -291,6 +293,7 @@ case 'f': fpar->fmtstate_.flags_ &= ~std::ios_base::floatfield; fpar->fmtstate_.flags_ |= std::ios_base::fixed; + BOOST_FALLTHROUGH; case 'u': case 'd': case 'i': Index: boost/iostreams/code_converter.hpp =================================================================== --- boost/iostreams/code_converter.hpp (revision 83771) +++ boost/iostreams/code_converter.hpp (working copy) @@ -393,7 +393,8 @@ switch (result) { case std::codecvt_base::partial: - partial = true; // Fall through. + partial = true; + BOOST_FALLTHROUGH; case std::codecvt_base::ok: total = static_cast(nint - s); break; Index: boost/locale/utf.hpp =================================================================== --- boost/locale/utf.hpp (revision 83771) +++ boost/locale/utf.hpp (working copy) @@ -222,6 +222,7 @@ if (!is_trail(tmp)) return illegal; c = (c << 6) | ( tmp & 0x3F); + BOOST_FALLTHROUGH; case 2: if(BOOST_LOCALE_UNLIKELY(p==e)) return incomplete; @@ -229,6 +230,7 @@ if (!is_trail(tmp)) return illegal; c = (c << 6) | ( tmp & 0x3F); + BOOST_FALLTHROUGH; case 1: if(BOOST_LOCALE_UNLIKELY(p==e)) return incomplete; @@ -272,8 +274,10 @@ switch(trail_size) { case 3: c = (c << 6) | ( static_cast(*p++) & 0x3F); + BOOST_FALLTHROUGH; case 2: c = (c << 6) | ( static_cast(*p++) & 0x3F); + BOOST_FALLTHROUGH; case 1: c = (c << 6) | ( static_cast(*p++) & 0x3F); } Index: boost/regex/v4/basic_regex_creator.hpp =================================================================== --- boost/regex/v4/basic_regex_creator.hpp (revision 83771) +++ boost/regex/v4/basic_regex_creator.hpp (working copy) @@ -738,14 +738,14 @@ case syntax_element_long_set_rep: // set the state_id of this repeat: static_cast(state)->state_id = m_repeater_id++; - // fall through: + BOOST_FALLTHROUGH; case syntax_element_alt: std::memset(static_cast(state)->_map, 0, sizeof(static_cast(state)->_map)); static_cast(state)->can_be_null = 0; - // fall through: + BOOST_FALLTHROUGH; case syntax_element_jump: static_cast(state)->alt.p = getaddress(static_cast(state)->alt.i, state); - // fall through again: + BOOST_FALLTHROUGH; default: if(state->next.i) state->next.p = getaddress(state->next.i, state); @@ -877,6 +877,7 @@ } } } + break; default: break; } @@ -941,7 +942,7 @@ e.raise(); } } - // fall through: + BOOST_FALLTHROUGH; default: state = state->next.p; } @@ -1153,13 +1154,14 @@ break; } m_recursion_checks[recursion_sub] = true; - // fall through, can't handle nested recursion here... + // can't handle nested recursion here... + BOOST_FALLTHROUGH; } case syntax_element_backref: // can be null, and any character can match: if(pnull) *pnull |= mask; - // fall through: + BOOST_FALLTHROUGH; case syntax_element_wild: { // can't be null, any character can match: @@ -1359,7 +1361,7 @@ state = state->next.p->next.p; break; } - // otherwise fall through: + BOOST_FALLTHROUGH; default: state = state->next.p; } @@ -1456,6 +1458,7 @@ if(state_id <= sizeof(m_bad_repeats) * CHAR_BIT) m_bad_repeats |= (one << state_id); } + break; default: break; } @@ -1537,7 +1540,7 @@ case syntax_element_long_set_rep: if(this->m_has_backrefs == 0) static_cast(state)->leading = true; - // fall through: + BOOST_FALLTHROUGH; default: return; } Index: boost/regex/v4/basic_regex_parser.hpp =================================================================== --- boost/regex/v4/basic_regex_parser.hpp (revision 83771) +++ boost/regex/v4/basic_regex_parser.hpp (working copy) @@ -369,7 +369,7 @@ while((m_position != m_end) && !is_separator(*m_position++)){} return true; } - // Otherwise fall through: + BOOST_FALLTHROUGH; default: result = parse_literal(); break; @@ -623,7 +623,7 @@ { case 'w': negate = false; - // fall through: + BOOST_FALLTHROUGH; case 'W': { basic_char_set char_set; @@ -640,7 +640,7 @@ } case 's': negate = false; - // fall through: + BOOST_FALLTHROUGH; case 'S': return add_emacs_code(negate); case 'c': @@ -672,7 +672,7 @@ { case regex_constants::escape_type_not_class: negate = true; - // fall through: + BOOST_FALLTHROUGH; case regex_constants::escape_type_class: { escape_type_class_jump: @@ -742,7 +742,7 @@ break; case regex_constants::escape_type_not_property: negate = true; - // fall through: + BOOST_FALLTHROUGH; case regex_constants::escape_type_property: { ++m_position; @@ -901,7 +901,7 @@ case regex_constants::escape_type_control_v: if(0 == (this->flags() & (regbase::main_option_type | regbase::no_perl_ex))) goto escape_type_class_jump; - // fallthrough: + BOOST_FALLTHROUGH; default: this->append_literal(unescape_character()); break; @@ -1959,7 +1959,7 @@ { case regex_constants::syntax_or: m_mark_reset = m_mark_count; - // fall through: + BOOST_FALLTHROUGH; case regex_constants::syntax_colon: // // a non-capturing mark: Index: boost/regex/v4/regex_format.hpp =================================================================== --- boost/regex/v4/regex_format.hpp (revision 83771) +++ boost/regex/v4/regex_format.hpp (working copy) @@ -283,7 +283,8 @@ format_perl(); break; } - // fall through, not a special character: + // not a special character: + BOOST_FALLTHROUGH; default: put(*m_position); ++m_position; @@ -354,7 +355,7 @@ case '{': have_brace = true; ++m_position; - // fall through.... + BOOST_FALLTHROUGH; default: // see if we have a number: { Index: boost/statechart/simple_state.hpp =================================================================== --- boost/statechart/simple_state.hpp (revision 83771) +++ boost/statechart/simple_state.hpp (working copy) @@ -527,7 +527,7 @@ { pContext_->set_outermost_unstable_state( pOutermostUnstableState ); - // fall through to next case intended + BOOST_FALLTHROUGH; } else { Index: boost/wave/util/flex_string.hpp =================================================================== --- boost/wave/util/flex_string.hpp (revision 83771) +++ boost/wave/util/flex_string.hpp (working copy) @@ -139,13 +139,13 @@ case 0: while (b != e) { - *b = c; ++b; - case 7: *b = c; ++b; - case 6: *b = c; ++b; - case 5: *b = c; ++b; - case 4: *b = c; ++b; - case 3: *b = c; ++b; - case 2: *b = c; ++b; + *b = c; ++b; BOOST_FALLTHROUGH; + case 7: *b = c; ++b; BOOST_FALLTHROUGH; + case 6: *b = c; ++b; BOOST_FALLTHROUGH; + case 5: *b = c; ++b; BOOST_FALLTHROUGH; + case 4: *b = c; ++b; BOOST_FALLTHROUGH; + case 3: *b = c; ++b; BOOST_FALLTHROUGH; + case 2: *b = c; ++b; BOOST_FALLTHROUGH; case 1: *b = c; ++b; } } Index: boost/xpressive/detail/dynamic/parse_charset.hpp =================================================================== --- boost/xpressive/detail/dynamic/parse_charset.hpp (revision 83771) +++ boost/xpressive/detail/dynamic/parse_charset.hpp (working copy) @@ -246,6 +246,7 @@ case token_charset_hyphen: case token_charset_invert: begin = iprev2; // un-get these tokens and fall through + BOOST_FALLTHROUGH; case token_literal: ch_next = *begin++; BOOST_XPR_ENSURE_(ch_prev <= ch_next, error_range, "invalid charset range"); @@ -264,7 +265,8 @@ chset.set_range(ch_prev, esc.ch_, rxtraits, icase); continue; } - case token_charset_end: // fall through + BOOST_FALLTHROUGH; + case token_charset_end: default: // not a range. begin = iprev; // backup to hyphen token chset.set_char(ch_prev, rxtraits, icase); Index: boost/xpressive/detail/dynamic/parser_traits.hpp =================================================================== --- boost/xpressive/detail/dynamic/parser_traits.hpp (revision 83771) +++ boost/xpressive/detail/dynamic/parser_traits.hpp (working copy) @@ -394,9 +394,9 @@ case BOOST_XPR_CHAR_(char_type, 'm'): this->flag_(!set, single_line); break; case BOOST_XPR_CHAR_(char_type, 's'): this->flag_(!set, not_dot_newline); break; case BOOST_XPR_CHAR_(char_type, 'x'): this->flag_(set, ignore_white_space); break; - case BOOST_XPR_CHAR_(char_type, ':'): ++begin; // fall-through + case BOOST_XPR_CHAR_(char_type, ':'): ++begin; BOOST_FALLTHROUGH; case BOOST_XPR_CHAR_(char_type, ')'): return token_no_mark; - case BOOST_XPR_CHAR_(char_type, '-'): if(false == (set = !set)) break; // else fall-through + case BOOST_XPR_CHAR_(char_type, '-'): if(false == (set = !set)) break; BOOST_FALLTHROUGH; default: BOOST_THROW_EXCEPTION(regex_error(error_paren, "unknown pattern modifier")); } while(BOOST_XPR_ENSURE_(++begin != end, error_paren, "incomplete extension")); Index: boost/xpressive/match_results.hpp =================================================================== --- boost/xpressive/match_results.hpp (revision 83771) +++ boost/xpressive/match_results.hpp (working copy) @@ -1096,11 +1096,12 @@ case BOOST_XPR_CHAR_(char_type, ':'): if(metacolon) { + BOOST_FALLTHROUGH; case BOOST_XPR_CHAR_(char_type, ')'): ++cur; return out; } - // else fall-through + BOOST_FALLTHROUGH; default: *out++ = *cur++; Index: boost/xpressive/regex_compiler.hpp =================================================================== --- boost/xpressive/regex_compiler.hpp (revision 83771) +++ boost/xpressive/regex_compiler.hpp (working copy) @@ -282,7 +282,7 @@ break; case 2: seq = detail::make_dynamic(alternate_matcher()) | seq; - // fall-through + BOOST_FALLTHROUGH; default: seq |= this->parse_sequence(tmp, end); } @@ -322,13 +322,15 @@ break; case token_negative_lookahead: - negative = true; // fall-through + negative = true; + BOOST_FALLTHROUGH; case token_positive_lookahead: lookahead = true; break; case token_negative_lookbehind: - negative = true; // fall-through + negative = true; + BOOST_FALLTHROUGH; case token_positive_lookbehind: lookbehind = true; break; @@ -342,10 +344,16 @@ { switch(this->traits_.get_token(begin, end)) { - case token_group_end: return this->parse_atom(begin, end); - case token_escape: BOOST_XPR_ENSURE_(begin != end, error_escape, "incomplete escape sequence"); - case token_literal: ++begin; - default:; + case token_group_end: + return this->parse_atom(begin, end); + case token_escape: + BOOST_XPR_ENSURE_(begin != end, error_escape, "incomplete escape sequence"); + BOOST_FALLTHROUGH; + case token_literal: + ++begin; + break; + default: + break; } } break; @@ -688,11 +696,17 @@ { switch(this->traits_.get_token(begin, end)) { - case token_quote_meta_end: return string_type(old_begin, old_end); - case token_escape: BOOST_XPR_ENSURE_(begin != end, error_escape, "incomplete escape sequence"); + case token_quote_meta_end: + return string_type(old_begin, old_end); + case token_escape: + BOOST_XPR_ENSURE_(begin != end, error_escape, "incomplete escape sequence"); + BOOST_FALLTHROUGH; case token_invalid_quantifier: - case token_literal: ++begin; - default:; + case token_literal: + ++begin; + BOOST_FALLTHROUGH; + default: + break; } } return string_type(old_begin, begin); Index: libs/config/doc/html/boost_config/boost_macro_reference.html =================================================================== --- libs/config/doc/html/boost_config/boost_macro_reference.html (revision 83771) +++ libs/config/doc/html/boost_config/boost_macro_reference.html (working copy) @@ -3,7 +3,7 @@ Boost Macro Reference - + @@ -26,7 +26,7 @@ -
+
Macros that describe C++03 defects
Macros @@ -3384,6 +3384,54 @@

+ BOOST_FALLTHROUGH +

+ + +

+ The BOOST_FALLTHROUGH macro can be used to annotate implicit fall-through + between switch labels: +

+
switch (x) {
+  case 40:
+  case 41:
+    if (truth_is_out_there) {
+      ++x;
+      BOOST_FALLTHROUGH;  // Use instead of/along with annotations in
+                          // comments.
+    } else {
+      return x;
+    }
+  case 42:
+    ...
+
+

+ As shown in the example above, the BOOST_FALLTHROUGH 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 >3.2 in C++11 mode, the BOOST_FALLTHROUGH + 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 BOOST_FALLTHROUGH macro + has no effect on diagnostics. +

+

+ In either case this macro has no effect on runtime behavior and + performance of code. +

+ + + + +

BOOST_EXPLICIT_TEMPLATE_TYPE(t) BOOST_EXPLICIT_TEMPLATE_NON_TYPE(t,v) BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(t) BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(t,v)

@@ -4923,7 +4971,7 @@
Macros for libraries with separate source code
-
+
Macros controlling shared library symbol visibility
ABI Index: libs/config/doc/macro_reference.qbk =================================================================== --- libs/config/doc/macro_reference.qbk (revision 83771) +++ libs/config/doc/macro_reference.qbk (working copy) @@ -862,6 +862,41 @@ Normally evaluates to nothing, but evaluates to return x; if the compiler requires a return, even when it can never be reached. ]] +[[`BOOST_FALLTHROUGH`][ +The BOOST_FALLTHROUGH macro can be used to annotate implicit fall-through +between switch labels: +`` + switch (x) { + case 40: + case 41: + if (truth_is_out_there) { + ++x; + BOOST_FALLTHROUGH; // Use instead of/along with annotations in + // comments. + } else { + return x; + } + case 42: + ... +`` +As shown in the example above, the BOOST_FALLTHROUGH 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 >3.2 in C++11 mode, the BOOST_FALLTHROUGH 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 BOOST_FALLTHROUGH macro has no +effect on diagnostics. + +In either case this macro has no effect on runtime behavior and performance +of code. +]] [[`BOOST_EXPLICIT_TEMPLATE_TYPE(t)` `BOOST_EXPLICIT_TEMPLATE_NON_TYPE(t,v)` `BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(t)` Index: libs/config/test/boost_no_std_wstreambuf.ipp =================================================================== --- libs/config/test/boost_no_std_wstreambuf.ipp (revision 83771) +++ libs/config/test/boost_no_std_wstreambuf.ipp (working copy) @@ -61,13 +61,13 @@ case ::std::ios_base::beg: if((off < 0) || (off > size)) return pos_type(off_type(-1)); - else - this->setg(g, g + off, g + size); + this->setg(g, g + off, g + size); + BOOST_FALLTHROUGH; case ::std::ios_base::end: if((off < 0) || (off > size)) return pos_type(off_type(-1)); - else - this->setg(g, g + size - off, g + size); + this->setg(g, g + size - off, g + size); + BOOST_FALLTHROUGH; case ::std::ios_base::cur: { int newpos = pos + off; Index: libs/graph/src/read_graphviz_new.cpp =================================================================== --- libs/graph/src/read_graphviz_new.cpp (revision 83771) +++ libs/graph/src/read_graphviz_new.cpp (working copy) @@ -230,6 +230,7 @@ case '>': return token(token::dash_greater, str); default: BOOST_ASSERT (!"Definition of punctuation_token does not match switch statement"); } + break; } default: BOOST_ASSERT (!"Definition of punctuation_token does not match switch statement"); } @@ -604,6 +605,7 @@ } default: error("Wanted identifier or left parenthesis as start of port location"); } + break; } default: break; } Index: libs/locale/src/util/gregorian.cpp =================================================================== --- libs/locale/src/util/gregorian.cpp (revision 83771) +++ libs/locale/src/util/gregorian.cpp (working copy) @@ -207,7 +207,7 @@ value += (-value / 7) * 7 + 7; // convert to local DOW value = (value - 1 - first_day_of_week_ + 14) % 7 + 1; - // fall throght + BOOST_FALLTHROUGH; case day_of_week_local: ///< Local day of week, for example in France Monday is 1, in US Sunday is 1, [1..7] normalize(); tm_updated_.tm_mday += (value - 1) - (tm_updated_.tm_wday - first_day_of_week_ + 7) % 7; @@ -666,8 +666,9 @@ normalize(); } } + break; default: - ; + break; } } @@ -726,7 +727,7 @@ case week_of_month: case week_of_year: factor = 7; - // fall + BOOST_FALLTHROUGH; case day: case day_of_year: case day_of_week: Index: libs/locale/test/test_locale.hpp =================================================================== --- libs/locale/test/test_locale.hpp (revision 83771) +++ libs/locale/test/test_locale.hpp (working copy) @@ -81,8 +81,10 @@ switch(l) { case 3: c = (c << 6) | (((unsigned char)s[pos++]) & 0x3F); + BOOST_FALLTHROUGH; case 2: c = (c << 6) | (((unsigned char)s[pos++]) & 0x3F); + BOOST_FALLTHROUGH; case 1: c = (c << 6) | (((unsigned char)s[pos++]) & 0x3F); } Index: libs/serialization/test/B.hpp =================================================================== --- libs/serialization/test/B.hpp (revision 83771) +++ libs/serialization/test/B.hpp (working copy) @@ -67,6 +67,7 @@ ar >> BOOST_SERIALIZATION_NVP(v); ar >> BOOST_SERIALIZATION_NVP(w); ar >> BOOST_SERIALIZATION_NVP(x); + break; default: break; } Index: libs/wave/samples/cpp_tokens/slex/cpp_slex_lexer.hpp =================================================================== --- libs/wave/samples/cpp_tokens/slex/cpp_slex_lexer.hpp (revision 83771) +++ libs/wave/samples/cpp_tokens/slex/cpp_slex_lexer.hpp (working copy) @@ -658,7 +658,7 @@ case T_EXTSTRINGLIT: case T_EXTRAWSTRINGLIT: id = token_id(id & ~AltTokenType); - // fall through + BOOST_FALLTHROUGH; case T_CHARLIT: case T_STRINGLIT: Index: tools/quickbook/src/actions.cpp =================================================================== --- tools/quickbook/src/actions.cpp (revision 83771) +++ tools/quickbook/src/actions.cpp (working copy) @@ -1101,6 +1101,7 @@ case '\n': case '\r': if (depth == 0) return begin; + break; default: break; }