Implement -Wimplicit-fallthrough.
Co-Authored-By: Jakub Jelinek <jakub@redhat.com> From-SVN: r240485
This commit is contained in:
parent
392fa55c79
commit
81fea426da
@ -1,3 +1,59 @@
|
||||
2016-09-26 Marek Polacek <polacek@redhat.com>
|
||||
|
||||
PR c/7652
|
||||
* Makefile.in (insn-attrtab.o-warn, insn-dfatab.o-warn,
|
||||
insn-latencytab.o-warn, insn-output.o-warn, insn-emit.o-warn): Add
|
||||
-Wno-switch-fallthrough.
|
||||
* builtins.c (expand_builtin_int_roundingfn_2): Add gcc_fallthrough.
|
||||
(expand_builtin): Likewise.
|
||||
* config/rs6000/rs6000.c (rs6000_builtin_vectorized_libmass): Likewise.
|
||||
* convert.c (convert_to_real_1): Likewise.
|
||||
(convert_to_integer_1): Likewise.
|
||||
* final.c (output_alternate_entry_point): Likewise.
|
||||
* genattrtab.c (make_canonical): Likewise.
|
||||
(write_test_expr): Likewise.
|
||||
* genpreds.c (validate_exp): Likewise.
|
||||
* gimple-ssa-strength-reduction.c
|
||||
(find_candidates_dom_walker::before_dom_children): Likewise.
|
||||
* godump.c (go_format_type): Likewise.
|
||||
* reload1.c (elimination_effects): Likewise.
|
||||
* resource.c (mark_referenced_resources): Likewise.
|
||||
(mark_set_resources): Likewise.
|
||||
* tree-ssa-loop-ivopts.c (find_deriving_biv_for_expr): Likewise.
|
||||
* varasm.c (output_addressed_constants): Likewise.
|
||||
|
||||
2016-09-26 Marek Polacek <polacek@redhat.com>
|
||||
|
||||
PR c/7652
|
||||
* common.opt (Wimplicit-fallthrough): New option.
|
||||
* doc/extend.texi: Document statement attributes and the fallthrough
|
||||
attribute.
|
||||
* doc/invoke.texi: Document -Wimplicit-fallthrough.
|
||||
* gimple.h (gimple_call_internal_p): New function.
|
||||
* gimplify.c (struct gimplify_ctx): Add in_switch_expr.
|
||||
(struct label_entry): New struct.
|
||||
(find_label_entry): New function.
|
||||
(case_label_p): New function.
|
||||
(collect_fallthrough_labels): New function.
|
||||
(last_stmt_in_scope): New function.
|
||||
(should_warn_for_implicit_fallthrough): New function.
|
||||
(warn_implicit_fallthrough_r): New function.
|
||||
(maybe_warn_implicit_fallthrough): New function.
|
||||
(expand_FALLTHROUGH_r): New function.
|
||||
(expand_FALLTHROUGH): New function.
|
||||
(gimplify_switch_expr): Call maybe_warn_implicit_fallthrough and
|
||||
expand_FALLTHROUGH for the innermost GIMPLE_SWITCH.
|
||||
(gimplify_label_expr): New function.
|
||||
(gimplify_case_label_expr): Set location.
|
||||
(gimplify_expr): Call gimplify_label_expr.
|
||||
* internal-fn.c (expand_FALLTHROUGH): New function.
|
||||
* internal-fn.def (FALLTHROUGH): New internal function.
|
||||
* langhooks.c (lang_GNU_OBJC): New function.
|
||||
* langhooks.h (lang_GNU_OBJC): Declare.
|
||||
* system.h (gcc_fallthrough): Define.
|
||||
* tree-core.h: Add FALLTHROUGH_LABEL_P comment.
|
||||
* tree.h (FALLTHROUGH_LABEL_P): Define.
|
||||
|
||||
2016-09-26 Richard Biener <rguenther@suse.de>
|
||||
|
||||
* dwarf2out.c (stripattributes): Remove unused function.
|
||||
|
@ -218,6 +218,11 @@ libgcov-merge-tool.o-warn = -Wno-error
|
||||
gimple-match.o-warn = -Wno-unused
|
||||
generic-match.o-warn = -Wno-unused
|
||||
dfp.o-warn = -Wno-strict-aliasing
|
||||
insn-attrtab.o-warn = -Wno-implicit-fallthrough
|
||||
insn-dfatab.o-warn = -Wno-implicit-fallthrough
|
||||
insn-latencytab.o-warn = -Wno-implicit-fallthrough
|
||||
insn-output.o-warn = -Wno-implicit-fallthrough
|
||||
insn-emit.o-warn = -Wno-implicit-fallthrough
|
||||
|
||||
# All warnings have to be shut off in stage1 if the compiler used then
|
||||
# isn't gcc; configure determines that. WARN_CFLAGS will be either
|
||||
|
@ -2586,7 +2586,7 @@ expand_builtin_int_roundingfn_2 (tree exp, rtx target)
|
||||
{
|
||||
CASE_FLT_FN (BUILT_IN_IRINT):
|
||||
fallback_fn = BUILT_IN_LRINT;
|
||||
/* FALLTHRU */
|
||||
gcc_fallthrough ();
|
||||
CASE_FLT_FN (BUILT_IN_LRINT):
|
||||
CASE_FLT_FN (BUILT_IN_LLRINT):
|
||||
builtin_optab = lrint_optab;
|
||||
@ -2594,7 +2594,7 @@ expand_builtin_int_roundingfn_2 (tree exp, rtx target)
|
||||
|
||||
CASE_FLT_FN (BUILT_IN_IROUND):
|
||||
fallback_fn = BUILT_IN_LROUND;
|
||||
/* FALLTHRU */
|
||||
gcc_fallthrough ();
|
||||
CASE_FLT_FN (BUILT_IN_LROUND):
|
||||
CASE_FLT_FN (BUILT_IN_LLROUND):
|
||||
builtin_optab = lround_optab;
|
||||
@ -5901,6 +5901,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode,
|
||||
CASE_FLT_FN (BUILT_IN_ILOGB):
|
||||
if (! flag_unsafe_math_optimizations)
|
||||
break;
|
||||
gcc_fallthrough ();
|
||||
CASE_FLT_FN (BUILT_IN_ISINF):
|
||||
CASE_FLT_FN (BUILT_IN_FINITE):
|
||||
case BUILT_IN_ISFINITE:
|
||||
|
@ -1,3 +1,11 @@
|
||||
2016-09-26 Marek Polacek <polacek@redhat.com>
|
||||
|
||||
PR c/7652
|
||||
* c-common.c (c_common_attribute_table): Add fallthrough attribute.
|
||||
(handle_fallthrough_attribute): New function.
|
||||
(attribute_fallthrough_p): New function.
|
||||
* c-common.h (attribute_fallthrough_p): Declare.
|
||||
|
||||
2016-09-24 Marek Polacek <polacek@redhat.com>
|
||||
|
||||
PR c/77490
|
||||
|
@ -396,6 +396,7 @@ static tree handle_designated_init_attribute (tree *, tree, tree, int, bool *);
|
||||
static tree handle_bnd_variable_size_attribute (tree *, tree, tree, int, bool *);
|
||||
static tree handle_bnd_legacy (tree *, tree, tree, int, bool *);
|
||||
static tree handle_bnd_instrument (tree *, tree, tree, int, bool *);
|
||||
static tree handle_fallthrough_attribute (tree *, tree, tree, int, bool *);
|
||||
|
||||
static void check_nonnull_arg (void *, tree, unsigned HOST_WIDE_INT);
|
||||
static bool nonnull_check_p (tree, unsigned HOST_WIDE_INT);
|
||||
@ -847,6 +848,8 @@ const struct attribute_spec c_common_attribute_table[] =
|
||||
handle_bnd_legacy, false },
|
||||
{ "bnd_instrument", 0, 0, true, false, false,
|
||||
handle_bnd_instrument, false },
|
||||
{ "fallthrough", 0, 0, false, false, false,
|
||||
handle_fallthrough_attribute, false },
|
||||
{ NULL, 0, 0, false, false, false, NULL, false }
|
||||
};
|
||||
|
||||
@ -9855,6 +9858,45 @@ handle_designated_init_attribute (tree *node, tree name, tree, int,
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
|
||||
/* Handle a "fallthrough" attribute; arguments as in struct
|
||||
attribute_spec.handler. */
|
||||
|
||||
static tree
|
||||
handle_fallthrough_attribute (tree *, tree name, tree, int,
|
||||
bool *no_add_attrs)
|
||||
{
|
||||
warning (OPT_Wattributes, "%qE attribute ignored", name);
|
||||
*no_add_attrs = true;
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Check whether ATTR is a valid attribute fallthrough. */
|
||||
|
||||
bool
|
||||
attribute_fallthrough_p (tree attr)
|
||||
{
|
||||
tree t = lookup_attribute ("fallthrough", attr);
|
||||
if (t == NULL_TREE)
|
||||
return false;
|
||||
/* This attribute shall appear at most once in each attribute-list. */
|
||||
if (lookup_attribute ("fallthrough", TREE_CHAIN (t)))
|
||||
warning (OPT_Wattributes, "%<fallthrough%> attribute specified multiple "
|
||||
"times");
|
||||
/* No attribute-argument-clause shall be present. */
|
||||
else if (TREE_VALUE (t) != NULL_TREE)
|
||||
warning (OPT_Wattributes, "%<fallthrough%> attribute specified with "
|
||||
"a parameter");
|
||||
/* Warn if other attributes are found. */
|
||||
for (t = attr; t != NULL_TREE; t = TREE_CHAIN (t))
|
||||
{
|
||||
tree name = get_attribute_name (t);
|
||||
if (!is_attribute_p ("fallthrough", name))
|
||||
warning (OPT_Wattributes, "%qE attribute ignored", name);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* Check for valid arguments being passed to a function with FNTYPE.
|
||||
There are NARGS arguments in the array ARGARRAY. LOC should be used for
|
||||
|
@ -805,6 +805,7 @@ extern void check_function_arguments_recurse (void (*)
|
||||
extern bool check_builtin_function_arguments (location_t, vec<location_t>,
|
||||
tree, int, tree *);
|
||||
extern void check_function_format (tree, int, tree *);
|
||||
extern bool attribute_fallthrough_p (tree);
|
||||
extern tree handle_unused_attribute (tree *, tree, tree, int, bool *);
|
||||
extern tree handle_format_attribute (tree *, tree, tree, int, bool *);
|
||||
extern tree handle_format_arg_attribute (tree *, tree, tree, int, bool *);
|
||||
|
@ -1,3 +1,19 @@
|
||||
2016-09-26 Marek Polacek <polacek@redhat.com>
|
||||
|
||||
PR c/7652
|
||||
* c-decl.c (pop_scope): Add gcc_fallthrough.
|
||||
|
||||
2016-09-26 Marek Polacek <polacek@redhat.com>
|
||||
|
||||
PR c/7652
|
||||
* c-parser.c (struct c_token): Add flags field.
|
||||
(c_lex_one_token): Pass it to c_lex_with_flags.
|
||||
(c_parser_declaration_or_fndef): Turn __attribute__((fallthrough));
|
||||
into IFN_FALLTHROUGH.
|
||||
(c_parser_label): Set FALLTHROUGH_LABEL_P on labels. Handle
|
||||
attribute fallthrough after a case label or default label.
|
||||
(c_parser_statement_after_labels): Handle RID_ATTRIBUTE.
|
||||
|
||||
2016-09-24 Marek Polacek <polacek@redhat.com>
|
||||
|
||||
PR c/77490
|
||||
|
@ -1328,7 +1328,7 @@ pop_scope (void)
|
||||
set_type_context (TREE_TYPE (p), context);
|
||||
}
|
||||
|
||||
/* Fall through. */
|
||||
gcc_fallthrough ();
|
||||
/* Parameters go in DECL_ARGUMENTS, not BLOCK_VARS, and have
|
||||
already been put there by store_parm_decls. Unused-
|
||||
parameter warnings are handled by function.c.
|
||||
|
@ -193,6 +193,8 @@ struct GTY (()) c_token {
|
||||
location_t location;
|
||||
/* The value associated with this token, if any. */
|
||||
tree value;
|
||||
/* Token flags. */
|
||||
unsigned char flags;
|
||||
|
||||
source_range get_range () const
|
||||
{
|
||||
@ -270,7 +272,8 @@ c_lex_one_token (c_parser *parser, c_token *token)
|
||||
{
|
||||
timevar_push (TV_LEX);
|
||||
|
||||
token->type = c_lex_with_flags (&token->value, &token->location, NULL,
|
||||
token->type = c_lex_with_flags (&token->value, &token->location,
|
||||
&token->flags,
|
||||
(parser->lex_untranslated_string
|
||||
? C_LEX_STRING_NO_TRANSLATE : 0));
|
||||
token->id_kind = C_ID_NONE;
|
||||
@ -1288,7 +1291,8 @@ static void c_parser_external_declaration (c_parser *);
|
||||
static void c_parser_asm_definition (c_parser *);
|
||||
static void c_parser_declaration_or_fndef (c_parser *, bool, bool, bool,
|
||||
bool, bool, tree *, vec<c_token>,
|
||||
struct oacc_routine_data * = NULL);
|
||||
struct oacc_routine_data * = NULL,
|
||||
bool * = NULL);
|
||||
static void c_parser_static_assert_declaration_no_semi (c_parser *);
|
||||
static void c_parser_static_assert_declaration (c_parser *);
|
||||
static void c_parser_declspecs (c_parser *, struct c_declspecs *, bool, bool,
|
||||
@ -1591,6 +1595,8 @@ static void c_finish_oacc_routine (struct oacc_routine_data *, tree, bool);
|
||||
attributes; otherwise they may not.
|
||||
OBJC_FOREACH_OBJECT_DECLARATION can be used to get back the parsed
|
||||
declaration when parsing an Objective-C foreach statement.
|
||||
FALLTHRU_ATTR_P is used to signal whether this function parsed
|
||||
"__attribute__((fallthrough));".
|
||||
|
||||
declaration:
|
||||
declaration-specifiers init-declarator-list[opt] ;
|
||||
@ -1618,6 +1624,8 @@ static void c_finish_oacc_routine (struct oacc_routine_data *, tree, bool);
|
||||
declaration-specifiers declarator declaration-list[opt]
|
||||
compound-statement
|
||||
|
||||
attribute ;
|
||||
|
||||
Objective-C:
|
||||
attributes objc-class-definition
|
||||
attributes objc-category-definition
|
||||
@ -1652,7 +1660,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
|
||||
bool nested, bool start_attr_ok,
|
||||
tree *objc_foreach_object_declaration,
|
||||
vec<c_token> omp_declare_simd_clauses,
|
||||
struct oacc_routine_data *oacc_routine_data)
|
||||
struct oacc_routine_data *oacc_routine_data,
|
||||
bool *fallthru_attr_p)
|
||||
{
|
||||
struct c_declspecs *specs;
|
||||
tree prefix_attrs;
|
||||
@ -1749,6 +1758,15 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
|
||||
{
|
||||
if (auto_type_p)
|
||||
error_at (here, "%<__auto_type%> in empty declaration");
|
||||
else if (specs->typespec_kind == ctsk_none
|
||||
&& attribute_fallthrough_p (specs->attrs))
|
||||
{
|
||||
if (fallthru_attr_p != NULL)
|
||||
*fallthru_attr_p = true;
|
||||
tree fn = build_call_expr_internal_loc (here, IFN_FALLTHROUGH,
|
||||
void_type_node, 0);
|
||||
add_stmt (fn);
|
||||
}
|
||||
else if (empty_ok)
|
||||
shadow_tag (specs);
|
||||
else
|
||||
@ -1851,6 +1869,9 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (attribute_fallthrough_p (specs->attrs))
|
||||
warning_at (here, OPT_Wattributes,
|
||||
"%<fallthrough%> attribute not followed by %<;%>");
|
||||
|
||||
pending_xref_error ();
|
||||
prefix_attrs = specs->attrs;
|
||||
@ -4841,12 +4862,14 @@ c_parser_compound_statement_nostart (c_parser *parser)
|
||||
{
|
||||
last_label = false;
|
||||
mark_valid_location_for_stdc_pragma (false);
|
||||
bool fallthru_attr_p = false;
|
||||
c_parser_declaration_or_fndef (parser, true, true, true, true,
|
||||
true, NULL, vNULL);
|
||||
if (last_stmt)
|
||||
true, NULL, vNULL, NULL,
|
||||
&fallthru_attr_p);
|
||||
if (last_stmt && !fallthru_attr_p)
|
||||
pedwarn_c90 (loc, OPT_Wdeclaration_after_statement,
|
||||
"ISO C90 forbids mixed declarations and code");
|
||||
last_stmt = false;
|
||||
last_stmt = fallthru_attr_p;
|
||||
}
|
||||
else if (!last_label
|
||||
&& c_parser_next_token_is_keyword (parser, RID_EXTENSION))
|
||||
@ -4963,6 +4986,11 @@ c_parser_label (c_parser *parser)
|
||||
{
|
||||
location_t loc1 = c_parser_peek_token (parser)->location;
|
||||
tree label = NULL_TREE;
|
||||
|
||||
/* Remember whether this case or a user-defined label is allowed to fall
|
||||
through to. */
|
||||
bool fallthrough_p = c_parser_peek_token (parser)->flags & PREV_FALLTHROUGH;
|
||||
|
||||
if (c_parser_next_token_is_keyword (parser, RID_CASE))
|
||||
{
|
||||
tree exp1, exp2;
|
||||
@ -5009,6 +5037,33 @@ c_parser_label (c_parser *parser)
|
||||
}
|
||||
if (label)
|
||||
{
|
||||
if (TREE_CODE (label) == LABEL_EXPR)
|
||||
FALLTHROUGH_LABEL_P (LABEL_EXPR_LABEL (label)) = fallthrough_p;
|
||||
else
|
||||
FALLTHROUGH_LABEL_P (CASE_LABEL (label)) = fallthrough_p;
|
||||
|
||||
/* Allow '__attribute__((fallthrough));'. */
|
||||
if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
|
||||
{
|
||||
location_t loc = c_parser_peek_token (parser)->location;
|
||||
tree attrs = c_parser_attributes (parser);
|
||||
if (attribute_fallthrough_p (attrs))
|
||||
{
|
||||
if (c_parser_next_token_is (parser, CPP_SEMICOLON))
|
||||
{
|
||||
tree fn = build_call_expr_internal_loc (loc,
|
||||
IFN_FALLTHROUGH,
|
||||
void_type_node, 0);
|
||||
add_stmt (fn);
|
||||
}
|
||||
else
|
||||
warning_at (loc, OPT_Wattributes, "%<fallthrough%> attribute "
|
||||
"not followed by %<;%>");
|
||||
}
|
||||
else if (attrs != NULL_TREE)
|
||||
warning_at (loc, OPT_Wattributes, "only attribute %<fallthrough%>"
|
||||
" can be applied to a null statement");
|
||||
}
|
||||
if (c_parser_next_tokens_start_declaration (parser))
|
||||
{
|
||||
error_at (c_parser_peek_token (parser)->location,
|
||||
@ -5062,6 +5117,9 @@ c_parser_label (c_parser *parser)
|
||||
jump-statement:
|
||||
goto * expression ;
|
||||
|
||||
expression-statement:
|
||||
attributes ;
|
||||
|
||||
Objective-C:
|
||||
|
||||
statement:
|
||||
@ -5323,6 +5381,31 @@ c_parser_statement_after_labels (c_parser *parser, bool *if_p,
|
||||
gcc_assert (c_dialect_objc ());
|
||||
c_parser_objc_synchronized_statement (parser);
|
||||
break;
|
||||
case RID_ATTRIBUTE:
|
||||
{
|
||||
/* Allow '__attribute__((fallthrough));'. */
|
||||
tree attrs = c_parser_attributes (parser);
|
||||
if (attribute_fallthrough_p (attrs))
|
||||
{
|
||||
if (c_parser_next_token_is (parser, CPP_SEMICOLON))
|
||||
{
|
||||
tree fn = build_call_expr_internal_loc (loc,
|
||||
IFN_FALLTHROUGH,
|
||||
void_type_node, 0);
|
||||
add_stmt (fn);
|
||||
/* Eat the ';'. */
|
||||
c_parser_consume_token (parser);
|
||||
}
|
||||
else
|
||||
warning_at (loc, OPT_Wattributes,
|
||||
"%<fallthrough%> attribute not followed "
|
||||
"by %<;%>");
|
||||
}
|
||||
else if (attrs != NULL_TREE)
|
||||
warning_at (loc, OPT_Wattributes, "only attribute %<fallthrough%>"
|
||||
" can be applied to a null statement");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
goto expr_stmt;
|
||||
}
|
||||
|
@ -601,6 +601,10 @@ Whsa
|
||||
Common Var(warn_hsa) Init(1) Warning
|
||||
Warn when a function cannot be expanded to HSAIL.
|
||||
|
||||
Wimplicit-fallthrough
|
||||
Common Var(warn_implicit_fallthrough) Warning EnabledBy(Wextra)
|
||||
Warn when a switch case falls through.
|
||||
|
||||
Winline
|
||||
Common Var(warn_inline) Warning
|
||||
Warn when an inlined function cannot be inlined.
|
||||
|
@ -5489,7 +5489,7 @@ rs6000_builtin_vectorized_libmass (combined_fn fn, tree type_out,
|
||||
CASE_CFN_HYPOT:
|
||||
CASE_CFN_POW:
|
||||
n_args = 2;
|
||||
/* fall through */
|
||||
gcc_fallthrough ();
|
||||
|
||||
CASE_CFN_ACOS:
|
||||
CASE_CFN_ACOSH:
|
||||
|
@ -164,6 +164,7 @@ convert_to_real_1 (tree type, tree expr, bool fold_p)
|
||||
-fmath-errno. */
|
||||
if (flag_errno_math)
|
||||
break;
|
||||
gcc_fallthrough ();
|
||||
CASE_MATHFN (ACOS)
|
||||
CASE_MATHFN (ACOSH)
|
||||
CASE_MATHFN (ASIN)
|
||||
@ -184,6 +185,7 @@ convert_to_real_1 (tree type, tree expr, bool fold_p)
|
||||
/* The above functions are not safe to do this conversion. */
|
||||
if (!flag_unsafe_math_optimizations)
|
||||
break;
|
||||
gcc_fallthrough ();
|
||||
CASE_MATHFN (SQRT)
|
||||
CASE_MATHFN (FABS)
|
||||
CASE_MATHFN (LOGB)
|
||||
@ -516,7 +518,7 @@ convert_to_integer_1 (tree type, tree expr, bool dofold)
|
||||
/* Only convert nearbyint* if we can ignore math exceptions. */
|
||||
if (flag_trapping_math)
|
||||
break;
|
||||
/* ... Fall through ... */
|
||||
gcc_fallthrough ();
|
||||
CASE_FLT_FN (BUILT_IN_RINT):
|
||||
/* Only convert in ISO C99 mode and with -fno-math-errno. */
|
||||
if (!targetm.libc_has_function (function_c99_misc) || flag_errno_math)
|
||||
|
@ -1,3 +1,33 @@
|
||||
2016-09-26 Marek Polacek <polacek@redhat.com>
|
||||
|
||||
PR c/7652
|
||||
* parser.c (cp_parser_storage_class_specifier_opt): Add
|
||||
gcc_fallthrough.
|
||||
(cp_parser_skip_to_end_of_template_parameter_list): Likewise.
|
||||
(cp_parser_cache_defarg): Likewise.
|
||||
(cp_parser_omp_for_cond): Likewise.
|
||||
* semantics.c (finish_decltype_type): Likewise.
|
||||
* typeck.c (structural_comptypes): Likewise.
|
||||
(cp_build_binary_op): Likewise.
|
||||
(cp_build_modify_expr): Likewise.
|
||||
|
||||
2016-09-26 Marek Polacek <polacek@redhat.com>
|
||||
|
||||
PR c/7652
|
||||
* constexpr.c (cxx_eval_internal_function): Handle IFN_FALLTHROUGH.
|
||||
(potential_constant_expression_1): Likewise.
|
||||
* constraint.cc (function_concept_check_p): Check fn for null.
|
||||
* parser.c (cp_parser_expression_statement): Handle attribute
|
||||
fallthrough.
|
||||
(cp_parser_statement): Likewise.
|
||||
(cp_parser_label_for_labeled_statement): Set FALLTHROUGH_LABEL_P on
|
||||
labels.
|
||||
(cp_parser_std_attribute): Handle fallthrough attribute.
|
||||
(cp_parser_check_std_attribute): Add %< %> quotes.
|
||||
* pt.c (tsubst_copy_and_build): Handle internal functions.
|
||||
(instantiation_dependent_scope_ref_p): Return if the expression is
|
||||
null.
|
||||
|
||||
2016-09-24 Marek Polacek <polacek@redhat.com>
|
||||
|
||||
PR c/77490
|
||||
|
@ -1303,6 +1303,7 @@ cxx_eval_internal_function (const constexpr_ctx *ctx, tree t,
|
||||
case IFN_UBSAN_NULL:
|
||||
case IFN_UBSAN_BOUNDS:
|
||||
case IFN_UBSAN_VPTR:
|
||||
case IFN_FALLTHROUGH:
|
||||
return void_node;
|
||||
|
||||
case IFN_ADD_OVERFLOW:
|
||||
@ -4826,6 +4827,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict,
|
||||
case IFN_UBSAN_NULL:
|
||||
case IFN_UBSAN_BOUNDS:
|
||||
case IFN_UBSAN_VPTR:
|
||||
case IFN_FALLTHROUGH:
|
||||
return true;
|
||||
|
||||
case IFN_ADD_OVERFLOW:
|
||||
|
@ -116,7 +116,8 @@ function_concept_check_p (tree t)
|
||||
{
|
||||
gcc_assert (TREE_CODE (t) == CALL_EXPR);
|
||||
tree fn = CALL_EXPR_FN (t);
|
||||
if (TREE_CODE (fn) == TEMPLATE_ID_EXPR
|
||||
if (fn != NULL_TREE
|
||||
&& TREE_CODE (fn) == TEMPLATE_ID_EXPR
|
||||
&& TREE_CODE (TREE_OPERAND (fn, 0)) == OVERLOAD)
|
||||
{
|
||||
tree f1 = get_first_fn (fn);
|
||||
|
@ -10585,14 +10585,31 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
|
||||
}
|
||||
/* Look for an expression-statement instead. */
|
||||
statement = cp_parser_expression_statement (parser, in_statement_expr);
|
||||
|
||||
/* Handle [[fallthrough]];. */
|
||||
if (attribute_fallthrough_p (std_attrs))
|
||||
{
|
||||
/* The next token after the fallthrough attribute is ';'. */
|
||||
if (statement == NULL_TREE)
|
||||
{
|
||||
/* Turn [[fallthrough]]; into FALLTHROUGH ();. */
|
||||
statement = build_call_expr_internal_loc (statement_location,
|
||||
IFN_FALLTHROUGH,
|
||||
void_type_node, 0);
|
||||
finish_expr_stmt (statement);
|
||||
}
|
||||
else
|
||||
warning_at (statement_location, OPT_Wattributes,
|
||||
"%<fallthrough%> attribute not followed by %<;%>");
|
||||
std_attrs = NULL_TREE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the line number for the statement. */
|
||||
if (statement && STATEMENT_CODE_P (TREE_CODE (statement)))
|
||||
SET_EXPR_LOCATION (statement, statement_location);
|
||||
|
||||
/* Note that for now, we don't do anything with c++11 statements
|
||||
parsed at this level. */
|
||||
/* Allow "[[fallthrough]];", but warn otherwise. */
|
||||
if (std_attrs != NULL_TREE)
|
||||
warning_at (attrs_location,
|
||||
OPT_Wattributes,
|
||||
@ -10628,6 +10645,10 @@ cp_parser_label_for_labeled_statement (cp_parser* parser, tree attributes)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Remember whether this case or a user-defined label is allowed to fall
|
||||
through to. */
|
||||
bool fallthrough_p = token->flags & PREV_FALLTHROUGH;
|
||||
|
||||
parser->colon_corrects_to_scope_p = false;
|
||||
switch (token->keyword)
|
||||
{
|
||||
@ -10659,7 +10680,11 @@ cp_parser_label_for_labeled_statement (cp_parser* parser, tree attributes)
|
||||
expr_hi = NULL_TREE;
|
||||
|
||||
if (parser->in_switch_statement_p)
|
||||
finish_case_label (token->location, expr, expr_hi);
|
||||
{
|
||||
tree l = finish_case_label (token->location, expr, expr_hi);
|
||||
if (l && TREE_CODE (l) == CASE_LABEL_EXPR)
|
||||
FALLTHROUGH_LABEL_P (CASE_LABEL (l)) = fallthrough_p;
|
||||
}
|
||||
else
|
||||
error_at (token->location,
|
||||
"case label %qE not within a switch statement",
|
||||
@ -10672,7 +10697,11 @@ cp_parser_label_for_labeled_statement (cp_parser* parser, tree attributes)
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
|
||||
if (parser->in_switch_statement_p)
|
||||
finish_case_label (token->location, NULL_TREE, NULL_TREE);
|
||||
{
|
||||
tree l = finish_case_label (token->location, NULL_TREE, NULL_TREE);
|
||||
if (l && TREE_CODE (l) == CASE_LABEL_EXPR)
|
||||
FALLTHROUGH_LABEL_P (CASE_LABEL (l)) = fallthrough_p;
|
||||
}
|
||||
else
|
||||
error_at (token->location, "case label not within a switch statement");
|
||||
break;
|
||||
@ -10680,6 +10709,8 @@ cp_parser_label_for_labeled_statement (cp_parser* parser, tree attributes)
|
||||
default:
|
||||
/* Anything else must be an ordinary label. */
|
||||
label = finish_label_stmt (cp_parser_identifier (parser));
|
||||
if (label && TREE_CODE (label) == LABEL_DECL)
|
||||
FALLTHROUGH_LABEL_P (label) = fallthrough_p;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -10728,6 +10759,10 @@ cp_parser_expression_statement (cp_parser* parser, tree in_statement_expr)
|
||||
{
|
||||
tree statement = NULL_TREE;
|
||||
cp_token *token = cp_lexer_peek_token (parser->lexer);
|
||||
location_t loc = token->location;
|
||||
|
||||
/* There might be attribute fallthrough. */
|
||||
tree attr = cp_parser_gnu_attributes_opt (parser);
|
||||
|
||||
/* If the next token is a ';', then there is no expression
|
||||
statement. */
|
||||
@ -10742,6 +10777,25 @@ cp_parser_expression_statement (cp_parser* parser, tree in_statement_expr)
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle [[fallthrough]];. */
|
||||
if (attribute_fallthrough_p (attr))
|
||||
{
|
||||
/* The next token after the fallthrough attribute is ';'. */
|
||||
if (statement == NULL_TREE)
|
||||
/* Turn [[fallthrough]]; into FALLTHROUGH ();. */
|
||||
statement = build_call_expr_internal_loc (loc, IFN_FALLTHROUGH,
|
||||
void_type_node, 0);
|
||||
else
|
||||
warning_at (loc, OPT_Wattributes,
|
||||
"%<fallthrough%> attribute not followed by %<;%>");
|
||||
attr = NULL_TREE;
|
||||
}
|
||||
|
||||
/* Allow "[[fallthrough]];", but warn otherwise. */
|
||||
if (attr != NULL_TREE)
|
||||
warning_at (loc, OPT_Wattributes,
|
||||
"attributes at the beginning of statement are ignored");
|
||||
|
||||
/* Give a helpful message for "A<T>::type t;" and the like. */
|
||||
if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)
|
||||
&& !cp_parser_uncommitted_to_tentative_parse_p (parser))
|
||||
@ -12980,6 +13034,7 @@ cp_parser_storage_class_specifier_opt (cp_parser* parser)
|
||||
if (cxx_dialect != cxx98)
|
||||
return NULL_TREE;
|
||||
/* Fall through for C++98. */
|
||||
gcc_fallthrough ();
|
||||
|
||||
case RID_REGISTER:
|
||||
case RID_STATIC:
|
||||
@ -24116,7 +24171,7 @@ cp_parser_std_attribute (cp_parser *parser, tree attr_ns)
|
||||
if (is_attribute_p ("noreturn", attr_id))
|
||||
TREE_PURPOSE (TREE_PURPOSE (attribute)) = get_identifier ("gnu");
|
||||
/* C++14 deprecated attribute is equivalent to GNU's. */
|
||||
else if (cxx_dialect >= cxx11 && is_attribute_p ("deprecated", attr_id))
|
||||
else if (is_attribute_p ("deprecated", attr_id))
|
||||
{
|
||||
if (cxx_dialect == cxx11)
|
||||
pedwarn (token->location, OPT_Wpedantic,
|
||||
@ -24124,6 +24179,15 @@ cp_parser_std_attribute (cp_parser *parser, tree attr_ns)
|
||||
" use %<gnu::deprecated%>");
|
||||
TREE_PURPOSE (TREE_PURPOSE (attribute)) = get_identifier ("gnu");
|
||||
}
|
||||
/* C++17 fallthrough attribute is equivalent to GNU's. */
|
||||
else if (is_attribute_p ("fallthrough", attr_id))
|
||||
{
|
||||
if (cxx_dialect < cxx1z)
|
||||
pedwarn (token->location, OPT_Wpedantic,
|
||||
"%<fallthrough%> is a C++17 feature;"
|
||||
" use %<gnu::fallthrough%>");
|
||||
TREE_PURPOSE (TREE_PURPOSE (attribute)) = get_identifier ("gnu");
|
||||
}
|
||||
/* Transactional Memory TS optimize_for_synchronized attribute is
|
||||
equivalent to GNU transaction_callable. */
|
||||
else if (is_attribute_p ("optimize_for_synchronized", attr_id))
|
||||
@ -24182,11 +24246,11 @@ cp_parser_check_std_attribute (tree attributes, tree attribute)
|
||||
tree name = get_attribute_name (attribute);
|
||||
if (is_attribute_p ("noreturn", name)
|
||||
&& lookup_attribute ("noreturn", attributes))
|
||||
error ("attribute noreturn can appear at most once "
|
||||
error ("attribute %<noreturn%> can appear at most once "
|
||||
"in an attribute-list");
|
||||
else if (is_attribute_p ("deprecated", name)
|
||||
&& lookup_attribute ("deprecated", attributes))
|
||||
error ("attribute deprecated can appear at most once "
|
||||
error ("attribute %<deprecated%> can appear at most once "
|
||||
"in an attribute-list");
|
||||
}
|
||||
}
|
||||
@ -27303,6 +27367,7 @@ cp_parser_skip_to_end_of_template_parameter_list (cp_parser* parser)
|
||||
}
|
||||
/* Fall through for C++0x, so we handle the second `>' in
|
||||
the `>>'. */
|
||||
gcc_fallthrough ();
|
||||
|
||||
case CPP_GREATER:
|
||||
if (!nesting_depth && level-- == 0)
|
||||
@ -27760,6 +27825,7 @@ cp_parser_cache_defarg (cp_parser *parser, bool nsdmi)
|
||||
/* Fall through for C++0x, which treats the `>>'
|
||||
operator like two `>' tokens in certain
|
||||
cases. */
|
||||
gcc_fallthrough ();
|
||||
|
||||
case CPP_GREATER:
|
||||
if (depth == 0)
|
||||
@ -33402,6 +33468,7 @@ cp_parser_omp_for_cond (cp_parser *parser, tree decl, enum tree_code code)
|
||||
if (code == CILK_SIMD || code == CILK_FOR)
|
||||
break;
|
||||
/* Fall through: OpenMP disallows NE_EXPR. */
|
||||
gcc_fallthrough ();
|
||||
default:
|
||||
return error_mark_node;
|
||||
}
|
||||
|
11
gcc/cp/pt.c
11
gcc/cp/pt.c
@ -16556,6 +16556,15 @@ tsubst_copy_and_build (tree t,
|
||||
tree ret;
|
||||
|
||||
function = CALL_EXPR_FN (t);
|
||||
if (function == NULL_TREE)
|
||||
{
|
||||
/* If you hit this assert, it means that you're trying to tsubst
|
||||
an internal function with arguments. This isn't yet supported,
|
||||
so you need to build another internal call with the tsubsted
|
||||
arguments after the arguments have been tsubsted down below. */
|
||||
gcc_assert (call_expr_nargs (t) == 0);
|
||||
RETURN (t);
|
||||
}
|
||||
/* When we parsed the expression, we determined whether or
|
||||
not Koenig lookup should be performed. */
|
||||
koenig_p = KOENIG_LOOKUP_P (t);
|
||||
@ -22787,7 +22796,7 @@ instantiation_dependent_scope_ref_p (tree t)
|
||||
bool
|
||||
value_dependent_expression_p (tree expression)
|
||||
{
|
||||
if (!processing_template_decl)
|
||||
if (!processing_template_decl || expression == NULL_TREE)
|
||||
return false;
|
||||
|
||||
/* A name declared with a dependent type. */
|
||||
|
@ -8894,6 +8894,7 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p,
|
||||
break;
|
||||
}
|
||||
/* Fall through for fields that aren't bitfields. */
|
||||
gcc_fallthrough ();
|
||||
|
||||
case FUNCTION_DECL:
|
||||
case VAR_DECL:
|
||||
|
@ -1306,6 +1306,7 @@ structural_comptypes (tree t1, tree t2, int strict)
|
||||
if (TYPE_REF_IS_RVALUE (t1) != TYPE_REF_IS_RVALUE (t2))
|
||||
return false;
|
||||
/* fall through to checks for pointer types */
|
||||
gcc_fallthrough ();
|
||||
|
||||
case POINTER_TYPE:
|
||||
if (TYPE_MODE (t1) != TYPE_MODE (t2)
|
||||
@ -4265,6 +4266,7 @@ cp_build_binary_op (location_t location,
|
||||
}
|
||||
/* The pointer - int case is just like pointer + int; fall
|
||||
through. */
|
||||
gcc_fallthrough ();
|
||||
case PLUS_EXPR:
|
||||
if ((code0 == POINTER_TYPE || code1 == POINTER_TYPE)
|
||||
&& (code0 == INTEGER_TYPE || code1 == INTEGER_TYPE))
|
||||
@ -7554,7 +7556,7 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
|
||||
TREE_OPERAND (lhs, 1)),
|
||||
TREE_OPERAND (lhs, 0),
|
||||
TREE_OPERAND (lhs, 1));
|
||||
/* Fall through. */
|
||||
gcc_fallthrough ();
|
||||
|
||||
/* Handle (a ? b : c) used as an "lvalue". */
|
||||
case COND_EXPR:
|
||||
|
@ -60,6 +60,7 @@ extensions, accepted by GCC in C90 mode and in C++.
|
||||
* Type Attributes:: Specifying attributes of types.
|
||||
* Label Attributes:: Specifying attributes on labels.
|
||||
* Enumerator Attributes:: Specifying attributes on enumerators.
|
||||
* Statement Attributes:: Specifying attributes on statements.
|
||||
* Attribute Syntax:: Formal syntax for attributes.
|
||||
* Function Prototypes:: Prototype declarations and old-style definitions.
|
||||
* C++ Comments:: C++ comments are recognized.
|
||||
@ -2261,6 +2262,7 @@ GCC also supports attributes on
|
||||
variable declarations (@pxref{Variable Attributes}),
|
||||
labels (@pxref{Label Attributes}),
|
||||
enumerators (@pxref{Enumerator Attributes}),
|
||||
statements (@pxref{Statement Attributes}),
|
||||
and types (@pxref{Type Attributes}).
|
||||
|
||||
There is some overlap between the purposes of attributes and pragmas
|
||||
@ -5558,8 +5560,8 @@ attributes are currently defined generically for variables.
|
||||
Other attributes are defined for variables on particular target
|
||||
systems. Other attributes are available for functions
|
||||
(@pxref{Function Attributes}), labels (@pxref{Label Attributes}),
|
||||
enumerators (@pxref{Enumerator Attributes}), and for types
|
||||
(@pxref{Type Attributes}).
|
||||
enumerators (@pxref{Enumerator Attributes}), statements
|
||||
(@pxref{Statement Attributes}), and for types (@pxref{Type Attributes}).
|
||||
Other front ends might define more attributes
|
||||
(@pxref{C++ Extensions,,Extensions to the C++ Language}).
|
||||
|
||||
@ -6340,7 +6342,8 @@ attributes of types. Some type attributes apply only to @code{struct}
|
||||
and @code{union} types, while others can apply to any type defined
|
||||
via a @code{typedef} declaration. Other attributes are defined for
|
||||
functions (@pxref{Function Attributes}), labels (@pxref{Label
|
||||
Attributes}), enumerators (@pxref{Enumerator Attributes}), and for
|
||||
Attributes}), enumerators (@pxref{Enumerator Attributes}),
|
||||
statements (@pxref{Statement Attributes}), and for
|
||||
variables (@pxref{Variable Attributes}).
|
||||
|
||||
The @code{__attribute__} keyword is followed by an attribute specification
|
||||
@ -6850,7 +6853,8 @@ GCC allows attributes to be set on C labels. @xref{Attribute Syntax}, for
|
||||
details of the exact syntax for using attributes. Other attributes are
|
||||
available for functions (@pxref{Function Attributes}), variables
|
||||
(@pxref{Variable Attributes}), enumerators (@pxref{Enumerator Attributes}),
|
||||
and for types (@pxref{Type Attributes}).
|
||||
statements (@pxref{Statement Attributes}), and for types
|
||||
(@pxref{Type Attributes}).
|
||||
|
||||
This example uses the @code{cold} label attribute to indicate the
|
||||
@code{ErrorHandling} branch is unlikely to be taken and that the
|
||||
@ -6903,8 +6907,8 @@ with computed goto or @code{asm goto}.
|
||||
GCC allows attributes to be set on enumerators. @xref{Attribute Syntax}, for
|
||||
details of the exact syntax for using attributes. Other attributes are
|
||||
available for functions (@pxref{Function Attributes}), variables
|
||||
(@pxref{Variable Attributes}), labels (@pxref{Label Attributes}),
|
||||
and for types (@pxref{Type Attributes}).
|
||||
(@pxref{Variable Attributes}), labels (@pxref{Label Attributes}), statements
|
||||
(@pxref{Statement Attributes}), and for types (@pxref{Type Attributes}).
|
||||
|
||||
This example uses the @code{deprecated} enumerator attribute to indicate the
|
||||
@code{oldval} enumerator is deprecated:
|
||||
@ -6935,6 +6939,46 @@ do instead. Note that the warnings only occurs for uses.
|
||||
|
||||
@end table
|
||||
|
||||
@node Statement Attributes
|
||||
@section Statement Attributes
|
||||
@cindex Statement Attributes
|
||||
|
||||
GCC allows attributes to be set on null statements. @xref{Attribute Syntax},
|
||||
for details of the exact syntax for using attributes. Other attributes are
|
||||
available for functions (@pxref{Function Attributes}), variables
|
||||
(@pxref{Variable Attributes}), labels (@pxref{Label Attributes}), enumerators
|
||||
(@pxref{Enumerator Attributes}), and for types (@pxref{Type Attributes}).
|
||||
|
||||
This example uses the @code{fallthrough} statement attribute to indicate that
|
||||
the @option{-Wimplicit-fallthrough} warning should not be emitted:
|
||||
|
||||
@smallexample
|
||||
switch (cond)
|
||||
@{
|
||||
case 1:
|
||||
bar (1);
|
||||
__attribute__((fallthrough));
|
||||
case 2:
|
||||
@dots{}
|
||||
@}
|
||||
@end smallexample
|
||||
|
||||
@table @code
|
||||
@item fallthrough
|
||||
@cindex @code{fallthrough} statement attribute
|
||||
The @code{fallthrough} attribute with a null statement serves as a
|
||||
fallthrough statement. It hints to the compiler that a statement
|
||||
that falls through to another case label, or user-defined label
|
||||
in a switch statement is intentional and thus the
|
||||
@option{-Wimplicit-fallthrough} warning must not trigger. The
|
||||
fallthrough attribute may appear at most once in each attribute
|
||||
list, and may not be mixed with other attributes. It can only
|
||||
be used in a switch statement (the compiler will issue an error
|
||||
otherwise), after a preceding statement and before a logically
|
||||
succeeding case label, or user-defined label.
|
||||
|
||||
@end table
|
||||
|
||||
@node Attribute Syntax
|
||||
@section Attribute Syntax
|
||||
@cindex attribute syntax
|
||||
@ -6962,6 +7006,8 @@ and enumerated types.
|
||||
applying to labels.
|
||||
@xref{Enumerator Attributes}, for details of the semantics of attributes
|
||||
applying to enumerators.
|
||||
@xref{Statement Attributes}, for details of the semantics of attributes
|
||||
applying to statements.
|
||||
|
||||
An @dfn{attribute specifier} is of the form
|
||||
@code{__attribute__ ((@var{attribute-list}))}. An @dfn{attribute list}
|
||||
@ -7027,6 +7073,10 @@ present. The optional attribute in the enumerator appertains to the
|
||||
enumeration constant. It is not possible to place the attribute after
|
||||
the constant expression, if present.
|
||||
|
||||
@subsubheading Statement Attributes
|
||||
In GNU C, an attribute specifier list may appear as part of a null
|
||||
statement. The attribute goes before the semicolon.
|
||||
|
||||
@subsubheading Type Attributes
|
||||
|
||||
An attribute specifier list may appear as part of a @code{struct},
|
||||
|
@ -273,7 +273,8 @@ Objective-C and Objective-C++ Dialects}.
|
||||
-Wformat-security -Wformat-signedness -Wformat-y2k -Wframe-address @gol
|
||||
-Wframe-larger-than=@var{len} -Wno-free-nonheap-object -Wjump-misses-init @gol
|
||||
-Wignored-qualifiers -Wignored-attributes -Wincompatible-pointer-types @gol
|
||||
-Wimplicit -Wimplicit-function-declaration -Wimplicit-int @gol
|
||||
-Wimplicit -Wimplicit-fallthrough -Wimplicit-function-declaration @gol
|
||||
-Wimplicit-int @gol
|
||||
-Winit-self -Winline -Wno-int-conversion -Wint-in-bool-context @gol
|
||||
-Wno-int-to-pointer-cast -Winvalid-memory-model -Wno-invalid-offsetof @gol
|
||||
-Winvalid-pch -Wlarger-than=@var{len} @gol
|
||||
@ -3719,6 +3720,7 @@ name is still supported, but the newer name is more descriptive.)
|
||||
@gccoptlist{-Wclobbered @gol
|
||||
-Wempty-body @gol
|
||||
-Wignored-qualifiers @gol
|
||||
-Wimplicit-fallthrough @gol
|
||||
-Wmissing-field-initializers @gol
|
||||
-Wmissing-parameter-type @r{(C only)} @gol
|
||||
-Wold-style-declaration @r{(C only)} @gol
|
||||
@ -4087,6 +4089,93 @@ enabled by default and it is made into an error by
|
||||
Same as @option{-Wimplicit-int} and @option{-Wimplicit-function-declaration}.
|
||||
This warning is enabled by @option{-Wall}.
|
||||
|
||||
@item -Wimplicit-fallthrough
|
||||
@opindex Wimplicit-fallthrough
|
||||
@opindex Wno-implicit-fallthrough
|
||||
Warn when a switch case falls through. For example:
|
||||
|
||||
@smallexample
|
||||
@group
|
||||
switch (cond)
|
||||
@{
|
||||
case 1:
|
||||
a = 1;
|
||||
break;
|
||||
case 2:
|
||||
a = 2;
|
||||
case 3:
|
||||
a = 3;
|
||||
break;
|
||||
@}
|
||||
@end group
|
||||
@end smallexample
|
||||
|
||||
This warning does not warn when the last statement of a case cannot
|
||||
fall through, e.g. when there is a return statement or a call to function
|
||||
declared with the noreturn attribute. @option{-Wimplicit-fallthrough}
|
||||
also takes into account control flow statements, such as ifs, and only
|
||||
warns when appropriate. E.g.@:
|
||||
|
||||
@smallexample
|
||||
@group
|
||||
switch (cond)
|
||||
@{
|
||||
case 1:
|
||||
if (i > 3) @{
|
||||
bar (5);
|
||||
break;
|
||||
@} else if (i < 1) @{
|
||||
bar (0);
|
||||
@} else
|
||||
return;
|
||||
default:
|
||||
@dots{}
|
||||
@}
|
||||
@end group
|
||||
@end smallexample
|
||||
|
||||
Since there are occasions where a switch case fall through is desirable,
|
||||
GCC provides an attribute, @code{__attribute__ ((fallthrough))}, that is
|
||||
to be used along with a null statement to suppress this warning that
|
||||
would normally occur:
|
||||
|
||||
@smallexample
|
||||
@group
|
||||
switch (cond)
|
||||
@{
|
||||
case 1:
|
||||
bar (0);
|
||||
__attribute__ ((fallthrough));
|
||||
default:
|
||||
@dots{}
|
||||
@}
|
||||
@end group
|
||||
@end smallexample
|
||||
|
||||
C++17 provides a standard way to suppress the @option{-Wimplicit-fallthrough}
|
||||
warning using @code{[[fallthrough]];} instead of the GNU attribute. In C++11
|
||||
or C++14 users can use @code{[[gnu::fallthrough]];}, which is a GNU extension.
|
||||
Instead of the these attributes, it is also possible to add a "falls through"
|
||||
comment to silence the warning. GCC accepts a wide range of such comments,
|
||||
for example all of "Falls through.", "fallthru", "FALLS-THROUGH" work. This
|
||||
comment needs to consist of two words merely, optionally followed by periods
|
||||
or whitespaces.
|
||||
|
||||
@smallexample
|
||||
@group
|
||||
switch (cond)
|
||||
@{
|
||||
case 1:
|
||||
bar (0);
|
||||
/* FALLTHRU */
|
||||
default:
|
||||
@dots{}
|
||||
@}
|
||||
@end group
|
||||
@end smallexample
|
||||
|
||||
This warning is enabled by @option{-Wextra}.
|
||||
|
||||
@item -Wignored-qualifiers @r{(C and C++ only)}
|
||||
@opindex Wignored-qualifiers
|
||||
@opindex Wno-ignored-qualifiers
|
||||
|
@ -2096,9 +2096,11 @@ output_alternate_entry_point (FILE *file, rtx_insn *insn)
|
||||
case LABEL_WEAK_ENTRY:
|
||||
#ifdef ASM_WEAKEN_LABEL
|
||||
ASM_WEAKEN_LABEL (file, name);
|
||||
gcc_fallthrough ();
|
||||
#endif
|
||||
case LABEL_GLOBAL_ENTRY:
|
||||
targetm.asm_out.globalize_label (file, name);
|
||||
gcc_fallthrough ();
|
||||
case LABEL_STATIC_ENTRY:
|
||||
#ifdef ASM_OUTPUT_TYPE_DIRECTIVE
|
||||
ASM_OUTPUT_TYPE_DIRECTIVE (file, name, "function");
|
||||
|
@ -1,3 +1,15 @@
|
||||
2016-09-26 Marek Polacek <polacek@redhat.com>
|
||||
|
||||
PR c/7652
|
||||
* arith.c (eval_intrinsic): Add gcc_fallthrough.
|
||||
* frontend-passes.c (optimize_op): Likewise.
|
||||
(gfc_expr_walker): Likewise.
|
||||
* parse.c (next_fixed): Likewise.
|
||||
* primary.c (match_variable): Likewise.
|
||||
* trans-array.c: Likewise.
|
||||
* trans-expr.c (flatten_array_ctors_without_strlen): Likewise.
|
||||
* trans-io.c (transfer_expr): Likewise.
|
||||
|
||||
2016-09-25 Steven G. Kargl <kargl@gcc.gnu.org>
|
||||
|
||||
PR fortran/77429
|
||||
|
@ -1521,7 +1521,7 @@ eval_intrinsic (gfc_intrinsic_op op,
|
||||
break;
|
||||
}
|
||||
|
||||
/* Fall through */
|
||||
gcc_fallthrough ();
|
||||
/* Numeric binary */
|
||||
case INTRINSIC_PLUS:
|
||||
case INTRINSIC_MINUS:
|
||||
|
@ -1481,7 +1481,7 @@ optimize_op (gfc_expr *e)
|
||||
case INTRINSIC_LT:
|
||||
changed = optimize_comparison (e, op);
|
||||
|
||||
/* Fall through */
|
||||
gcc_fallthrough ();
|
||||
/* Look at array constructors. */
|
||||
case INTRINSIC_PLUS:
|
||||
case INTRINSIC_MINUS:
|
||||
@ -3349,6 +3349,7 @@ gfc_expr_walker (gfc_expr **e, walk_expr_fn_t exprfn, void *data)
|
||||
|
||||
/* Fall through to the variable case in order to walk the
|
||||
reference. */
|
||||
gcc_fallthrough ();
|
||||
|
||||
case EXPR_SUBSTRING:
|
||||
case EXPR_VARIABLE:
|
||||
|
@ -1261,7 +1261,7 @@ next_fixed (void)
|
||||
return decode_oacc_directive ();
|
||||
}
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
gcc_fallthrough ();
|
||||
|
||||
/* Comments have already been skipped by the time we get
|
||||
here so don't bother checking for them. */
|
||||
|
@ -3572,6 +3572,7 @@ match_variable (gfc_expr **result, int equiv_flag, int host_flag)
|
||||
break;
|
||||
|
||||
/* Fall through to error */
|
||||
gcc_fallthrough ();
|
||||
|
||||
default:
|
||||
gfc_error ("%qs at %C is not a variable", sym->name);
|
||||
|
@ -4032,6 +4032,7 @@ done:
|
||||
continue;
|
||||
}
|
||||
/* Otherwise fall through GFC_SS_FUNCTION. */
|
||||
gcc_fallthrough ();
|
||||
}
|
||||
case GFC_ISYM_LCOBOUND:
|
||||
case GFC_ISYM_UCOBOUND:
|
||||
|
@ -2208,6 +2208,7 @@ flatten_array_ctors_without_strlen (gfc_expr* e)
|
||||
}
|
||||
|
||||
/* Otherwise, fall through to handle constructor elements. */
|
||||
gcc_fallthrough ();
|
||||
case EXPR_STRUCTURE:
|
||||
for (c = gfc_constructor_first (e->value.constructor);
|
||||
c; c = gfc_constructor_next (c))
|
||||
|
@ -2384,6 +2384,7 @@ transfer_expr (gfc_se * se, gfc_typespec * ts, tree addr_expr,
|
||||
}
|
||||
/* If a CLASS object gets through to here, fall through and ICE. */
|
||||
}
|
||||
gcc_fallthrough ();
|
||||
default:
|
||||
gfc_internal_error ("Bad IO basetype (%d)", ts->type);
|
||||
}
|
||||
|
@ -1219,6 +1219,7 @@ make_canonical (file_location loc, struct attr_desc *attr, rtx exp)
|
||||
|
||||
exp = newexp;
|
||||
/* Fall through to COND case since this is now a COND. */
|
||||
gcc_fallthrough ();
|
||||
|
||||
case COND:
|
||||
{
|
||||
@ -3615,6 +3616,7 @@ write_test_expr (FILE *outf, rtx exp, unsigned int attrs_cached, int flags,
|
||||
}
|
||||
|
||||
/* Otherwise, fall through to normal unary operator. */
|
||||
gcc_fallthrough ();
|
||||
|
||||
/* Unary operators. */
|
||||
case ABS: case NEG:
|
||||
|
@ -74,7 +74,7 @@ validate_exp (rtx exp, const char *name, file_location loc)
|
||||
}
|
||||
}
|
||||
}
|
||||
/* fall through */
|
||||
gcc_fallthrough ();
|
||||
|
||||
/* These need no special checking. */
|
||||
case MATCH_OPERAND:
|
||||
|
@ -1690,7 +1690,7 @@ find_candidates_dom_walker::before_dom_children (basic_block bb)
|
||||
case POINTER_PLUS_EXPR:
|
||||
case MINUS_EXPR:
|
||||
rhs2 = gimple_assign_rhs2 (gs);
|
||||
/* Fall-through. */
|
||||
gcc_fallthrough ();
|
||||
|
||||
CASE_CONVERT:
|
||||
case MODIFY_EXPR:
|
||||
|
10
gcc/gimple.h
10
gcc/gimple.h
@ -2921,6 +2921,16 @@ gimple_call_internal_unique_p (const gimple *gs)
|
||||
return gimple_call_internal_unique_p (gc);
|
||||
}
|
||||
|
||||
/* Return true if GS is an internal function FN. */
|
||||
|
||||
static inline bool
|
||||
gimple_call_internal_p (const gimple *gs, internal_fn fn)
|
||||
{
|
||||
return (is_gimple_call (gs)
|
||||
&& gimple_call_internal_p (gs)
|
||||
&& gimple_call_internal_fn (gs) == fn);
|
||||
}
|
||||
|
||||
/* If CTRL_ALTERING_P is true, mark GIMPLE_CALL S to be a stmt
|
||||
that could alter control flow. */
|
||||
|
||||
|
454
gcc/gimplify.c
454
gcc/gimplify.c
@ -160,6 +160,7 @@ struct gimplify_ctx
|
||||
unsigned in_cleanup_point_expr : 1;
|
||||
unsigned keep_stack : 1;
|
||||
unsigned save_stack : 1;
|
||||
unsigned in_switch_expr : 1;
|
||||
};
|
||||
|
||||
struct gimplify_omp_ctx
|
||||
@ -1626,6 +1627,430 @@ maybe_warn_switch_unreachable (gimple_seq seq)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* A label entry that pairs label and a location. */
|
||||
struct label_entry
|
||||
{
|
||||
tree label;
|
||||
location_t loc;
|
||||
};
|
||||
|
||||
/* Find LABEL in vector of label entries VEC. */
|
||||
|
||||
static struct label_entry *
|
||||
find_label_entry (const auto_vec<struct label_entry> *vec, tree label)
|
||||
{
|
||||
unsigned int i;
|
||||
struct label_entry *l;
|
||||
|
||||
FOR_EACH_VEC_ELT (*vec, i, l)
|
||||
if (l->label == label)
|
||||
return l;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Return true if LABEL, a LABEL_DECL, represents a case label
|
||||
in a vector of labels CASES. */
|
||||
|
||||
static bool
|
||||
case_label_p (const vec<tree> *cases, tree label)
|
||||
{
|
||||
unsigned int i;
|
||||
tree l;
|
||||
|
||||
FOR_EACH_VEC_ELT (*cases, i, l)
|
||||
if (CASE_LABEL (l) == label)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Find the last statement in a scope STMT. */
|
||||
|
||||
static gimple *
|
||||
last_stmt_in_scope (gimple *stmt)
|
||||
{
|
||||
if (!stmt)
|
||||
return NULL;
|
||||
|
||||
switch (gimple_code (stmt))
|
||||
{
|
||||
case GIMPLE_BIND:
|
||||
{
|
||||
gbind *bind = as_a <gbind *> (stmt);
|
||||
stmt = gimple_seq_last_stmt (gimple_bind_body (bind));
|
||||
return last_stmt_in_scope (stmt);
|
||||
}
|
||||
|
||||
case GIMPLE_TRY:
|
||||
{
|
||||
gtry *try_stmt = as_a <gtry *> (stmt);
|
||||
stmt = gimple_seq_last_stmt (gimple_try_eval (try_stmt));
|
||||
gimple *last_eval = last_stmt_in_scope (stmt);
|
||||
if (gimple_stmt_may_fallthru (last_eval)
|
||||
&& gimple_try_kind (try_stmt) == GIMPLE_TRY_FINALLY)
|
||||
{
|
||||
stmt = gimple_seq_last_stmt (gimple_try_cleanup (try_stmt));
|
||||
return last_stmt_in_scope (stmt);
|
||||
}
|
||||
else
|
||||
return last_eval;
|
||||
}
|
||||
|
||||
default:
|
||||
return stmt;
|
||||
}
|
||||
}
|
||||
|
||||
/* Collect interesting labels in LABELS and return the statement preceding
|
||||
another case label, or a user-defined label. */
|
||||
|
||||
static gimple *
|
||||
collect_fallthrough_labels (gimple_stmt_iterator *gsi_p,
|
||||
auto_vec <struct label_entry> *labels)
|
||||
{
|
||||
gimple *prev = NULL;
|
||||
|
||||
do
|
||||
{
|
||||
if (gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_BIND
|
||||
|| gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_TRY)
|
||||
{
|
||||
/* Nested scope. Only look at the last statement of
|
||||
the innermost scope. */
|
||||
location_t bind_loc = gimple_location (gsi_stmt (*gsi_p));
|
||||
gimple *last = last_stmt_in_scope (gsi_stmt (*gsi_p));
|
||||
if (last)
|
||||
{
|
||||
prev = last;
|
||||
/* It might be a label without a location. Use the
|
||||
location of the scope then. */
|
||||
if (!gimple_has_location (prev))
|
||||
gimple_set_location (prev, bind_loc);
|
||||
}
|
||||
gsi_next (gsi_p);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Ifs are tricky. */
|
||||
if (gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_COND)
|
||||
{
|
||||
gcond *cond_stmt = as_a <gcond *> (gsi_stmt (*gsi_p));
|
||||
tree false_lab = gimple_cond_false_label (cond_stmt);
|
||||
location_t if_loc = gimple_location (cond_stmt);
|
||||
|
||||
/* If we have e.g.
|
||||
if (i > 1) goto <D.2259>; else goto D;
|
||||
we can't do much with the else-branch. */
|
||||
if (!DECL_ARTIFICIAL (false_lab))
|
||||
break;
|
||||
|
||||
/* Go on until the false label, then one step back. */
|
||||
for (; !gsi_end_p (*gsi_p); gsi_next (gsi_p))
|
||||
{
|
||||
gimple *stmt = gsi_stmt (*gsi_p);
|
||||
if (gimple_code (stmt) == GIMPLE_LABEL
|
||||
&& gimple_label_label (as_a <glabel *> (stmt)) == false_lab)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Not found? Oops. */
|
||||
if (gsi_end_p (*gsi_p))
|
||||
break;
|
||||
|
||||
struct label_entry l = { false_lab, if_loc };
|
||||
labels->safe_push (l);
|
||||
|
||||
/* Go to the last statement of the then branch. */
|
||||
gsi_prev (gsi_p);
|
||||
|
||||
/* if (i != 0) goto <D.1759>; else goto <D.1760>;
|
||||
<D.1759>:
|
||||
<stmt>;
|
||||
goto <D.1761>;
|
||||
<D.1760>:
|
||||
*/
|
||||
if (gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_GOTO
|
||||
&& !gimple_has_location (gsi_stmt (*gsi_p)))
|
||||
{
|
||||
/* Look at the statement before, it might be
|
||||
attribute fallthrough, in which case don't warn. */
|
||||
gsi_prev (gsi_p);
|
||||
bool fallthru_before_dest
|
||||
= gimple_call_internal_p (gsi_stmt (*gsi_p), IFN_FALLTHROUGH);
|
||||
gsi_next (gsi_p);
|
||||
tree goto_dest = gimple_goto_dest (gsi_stmt (*gsi_p));
|
||||
if (!fallthru_before_dest)
|
||||
{
|
||||
struct label_entry l = { goto_dest, if_loc };
|
||||
labels->safe_push (l);
|
||||
}
|
||||
}
|
||||
/* And move back. */
|
||||
gsi_next (gsi_p);
|
||||
}
|
||||
|
||||
/* Remember the last statement. Skip labels that are of no interest
|
||||
to us. */
|
||||
if (gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_LABEL)
|
||||
{
|
||||
tree label = gimple_label_label (as_a <glabel *> (gsi_stmt (*gsi_p)));
|
||||
if (find_label_entry (labels, label))
|
||||
prev = gsi_stmt (*gsi_p);
|
||||
}
|
||||
else
|
||||
prev = gsi_stmt (*gsi_p);
|
||||
gsi_next (gsi_p);
|
||||
}
|
||||
while (!gsi_end_p (*gsi_p)
|
||||
/* Stop if we find a case or a user-defined label. */
|
||||
&& (gimple_code (gsi_stmt (*gsi_p)) != GIMPLE_LABEL
|
||||
|| !gimple_has_location (gsi_stmt (*gsi_p))));
|
||||
|
||||
return prev;
|
||||
}
|
||||
|
||||
/* Return true if the switch fallthough warning should occur. LABEL is
|
||||
the label statement that we're falling through to. */
|
||||
|
||||
static bool
|
||||
should_warn_for_implicit_fallthrough (gimple_stmt_iterator *gsi_p, tree label)
|
||||
{
|
||||
gimple_stmt_iterator gsi = *gsi_p;
|
||||
|
||||
/* Don't warn for a non-case label followed by a statement:
|
||||
case 0:
|
||||
foo ();
|
||||
label:
|
||||
bar ();
|
||||
as these are likely intentional. */
|
||||
if (!case_label_p (&gimplify_ctxp->case_labels, label))
|
||||
{
|
||||
gsi_next (&gsi);
|
||||
if (gsi_end_p (gsi) || gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Don't warn for terminated branches, i.e. when the subsequent case labels
|
||||
immediately breaks. */
|
||||
gsi = *gsi_p;
|
||||
|
||||
/* Skip all immediately following labels. */
|
||||
while (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) == GIMPLE_LABEL)
|
||||
gsi_next (&gsi);
|
||||
|
||||
/* { ... something; default:; } */
|
||||
if (gsi_end_p (gsi)
|
||||
/* { ... something; default: break; } or
|
||||
{ ... something; default: goto L; } */
|
||||
|| gimple_code (gsi_stmt (gsi)) == GIMPLE_GOTO
|
||||
/* { ... something; default: return; } */
|
||||
|| gimple_code (gsi_stmt (gsi)) == GIMPLE_RETURN)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Callback for walk_gimple_seq. */
|
||||
|
||||
static tree
|
||||
warn_implicit_fallthrough_r (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
|
||||
struct walk_stmt_info *)
|
||||
{
|
||||
gimple *stmt = gsi_stmt (*gsi_p);
|
||||
|
||||
*handled_ops_p = true;
|
||||
switch (gimple_code (stmt))
|
||||
{
|
||||
case GIMPLE_TRY:
|
||||
case GIMPLE_BIND:
|
||||
case GIMPLE_CATCH:
|
||||
case GIMPLE_EH_FILTER:
|
||||
case GIMPLE_TRANSACTION:
|
||||
/* Walk the sub-statements. */
|
||||
*handled_ops_p = false;
|
||||
break;
|
||||
|
||||
/* Find a sequence of form:
|
||||
|
||||
GIMPLE_LABEL
|
||||
[...]
|
||||
<may fallthru stmt>
|
||||
GIMPLE_LABEL
|
||||
|
||||
and possibly warn. */
|
||||
case GIMPLE_LABEL:
|
||||
{
|
||||
/* Found a label. Skip all immediately following labels. */
|
||||
while (!gsi_end_p (*gsi_p)
|
||||
&& gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_LABEL)
|
||||
gsi_next (gsi_p);
|
||||
|
||||
/* There might be no more statements. */
|
||||
if (gsi_end_p (*gsi_p))
|
||||
return integer_zero_node;
|
||||
|
||||
/* Vector of labels that fall through. */
|
||||
auto_vec <struct label_entry> labels;
|
||||
gimple *prev = collect_fallthrough_labels (gsi_p, &labels);
|
||||
|
||||
/* There might be no more statements. */
|
||||
if (gsi_end_p (*gsi_p))
|
||||
return integer_zero_node;
|
||||
|
||||
gimple *next = gsi_stmt (*gsi_p);
|
||||
tree label;
|
||||
/* If what follows is a label, then we may have a fallthrough. */
|
||||
if (gimple_code (next) == GIMPLE_LABEL
|
||||
&& gimple_has_location (next)
|
||||
&& (label = gimple_label_label (as_a <glabel *> (next)))
|
||||
&& !FALLTHROUGH_LABEL_P (label)
|
||||
&& prev != NULL)
|
||||
{
|
||||
struct label_entry *l;
|
||||
bool warned_p = false;
|
||||
if (!should_warn_for_implicit_fallthrough (gsi_p, label))
|
||||
/* Quiet. */;
|
||||
else if (gimple_code (prev) == GIMPLE_LABEL
|
||||
&& (label = gimple_label_label (as_a <glabel *> (prev)))
|
||||
&& (l = find_label_entry (&labels, label)))
|
||||
warned_p = warning_at (l->loc, OPT_Wimplicit_fallthrough,
|
||||
"this statement may fall through");
|
||||
else if (!gimple_call_internal_p (prev, IFN_FALLTHROUGH)
|
||||
/* Try to be clever and don't warn when the statement
|
||||
can't actually fall through. */
|
||||
&& gimple_stmt_may_fallthru (prev)
|
||||
&& gimple_has_location (prev))
|
||||
warned_p = warning_at (gimple_location (prev),
|
||||
OPT_Wimplicit_fallthrough,
|
||||
"this statement may fall through");
|
||||
if (warned_p)
|
||||
inform (gimple_location (next), "here");
|
||||
|
||||
/* Mark this label as processed so as to prevent multiple
|
||||
warnings in nested switches. */
|
||||
FALLTHROUGH_LABEL_P (label) = true;
|
||||
|
||||
/* So that next warn_implicit_fallthrough_r will start looking for
|
||||
a new sequence starting with this label. */
|
||||
gsi_prev (gsi_p);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Warn when a switch case falls through. */
|
||||
|
||||
static void
|
||||
maybe_warn_implicit_fallthrough (gimple_seq seq)
|
||||
{
|
||||
if (!warn_implicit_fallthrough)
|
||||
return;
|
||||
|
||||
/* This warning is meant for C/C++/ObjC/ObjC++ only. */
|
||||
if (!(lang_GNU_C ()
|
||||
|| lang_GNU_CXX ()
|
||||
|| lang_GNU_OBJC ()))
|
||||
return;
|
||||
|
||||
struct walk_stmt_info wi;
|
||||
memset (&wi, 0, sizeof (wi));
|
||||
walk_gimple_seq (seq, warn_implicit_fallthrough_r, NULL, &wi);
|
||||
}
|
||||
|
||||
/* Callback for walk_gimple_seq. */
|
||||
|
||||
static tree
|
||||
expand_FALLTHROUGH_r (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
|
||||
struct walk_stmt_info *)
|
||||
{
|
||||
gimple *stmt = gsi_stmt (*gsi_p);
|
||||
|
||||
*handled_ops_p = true;
|
||||
switch (gimple_code (stmt))
|
||||
{
|
||||
case GIMPLE_TRY:
|
||||
case GIMPLE_BIND:
|
||||
case GIMPLE_CATCH:
|
||||
case GIMPLE_EH_FILTER:
|
||||
case GIMPLE_TRANSACTION:
|
||||
/* Walk the sub-statements. */
|
||||
*handled_ops_p = false;
|
||||
break;
|
||||
case GIMPLE_CALL:
|
||||
if (gimple_call_internal_p (stmt, IFN_FALLTHROUGH))
|
||||
{
|
||||
gsi_remove (gsi_p, true);
|
||||
if (gsi_end_p (*gsi_p))
|
||||
return integer_zero_node;
|
||||
|
||||
bool found = false;
|
||||
location_t loc = gimple_location (stmt);
|
||||
|
||||
gimple_stmt_iterator gsi2 = *gsi_p;
|
||||
stmt = gsi_stmt (gsi2);
|
||||
if (gimple_code (stmt) == GIMPLE_GOTO && !gimple_has_location (stmt))
|
||||
{
|
||||
/* Go on until the artificial label. */
|
||||
tree goto_dest = gimple_goto_dest (stmt);
|
||||
for (; !gsi_end_p (gsi2); gsi_next (&gsi2))
|
||||
{
|
||||
if (gimple_code (gsi_stmt (gsi2)) == GIMPLE_LABEL
|
||||
&& gimple_label_label (as_a <glabel *> (gsi_stmt (gsi2)))
|
||||
== goto_dest)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Not found? Stop. */
|
||||
if (gsi_end_p (gsi2))
|
||||
break;
|
||||
|
||||
/* Look one past it. */
|
||||
gsi_next (&gsi2);
|
||||
}
|
||||
|
||||
/* We're looking for a case label or default label here. */
|
||||
while (!gsi_end_p (gsi2))
|
||||
{
|
||||
stmt = gsi_stmt (gsi2);
|
||||
if (gimple_code (stmt) == GIMPLE_LABEL)
|
||||
{
|
||||
tree label = gimple_label_label (as_a <glabel *> (stmt));
|
||||
if (gimple_has_location (stmt) && DECL_ARTIFICIAL (label))
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
/* Something other than a label. That's not expected. */
|
||||
break;
|
||||
gsi_next (&gsi2);
|
||||
}
|
||||
if (!found)
|
||||
warning_at (loc, 0, "attribute %<fallthrough%> not preceding "
|
||||
"a case label or default label");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Expand all FALLTHROUGH () calls in SEQ. */
|
||||
|
||||
static void
|
||||
expand_FALLTHROUGH (gimple_seq *seq_p)
|
||||
{
|
||||
struct walk_stmt_info wi;
|
||||
memset (&wi, 0, sizeof (wi));
|
||||
walk_gimple_seq_mod (seq_p, expand_FALLTHROUGH_r, NULL, &wi);
|
||||
}
|
||||
|
||||
|
||||
/* Gimplify a SWITCH_EXPR, and collect the vector of labels it can
|
||||
branch to. */
|
||||
@ -1660,10 +2085,17 @@ gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p)
|
||||
labels. Save all the things from the switch body to append after. */
|
||||
saved_labels = gimplify_ctxp->case_labels;
|
||||
gimplify_ctxp->case_labels.create (8);
|
||||
bool old_in_switch_expr = gimplify_ctxp->in_switch_expr;
|
||||
gimplify_ctxp->in_switch_expr = true;
|
||||
|
||||
gimplify_stmt (&SWITCH_BODY (switch_expr), &switch_body_seq);
|
||||
|
||||
gimplify_ctxp->in_switch_expr = old_in_switch_expr;
|
||||
maybe_warn_switch_unreachable (switch_body_seq);
|
||||
maybe_warn_implicit_fallthrough (switch_body_seq);
|
||||
/* Only do this for the outermost GIMPLE_SWITCH. */
|
||||
if (!gimplify_ctxp->in_switch_expr)
|
||||
expand_FALLTHROUGH (&switch_body_seq);
|
||||
|
||||
labels = gimplify_ctxp->case_labels;
|
||||
gimplify_ctxp->case_labels = saved_labels;
|
||||
@ -1694,6 +2126,21 @@ gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p)
|
||||
return GS_ALL_DONE;
|
||||
}
|
||||
|
||||
/* Gimplify the LABEL_EXPR pointed to by EXPR_P. */
|
||||
|
||||
static enum gimplify_status
|
||||
gimplify_label_expr (tree *expr_p, gimple_seq *pre_p)
|
||||
{
|
||||
gcc_assert (decl_function_context (LABEL_EXPR_LABEL (*expr_p))
|
||||
== current_function_decl);
|
||||
|
||||
glabel *label_stmt = gimple_build_label (LABEL_EXPR_LABEL (*expr_p));
|
||||
gimple_set_location (label_stmt, EXPR_LOCATION (*expr_p));
|
||||
gimplify_seq_add_stmt (pre_p, label_stmt);
|
||||
|
||||
return GS_ALL_DONE;
|
||||
}
|
||||
|
||||
/* Gimplify the CASE_LABEL_EXPR pointed to by EXPR_P. */
|
||||
|
||||
static enum gimplify_status
|
||||
@ -1711,6 +2158,7 @@ gimplify_case_label_expr (tree *expr_p, gimple_seq *pre_p)
|
||||
break;
|
||||
|
||||
label_stmt = gimple_build_label (CASE_LABEL (*expr_p));
|
||||
gimple_set_location (label_stmt, EXPR_LOCATION (*expr_p));
|
||||
ctxp->case_labels.safe_push (*expr_p);
|
||||
gimplify_seq_add_stmt (pre_p, label_stmt);
|
||||
|
||||
@ -10777,11 +11225,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
|
||||
break;
|
||||
|
||||
case LABEL_EXPR:
|
||||
ret = GS_ALL_DONE;
|
||||
gcc_assert (decl_function_context (LABEL_EXPR_LABEL (*expr_p))
|
||||
== current_function_decl);
|
||||
gimplify_seq_add_stmt (pre_p,
|
||||
gimple_build_label (LABEL_EXPR_LABEL (*expr_p)));
|
||||
ret = gimplify_label_expr (expr_p, pre_p);
|
||||
break;
|
||||
|
||||
case CASE_LABEL_EXPR:
|
||||
|
@ -893,6 +893,7 @@ go_format_type (struct godump_container *container, tree type,
|
||||
case UNION_TYPE:
|
||||
is_union = true;
|
||||
/* Fall through to RECORD_TYPE case. */
|
||||
gcc_fallthrough ();
|
||||
case RECORD_TYPE:
|
||||
{
|
||||
unsigned int prev_field_end;
|
||||
|
@ -244,6 +244,15 @@ expand_TSAN_FUNC_EXIT (internal_fn, gcall *)
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
/* This should get expanded in the lower pass. */
|
||||
|
||||
static void
|
||||
expand_FALLTHROUGH (internal_fn, gcall *call)
|
||||
{
|
||||
error_at (gimple_location (call),
|
||||
"invalid use of attribute %<fallthrough%>");
|
||||
}
|
||||
|
||||
/* Helper function for expand_addsub_overflow. Return 1
|
||||
if ARG interpreted as signed in its precision is known to be always
|
||||
positive or 2 if ARG is known to be always negative, or 3 if ARG may
|
||||
|
@ -195,6 +195,9 @@ DEF_INTERNAL_FN (ATOMIC_BIT_TEST_AND_COMPLEMENT, ECF_LEAF | ECF_NOTHROW, NULL)
|
||||
DEF_INTERNAL_FN (ATOMIC_BIT_TEST_AND_RESET, ECF_LEAF | ECF_NOTHROW, NULL)
|
||||
DEF_INTERNAL_FN (ATOMIC_COMPARE_EXCHANGE, ECF_LEAF | ECF_NOTHROW, NULL)
|
||||
|
||||
/* To implement [[fallthrough]]. */
|
||||
DEF_INTERNAL_FN (FALLTHROUGH, ECF_LEAF | ECF_NOTHROW, NULL)
|
||||
|
||||
#undef DEF_INTERNAL_INT_FN
|
||||
#undef DEF_INTERNAL_FLT_FN
|
||||
#undef DEF_INTERNAL_OPTAB_FN
|
||||
|
@ -725,3 +725,12 @@ lang_GNU_Fortran (void)
|
||||
{
|
||||
return strncmp (lang_hooks.name, "GNU Fortran", 11) == 0;
|
||||
}
|
||||
|
||||
/* Returns true if the current lang_hooks represents the GNU Objective-C
|
||||
frontend. */
|
||||
|
||||
bool
|
||||
lang_GNU_OBJC (void)
|
||||
{
|
||||
return strncmp (lang_hooks.name, "GNU Objective-C", 15) == 0;
|
||||
}
|
||||
|
@ -546,5 +546,6 @@ extern tree add_builtin_type (const char *name, tree type);
|
||||
extern bool lang_GNU_C (void);
|
||||
extern bool lang_GNU_CXX (void);
|
||||
extern bool lang_GNU_Fortran (void);
|
||||
extern bool lang_GNU_OBJC (void);
|
||||
|
||||
#endif /* GCC_LANG_HOOKS_H */
|
||||
|
@ -3022,6 +3022,7 @@ elimination_effects (rtx x, machine_mode mem_mode)
|
||||
break;
|
||||
|
||||
/* Fall through to generic unary operation case. */
|
||||
gcc_fallthrough ();
|
||||
case STRICT_LOW_PART:
|
||||
case NEG: case NOT:
|
||||
case SIGN_EXTEND: case ZERO_EXTEND:
|
||||
|
@ -364,6 +364,7 @@ mark_referenced_resources (rtx x, struct resources *res,
|
||||
}
|
||||
|
||||
/* ... fall through to other INSN processing ... */
|
||||
gcc_fallthrough ();
|
||||
|
||||
case INSN:
|
||||
case JUMP_INSN:
|
||||
@ -674,6 +675,7 @@ mark_set_resources (rtx x, struct resources *res, int in_dest,
|
||||
}
|
||||
|
||||
/* ... and also what its RTL says it modifies, if anything. */
|
||||
gcc_fallthrough ();
|
||||
|
||||
case JUMP_INSN:
|
||||
case INSN:
|
||||
|
@ -746,6 +746,12 @@ extern void fancy_abort (const char *, int, const char *) ATTRIBUTE_NORETURN;
|
||||
#define gcc_unreachable() (fancy_abort (__FILE__, __LINE__, __FUNCTION__))
|
||||
#endif
|
||||
|
||||
#if GCC_VERSION >= 7000
|
||||
# define gcc_fallthrough() __attribute__((fallthrough))
|
||||
#else
|
||||
# define gcc_fallthrough()
|
||||
#endif
|
||||
|
||||
#if GCC_VERSION >= 3001
|
||||
#define STATIC_CONSTANT_P(X) (__builtin_constant_p (X) && (X))
|
||||
#else
|
||||
|
@ -1,3 +1,37 @@
|
||||
2016-09-26 Marek Polacek <polacek@redhat.com>
|
||||
|
||||
PR c/7652
|
||||
* c-c++-common/Wimplicit-fallthrough-1.c: New test.
|
||||
* c-c++-common/Wimplicit-fallthrough-10.c: New test.
|
||||
* c-c++-common/Wimplicit-fallthrough-11.c: New test.
|
||||
* c-c++-common/Wimplicit-fallthrough-12.c: New test.
|
||||
* c-c++-common/Wimplicit-fallthrough-13.c: New test.
|
||||
* c-c++-common/Wimplicit-fallthrough-14.c: New test.
|
||||
* c-c++-common/Wimplicit-fallthrough-15.c: New test.
|
||||
* c-c++-common/Wimplicit-fallthrough-16.c: New test.
|
||||
* c-c++-common/Wimplicit-fallthrough-17.c: New test.
|
||||
* c-c++-common/Wimplicit-fallthrough-18.c: New test.
|
||||
* c-c++-common/Wimplicit-fallthrough-19.c: New test.
|
||||
* c-c++-common/Wimplicit-fallthrough-20.c: New test.
|
||||
* c-c++-common/Wimplicit-fallthrough-21.c: New test.
|
||||
* c-c++-common/Wimplicit-fallthrough-2.c: New test.
|
||||
* c-c++-common/Wimplicit-fallthrough-3.c: New test.
|
||||
* c-c++-common/Wimplicit-fallthrough-4.c: New test.
|
||||
* c-c++-common/Wimplicit-fallthrough-5.c: New test.
|
||||
* c-c++-common/Wimplicit-fallthrough-6.c: New test.
|
||||
* c-c++-common/Wimplicit-fallthrough-7.c: New test.
|
||||
* c-c++-common/Wimplicit-fallthrough-8.c: New test.
|
||||
* c-c++-common/Wimplicit-fallthrough-9.c: New test.
|
||||
* c-c++-common/attr-fallthrough-1.c: New test.
|
||||
* c-c++-common/attr-fallthrough-2.c: New test.
|
||||
* g++.dg/cpp0x/fallthrough1.C: New test.
|
||||
* g++.dg/cpp0x/fallthrough2.C: New test.
|
||||
* g++.dg/cpp1z/fallthrough1.C: New test.
|
||||
* g++.dg/warn/Wunused-label-1.C: Turn dg-error into dg-warning.
|
||||
* gcc.dg/Wimplicit-fallthrough-1.c: New test.
|
||||
* obj-c++.dg/Wimplicit-fallthrough-1.mm: New test.
|
||||
* objc.dg/Wimplicit-fallthrough-1.m: New test.
|
||||
|
||||
2016-09-25 Steven G. Kargl <kargl@gcc.gnu.org>
|
||||
|
||||
PR fortran/77429
|
||||
|
38
gcc/testsuite/c-c++-common/Wimplicit-fallthrough-1.c
Normal file
38
gcc/testsuite/c-c++-common/Wimplicit-fallthrough-1.c
Normal file
@ -0,0 +1,38 @@
|
||||
/* PR c/7652 */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-Wimplicit-fallthrough" } */
|
||||
/* Test taken from
|
||||
<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0188r0.pdf>. */
|
||||
|
||||
extern void f (int);
|
||||
|
||||
void
|
||||
foo (int n)
|
||||
{
|
||||
switch (n)
|
||||
{
|
||||
case 22:
|
||||
case 33:
|
||||
f (1); /* { dg-warning "statement may fall through" } */
|
||||
case 44:
|
||||
f (2);
|
||||
__attribute__((fallthrough));
|
||||
case 55:
|
||||
if (n > 10)
|
||||
{
|
||||
f (3);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
f (4);
|
||||
__attribute__((fallthrough));
|
||||
}
|
||||
case 66:
|
||||
f (5);
|
||||
__attribute__((fallthrough)); /* { dg-warning "not preceding" } */
|
||||
f (6); /* { dg-warning "statement may fall through" } */
|
||||
case 77:
|
||||
f (7);
|
||||
}
|
||||
}
|
239
gcc/testsuite/c-c++-common/Wimplicit-fallthrough-10.c
Normal file
239
gcc/testsuite/c-c++-common/Wimplicit-fallthrough-10.c
Normal file
@ -0,0 +1,239 @@
|
||||
/* PR c/7652 */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-Wimplicit-fallthrough" } */
|
||||
|
||||
extern void bar (int);
|
||||
|
||||
void
|
||||
f (int i)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
{
|
||||
bar (0);
|
||||
break;
|
||||
}
|
||||
else if (i > 10)
|
||||
{
|
||||
bar (1);
|
||||
__attribute__((fallthrough));
|
||||
}
|
||||
else
|
||||
break;
|
||||
case 2:
|
||||
bar (99);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i) /* { dg-warning "statement may fall through" } */
|
||||
bar (2);
|
||||
else if (i > 10)
|
||||
{
|
||||
bar (3);
|
||||
__attribute__((fallthrough));
|
||||
}
|
||||
else
|
||||
break;
|
||||
case 2:
|
||||
bar (4);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
{
|
||||
bar (0);
|
||||
break;
|
||||
}
|
||||
else if (i > 10) /* { dg-warning "statement may fall through" } */
|
||||
{
|
||||
bar (1);
|
||||
}
|
||||
else
|
||||
break;
|
||||
case 2:
|
||||
bar (99);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
{
|
||||
bar (0);
|
||||
break;
|
||||
}
|
||||
else if (i > 10)
|
||||
{
|
||||
bar (1);
|
||||
break;
|
||||
}
|
||||
else
|
||||
break;
|
||||
case 2:
|
||||
bar (99);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
{
|
||||
bar (0);
|
||||
break;
|
||||
}
|
||||
else if (i > 10)
|
||||
{
|
||||
bar (1);
|
||||
break;
|
||||
}
|
||||
else
|
||||
bar (2); /* { dg-warning "statement may fall through" } */
|
||||
case 2:
|
||||
bar (99);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
{
|
||||
bar (0);
|
||||
__attribute__((fallthrough));
|
||||
}
|
||||
else if (i > 10)
|
||||
{
|
||||
bar (1);
|
||||
break;
|
||||
}
|
||||
else
|
||||
bar (2); /* { dg-warning "statement may fall through" } */
|
||||
case 2:
|
||||
bar (99);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
{
|
||||
bar (0);
|
||||
__attribute__((fallthrough));
|
||||
}
|
||||
else if (i > 10)
|
||||
{
|
||||
bar (1);
|
||||
__attribute__((fallthrough));
|
||||
}
|
||||
else
|
||||
break;
|
||||
case 2:
|
||||
bar (99);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
{
|
||||
bar (0);
|
||||
__attribute__((fallthrough));
|
||||
}
|
||||
else if (i > 10)
|
||||
{
|
||||
bar (1);
|
||||
__attribute__((fallthrough));
|
||||
}
|
||||
else
|
||||
bar (2); /* { dg-warning "statement may fall through" } */
|
||||
case 2:
|
||||
bar (99);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
{
|
||||
bar (0);
|
||||
__attribute__((fallthrough));
|
||||
}
|
||||
else if (i > 10) /* { dg-warning "statement may fall through" } */
|
||||
{
|
||||
bar (1);
|
||||
bar (2);
|
||||
}
|
||||
else
|
||||
__attribute__((fallthrough));
|
||||
case 2:
|
||||
bar (99);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i) /* { dg-warning "statement may fall through" } */
|
||||
{
|
||||
bar (0);
|
||||
}
|
||||
else if (i > 10)
|
||||
{
|
||||
bar (1);
|
||||
}
|
||||
else
|
||||
{
|
||||
bar (1);
|
||||
__attribute__((fallthrough));
|
||||
}
|
||||
case 2:
|
||||
bar (99);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
{
|
||||
bar (0);
|
||||
__attribute__((fallthrough));
|
||||
}
|
||||
else if (i > 10)
|
||||
{
|
||||
bar (1);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
bar (1);
|
||||
__attribute__((fallthrough));
|
||||
}
|
||||
case 2:
|
||||
bar (99);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
{
|
||||
bar (0);
|
||||
break;
|
||||
}
|
||||
else if (i > 10) /* { dg-warning "statement may fall through" } */
|
||||
{
|
||||
bar (1);
|
||||
}
|
||||
else
|
||||
{
|
||||
bar (1);
|
||||
__attribute__((fallthrough));
|
||||
}
|
||||
case 2:
|
||||
bar (99);
|
||||
}
|
||||
}
|
23
gcc/testsuite/c-c++-common/Wimplicit-fallthrough-11.c
Normal file
23
gcc/testsuite/c-c++-common/Wimplicit-fallthrough-11.c
Normal file
@ -0,0 +1,23 @@
|
||||
/* PR c/7652 */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-Wimplicit-fallthrough -O2" } */
|
||||
|
||||
/* Prevent false positive with optimizations. */
|
||||
|
||||
extern void g (int);
|
||||
|
||||
void
|
||||
f (int i)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i > 10)
|
||||
g (0);
|
||||
else
|
||||
goto L;
|
||||
break;
|
||||
L:
|
||||
case 2:;
|
||||
}
|
||||
}
|
26
gcc/testsuite/c-c++-common/Wimplicit-fallthrough-12.c
Normal file
26
gcc/testsuite/c-c++-common/Wimplicit-fallthrough-12.c
Normal file
@ -0,0 +1,26 @@
|
||||
/* PR c/7652 */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-Wimplicit-fallthrough -O2" } */
|
||||
|
||||
/* Don't let optimizations preclude the warning. */
|
||||
|
||||
extern void bar (int);
|
||||
|
||||
void
|
||||
f (int i)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i > 1)
|
||||
bar (1);
|
||||
else
|
||||
goto D;
|
||||
break;
|
||||
case 2:
|
||||
bar (2); /* { dg-warning "statement may fall through" } */
|
||||
D:
|
||||
default:
|
||||
bar (33);
|
||||
}
|
||||
}
|
63
gcc/testsuite/c-c++-common/Wimplicit-fallthrough-13.c
Normal file
63
gcc/testsuite/c-c++-common/Wimplicit-fallthrough-13.c
Normal file
@ -0,0 +1,63 @@
|
||||
/* PR c/7652 */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-Wimplicit-fallthrough" } */
|
||||
|
||||
/* As per <http://security.coverity.com/blog/2013/Sep/gimme-a-break.html>, don't
|
||||
warn for terminated branches (fall through to break / end of the switch). */
|
||||
|
||||
extern void bar (int);
|
||||
|
||||
void
|
||||
f (int i)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
bar (1);
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
bar (1);
|
||||
default:
|
||||
goto X;
|
||||
}
|
||||
X:
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
bar (1);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
bar (1);
|
||||
case 2:
|
||||
case 3:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
bar (1);
|
||||
default:;
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
bar (1);
|
||||
case 2:
|
||||
case 3:
|
||||
default:;
|
||||
}
|
||||
}
|
162
gcc/testsuite/c-c++-common/Wimplicit-fallthrough-14.c
Normal file
162
gcc/testsuite/c-c++-common/Wimplicit-fallthrough-14.c
Normal file
@ -0,0 +1,162 @@
|
||||
/* PR c/7652 */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-Wimplicit-fallthrough" } */
|
||||
|
||||
/* Test various falls through comments. */
|
||||
|
||||
extern void bar (int);
|
||||
|
||||
void
|
||||
fn (int i)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case -1:
|
||||
bar (-1);
|
||||
/*-fallthrough*/
|
||||
case 0:
|
||||
bar (0);
|
||||
/*@fallthrough@*/
|
||||
case 1:
|
||||
bar (1);
|
||||
/* FALL THRU */
|
||||
case 2:
|
||||
bar (2);
|
||||
/* FALLTHRU */
|
||||
case 3:
|
||||
bar (3);
|
||||
/* FALLS THRU */
|
||||
case 4:
|
||||
bar (4);
|
||||
/* FALL-THRU */
|
||||
case 5:
|
||||
bar (5);
|
||||
/* FALL THROUGH */
|
||||
case 6:
|
||||
bar (6);
|
||||
/* FALLTHROUGH */
|
||||
case 7:
|
||||
bar (7);
|
||||
/* FALLS THROUGH */
|
||||
case 8:
|
||||
bar (8);
|
||||
/* FALL-THROUGH */
|
||||
case 9:
|
||||
bar (9);
|
||||
/*FALLTHRU*/
|
||||
case 10:
|
||||
bar (10);
|
||||
/* FALLTHRU.*/
|
||||
case 11:
|
||||
bar (11);
|
||||
/* FALLTHROUGH. */
|
||||
case 12:
|
||||
bar (12);
|
||||
/* Fall thru */
|
||||
case 13:
|
||||
bar (13);
|
||||
/* Falls thru */
|
||||
case 14:
|
||||
bar (14);
|
||||
/* Fall-thru */
|
||||
case 15:
|
||||
bar (15);
|
||||
/* Fall Thru */
|
||||
case 16:
|
||||
bar (16);
|
||||
/* Falls Thru */
|
||||
case 17:
|
||||
bar (17);
|
||||
/* Fall-Thru */
|
||||
case 18:
|
||||
bar (18);
|
||||
/* Fall through */
|
||||
case 19:
|
||||
bar (19);
|
||||
/* Falls through */
|
||||
case 20:
|
||||
bar (20);
|
||||
/* Fall-through */
|
||||
case 21:
|
||||
bar (21);
|
||||
/* Fall Through */
|
||||
case 22:
|
||||
bar (22);
|
||||
/* Falls Through */
|
||||
case 23:
|
||||
bar (23);
|
||||
/* Fall-Through */
|
||||
case 24:
|
||||
bar (24);
|
||||
/* Falls through. */
|
||||
case 25:
|
||||
bar (25);
|
||||
/* Falls through. */
|
||||
case 26:
|
||||
bar (26);
|
||||
/* fall thru */
|
||||
case 27:
|
||||
bar (27);
|
||||
/* falls thru */
|
||||
case 28:
|
||||
bar (28);
|
||||
/* fall-thru */
|
||||
case 29:
|
||||
bar (29);
|
||||
/* fall thru */
|
||||
case 30:
|
||||
bar (30);
|
||||
/* falls thru */
|
||||
case 31:
|
||||
bar (31);
|
||||
/* fall-thru */
|
||||
case 32:
|
||||
bar (32);
|
||||
/* fall through */
|
||||
case 33:
|
||||
bar (33);
|
||||
/* falls through */
|
||||
case 34:
|
||||
bar (34);
|
||||
/* fall-through */
|
||||
default:
|
||||
bar (99);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
i++;
|
||||
/*@fallthrough@*/
|
||||
L:
|
||||
default:
|
||||
bar (6);
|
||||
}
|
||||
|
||||
{
|
||||
__label__ L2;
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
i++;
|
||||
/*@fallthrough@*/
|
||||
L2:
|
||||
default:
|
||||
bar (6);
|
||||
}
|
||||
}
|
||||
|
||||
/* Don't generate false -Wswitch-unreachable warning. */
|
||||
switch (i)
|
||||
{
|
||||
/*FALLTHROUGH*/
|
||||
case 0:
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i)
|
||||
{
|
||||
/* fall through */
|
||||
L1:;
|
||||
}
|
||||
}
|
31
gcc/testsuite/c-c++-common/Wimplicit-fallthrough-15.c
Normal file
31
gcc/testsuite/c-c++-common/Wimplicit-fallthrough-15.c
Normal file
@ -0,0 +1,31 @@
|
||||
/* PR c/7652 */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-Wimplicit-fallthrough" } */
|
||||
|
||||
/* Another nested switch. Check that we don't warn here. */
|
||||
|
||||
void
|
||||
f (int i)
|
||||
{
|
||||
int j = 0;
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
j = 10;
|
||||
__attribute__((fallthrough));
|
||||
case 2:
|
||||
j += 10;
|
||||
break;
|
||||
case 3:
|
||||
switch (i)
|
||||
{
|
||||
case 5:
|
||||
j += 2;
|
||||
__attribute__((fallthrough));
|
||||
case 6:
|
||||
j += 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
32
gcc/testsuite/c-c++-common/Wimplicit-fallthrough-16.c
Normal file
32
gcc/testsuite/c-c++-common/Wimplicit-fallthrough-16.c
Normal file
@ -0,0 +1,32 @@
|
||||
/* PR c/7652 */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-Wimplicit-fallthrough" } */
|
||||
|
||||
/* Another nested switch, and with an initialization on top. Check that
|
||||
we do warn here. */
|
||||
|
||||
void
|
||||
f (int i)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
int t = 3;
|
||||
switch (i)
|
||||
{
|
||||
case 3:
|
||||
if (i > 5)
|
||||
--i;
|
||||
i += 10; /* { dg-warning "statement may fall through" } */
|
||||
case 4:
|
||||
t /= 5;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
--i;
|
||||
break;
|
||||
}
|
||||
}
|
29
gcc/testsuite/c-c++-common/Wimplicit-fallthrough-17.c
Normal file
29
gcc/testsuite/c-c++-common/Wimplicit-fallthrough-17.c
Normal file
@ -0,0 +1,29 @@
|
||||
/* PR c/7652 */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-Wimplicit-fallthrough" } */
|
||||
|
||||
/* Another nested switch, and with an initialization on top. Check that
|
||||
we do not warn here as the case 3 falls through to break. */
|
||||
|
||||
void
|
||||
f (int i)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
int t = 3;
|
||||
switch (i)
|
||||
{
|
||||
case 3:
|
||||
i += 10;
|
||||
case 4:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
--i;
|
||||
break;
|
||||
}
|
||||
}
|
42
gcc/testsuite/c-c++-common/Wimplicit-fallthrough-18.c
Normal file
42
gcc/testsuite/c-c++-common/Wimplicit-fallthrough-18.c
Normal file
@ -0,0 +1,42 @@
|
||||
/* PR c/7652 */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-Wimplicit-fallthrough" } */
|
||||
|
||||
/* Testing some loops. */
|
||||
|
||||
int f (void);
|
||||
|
||||
int
|
||||
g (int i)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
for (;;)
|
||||
{
|
||||
if (f ()) /* { dg-warning "statement may fall through" "fall through" { xfail *-*-* } } */
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
h (int i)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
do
|
||||
{
|
||||
if (f ()) /* { dg-warning "statement may fall through" } */
|
||||
break;
|
||||
}
|
||||
while (0);
|
||||
case 1:
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
85
gcc/testsuite/c-c++-common/Wimplicit-fallthrough-19.c
Normal file
85
gcc/testsuite/c-c++-common/Wimplicit-fallthrough-19.c
Normal file
@ -0,0 +1,85 @@
|
||||
/* PR c/7652 */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-Wimplicit-fallthrough" } */
|
||||
|
||||
/* Testing non-case labels. */
|
||||
|
||||
int foo (int);
|
||||
|
||||
void
|
||||
f1 (int i)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
foo (1);
|
||||
L1:
|
||||
foo (2);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
foo (1); /* { dg-warning "statement may fall through" } */
|
||||
L2:
|
||||
case 2:
|
||||
foo (2);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
foo (1); /* { dg-warning "statement may fall through" } */
|
||||
case 2:
|
||||
L3:
|
||||
foo (2);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
foo (1); /* { dg-warning "statement may fall through" } */
|
||||
L4:
|
||||
case 2:
|
||||
L5:
|
||||
foo (2);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
foo (2);
|
||||
L6:
|
||||
foo (3);
|
||||
}
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
foo (2); /* { dg-warning "statement may fall through" } */
|
||||
L7:
|
||||
case 2:
|
||||
foo (3);
|
||||
}
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
foo (2); /* { dg-warning "statement may fall through" } */
|
||||
case 2:
|
||||
L8:
|
||||
foo (3);
|
||||
}
|
||||
}
|
||||
}
|
223
gcc/testsuite/c-c++-common/Wimplicit-fallthrough-2.c
Normal file
223
gcc/testsuite/c-c++-common/Wimplicit-fallthrough-2.c
Normal file
@ -0,0 +1,223 @@
|
||||
/* PR c/7652 */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-Wimplicit-fallthrough" } */
|
||||
|
||||
extern void bar (int);
|
||||
|
||||
/* Test if without else. */
|
||||
|
||||
void
|
||||
f (int i)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i) /* { dg-warning "statement may fall through" } */
|
||||
bar (1);
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i) /* { dg-warning "statement may fall through" } */
|
||||
return;
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
bar (1);
|
||||
break;
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
return;
|
||||
break;
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i) /* { dg-warning "statement may fall through" } */
|
||||
goto L1;
|
||||
case 2:
|
||||
L1:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i) /* { dg-warning "statement may fall through" } */
|
||||
goto L2;
|
||||
L2:
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
goto L3;
|
||||
break;
|
||||
case 2:
|
||||
L3:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
goto L4;
|
||||
break;
|
||||
L4:
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i) /* { dg-warning "statement may fall through" } */
|
||||
if (i > 9)
|
||||
bar (1);
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
if (i > 9)
|
||||
bar (1);
|
||||
break;
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
{ int a; }
|
||||
{
|
||||
if (i) /* { dg-warning "statement may fall through" } */
|
||||
if (i > 9)
|
||||
bar (1);
|
||||
}
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
bar (1);
|
||||
bar (2); /* { dg-warning "statement may fall through" } */
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
bar (1);
|
||||
bar (2);
|
||||
break;
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
return;
|
||||
bar (2); /* { dg-warning "statement may fall through" } */
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
return;
|
||||
bar (2);
|
||||
break;
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
bar (1);
|
||||
if (i)
|
||||
bar (2);
|
||||
if (i)
|
||||
bar (3);
|
||||
bar (4); /* { dg-warning "statement may fall through" } */
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
bar (1);
|
||||
if (i)
|
||||
bar (2);
|
||||
if (i) /* { dg-warning "statement may fall through" } */
|
||||
bar (3);
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
bar (1);
|
||||
if (i)
|
||||
bar (2);
|
||||
if (i)
|
||||
bar (3);
|
||||
bar (4);
|
||||
break;
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
bar (1);
|
||||
if (i)
|
||||
bar (2);
|
||||
if (i)
|
||||
bar (3);
|
||||
break;
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
}
|
41
gcc/testsuite/c-c++-common/Wimplicit-fallthrough-20.c
Normal file
41
gcc/testsuite/c-c++-common/Wimplicit-fallthrough-20.c
Normal file
@ -0,0 +1,41 @@
|
||||
/* PR c/7652 */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-Wimplicit-fallthrough" } */
|
||||
|
||||
int
|
||||
f (int i)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case -1:
|
||||
__attribute__((fallthrough));
|
||||
default:
|
||||
__attribute__((fallthrough));
|
||||
case 1:
|
||||
return 6;
|
||||
case 2 ... 4:
|
||||
__attribute__((fallthrough));
|
||||
case 5:
|
||||
return 7;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
g (int i)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case -1:
|
||||
__attribute__((used)); /* { dg-warning "ignored|only attribute" } */
|
||||
default:
|
||||
__attribute__((used)); /* { dg-warning "ignored|only attribute" } */
|
||||
case 1:
|
||||
return 6;
|
||||
case 2 ... 4:
|
||||
__attribute__((used)); /* { dg-warning "ignored|only attribute" } */
|
||||
case 5:
|
||||
return 7;
|
||||
}
|
||||
return 0;
|
||||
}
|
25
gcc/testsuite/c-c++-common/Wimplicit-fallthrough-21.c
Normal file
25
gcc/testsuite/c-c++-common/Wimplicit-fallthrough-21.c
Normal file
@ -0,0 +1,25 @@
|
||||
/* PR c/7652 */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-Wimplicit-fallthrough" } */
|
||||
|
||||
int
|
||||
f (int i)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
i++;
|
||||
__attribute__((fallthrough));
|
||||
lab1:
|
||||
case 1:
|
||||
i++;
|
||||
__attribute__((fallthrough)); /* { dg-warning "not preceding" } */
|
||||
lab2:
|
||||
--i;
|
||||
break;
|
||||
case 3:
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
543
gcc/testsuite/c-c++-common/Wimplicit-fallthrough-3.c
Normal file
543
gcc/testsuite/c-c++-common/Wimplicit-fallthrough-3.c
Normal file
@ -0,0 +1,543 @@
|
||||
/* PR c/7652 */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-Wimplicit-fallthrough" } */
|
||||
|
||||
extern void bar (int);
|
||||
|
||||
/* Test if with else. */
|
||||
|
||||
void
|
||||
f (int i)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i) /* { dg-warning "statement may fall through" } */
|
||||
bar (1);
|
||||
else
|
||||
bar (2);
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
bar (1);
|
||||
else
|
||||
bar (2);
|
||||
bar (3); /* { dg-warning "statement may fall through" } */
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
return;
|
||||
else
|
||||
bar (2); /* { dg-warning "statement may fall through" } */
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
return;
|
||||
else
|
||||
bar (2);
|
||||
bar (3); /* { dg-warning "statement may fall through" } */
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i) /* { dg-warning "statement may fall through" } */
|
||||
bar (1);
|
||||
else
|
||||
return;
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
bar (1);
|
||||
else
|
||||
return;
|
||||
bar (3); /* { dg-warning "statement may fall through" } */
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
return;
|
||||
else
|
||||
return;
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
return;
|
||||
else
|
||||
return;
|
||||
bar (3); /* { dg-warning "statement may fall through" } */
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i) /* { dg-warning "statement may fall through" } */
|
||||
{
|
||||
bar (1);
|
||||
bar (2);
|
||||
bar (3);
|
||||
bar (4);
|
||||
}
|
||||
else
|
||||
{
|
||||
bar (5);
|
||||
bar (6);
|
||||
bar (7);
|
||||
bar (8);
|
||||
}
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
{
|
||||
bar (1);
|
||||
bar (2);
|
||||
bar (3);
|
||||
bar (4);
|
||||
}
|
||||
else
|
||||
{
|
||||
bar (5);
|
||||
bar (6);
|
||||
bar (7);
|
||||
bar (8);
|
||||
}
|
||||
bar (9); /* { dg-warning "statement may fall through" } */
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i) /* { dg-warning "statement may fall through" } */
|
||||
{
|
||||
}
|
||||
else
|
||||
bar (2);
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i) /* { dg-warning "statement may fall through" } */
|
||||
bar (1);
|
||||
else
|
||||
{
|
||||
}
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i) /* { dg-warning "statement may fall through" } */
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i) /* { dg-warning "statement may fall through" } */
|
||||
return;
|
||||
else
|
||||
{
|
||||
}
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i) /* { dg-warning "statement may fall through" } */
|
||||
{
|
||||
}
|
||||
else
|
||||
return;
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
goto L1;
|
||||
else
|
||||
bar (2); /* { dg-warning "statement may fall through" } */
|
||||
case 2:
|
||||
L1:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
goto L2;
|
||||
else
|
||||
bar (2); /* { dg-warning "statement may fall through" } */
|
||||
L2:
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i) /* { dg-warning "statement may fall through" } */
|
||||
bar (1);
|
||||
else
|
||||
goto L3;
|
||||
case 2:
|
||||
L3:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i) /* { dg-warning "statement may fall through" } */
|
||||
bar (1);
|
||||
else
|
||||
goto L4;
|
||||
L4:
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
goto L5;
|
||||
else
|
||||
goto L5;
|
||||
L5:
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
bar (1);
|
||||
else
|
||||
bar (2);
|
||||
break;
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
bar (1);
|
||||
else
|
||||
bar (2);
|
||||
bar (3);
|
||||
break;
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
return;
|
||||
else
|
||||
bar (2);
|
||||
break;
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
return;
|
||||
else
|
||||
bar (2);
|
||||
bar (3);
|
||||
break;
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
bar (1);
|
||||
else
|
||||
return;
|
||||
break;
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
bar (1);
|
||||
else
|
||||
return;
|
||||
bar (3);
|
||||
break;
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
return;
|
||||
else
|
||||
return;
|
||||
break;
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
return;
|
||||
else
|
||||
return;
|
||||
bar (3);
|
||||
break;
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
{
|
||||
bar (1);
|
||||
bar (2);
|
||||
bar (3);
|
||||
bar (4);
|
||||
}
|
||||
else
|
||||
{
|
||||
bar (5);
|
||||
bar (6);
|
||||
bar (7);
|
||||
bar (8);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
{
|
||||
bar (1);
|
||||
bar (2);
|
||||
bar (3);
|
||||
bar (4);
|
||||
}
|
||||
else
|
||||
{
|
||||
bar (5);
|
||||
bar (6);
|
||||
bar (7);
|
||||
bar (8);
|
||||
}
|
||||
bar (9);
|
||||
break;
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
{
|
||||
}
|
||||
else
|
||||
bar (2);
|
||||
break;
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
bar (1);
|
||||
else
|
||||
{
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
return;
|
||||
else
|
||||
{
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
{
|
||||
}
|
||||
else
|
||||
return;
|
||||
break;
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
goto L6;
|
||||
else
|
||||
bar (2);
|
||||
break;
|
||||
case 2:
|
||||
L6:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
goto L7;
|
||||
else
|
||||
bar (2);
|
||||
break;
|
||||
L7:
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
bar (1);
|
||||
else
|
||||
goto L8;
|
||||
break;
|
||||
case 2:
|
||||
L8:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
bar (1);
|
||||
else
|
||||
goto L9;
|
||||
break;
|
||||
L9:
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i)
|
||||
goto L10;
|
||||
else
|
||||
goto L10;
|
||||
break;
|
||||
L10:
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
}
|
250
gcc/testsuite/c-c++-common/Wimplicit-fallthrough-4.c
Normal file
250
gcc/testsuite/c-c++-common/Wimplicit-fallthrough-4.c
Normal file
@ -0,0 +1,250 @@
|
||||
/* PR c/7652 */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-Wimplicit-fallthrough" } */
|
||||
|
||||
extern void bar (int);
|
||||
|
||||
/* Test if with more elses. */
|
||||
|
||||
void
|
||||
f (int i)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i > 5) /* { dg-warning "statement may fall through" } */
|
||||
bar (1);
|
||||
else if (i > 10)
|
||||
bar (2);
|
||||
else if (i > 15)
|
||||
bar (3);
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i > 5) /* { dg-warning "statement may fall through" } */
|
||||
bar (1);
|
||||
else if (i > 10)
|
||||
bar (2);
|
||||
else if (i > 15)
|
||||
bar (3);
|
||||
else
|
||||
bar (4);
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i > 5)
|
||||
return;
|
||||
else if (i > 10) /* { dg-warning "statement may fall through" } */
|
||||
bar (2);
|
||||
else if (i > 15)
|
||||
bar (3);
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i > 5)
|
||||
return;
|
||||
else if (i > 10) /* { dg-warning "statement may fall through" } */
|
||||
bar (2);
|
||||
else if (i > 15)
|
||||
bar (3);
|
||||
else
|
||||
bar (4);
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i > 5) /* { dg-warning "statement may fall through" } */
|
||||
bar (1);
|
||||
else if (i > 10)
|
||||
return;
|
||||
else if (i > 15)
|
||||
bar (3);
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i > 5) /* { dg-warning "statement may fall through" } */
|
||||
bar (1);
|
||||
else if (i > 10)
|
||||
return;
|
||||
else if (i > 15)
|
||||
bar (3);
|
||||
else
|
||||
bar (4);
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i > 5) /* { dg-warning "statement may fall through" } */
|
||||
bar (1);
|
||||
else if (i > 10)
|
||||
bar (4);
|
||||
else if (i > 15)
|
||||
return;
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i > 5) /* { dg-warning "statement may fall through" } */
|
||||
bar (1);
|
||||
else if (i > 10)
|
||||
bar (4);
|
||||
else if (i > 15)
|
||||
return;
|
||||
else
|
||||
bar (4);
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i > 5)
|
||||
return;
|
||||
else if (i > 10)
|
||||
return;
|
||||
else if (i > 15) /* { dg-warning "statement may fall through" } */
|
||||
bar (3);
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i > 5)
|
||||
return;
|
||||
else if (i > 10)
|
||||
return;
|
||||
else if (i > 15) /* { dg-warning "statement may fall through" } */
|
||||
bar (3);
|
||||
else
|
||||
bar (4);
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i > 5)
|
||||
return;
|
||||
else if (i > 10) /* { dg-warning "statement may fall through" } */
|
||||
bar (2);
|
||||
else if (i > 15)
|
||||
return;
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i > 5)
|
||||
return;
|
||||
else if (i > 10) /* { dg-warning "statement may fall through" } */
|
||||
bar (2);
|
||||
else if (i > 15)
|
||||
return;
|
||||
else
|
||||
bar (4);
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i > 5) /* { dg-warning "statement may fall through" } */
|
||||
bar (1);
|
||||
else if (i > 10)
|
||||
return;
|
||||
else if (i > 15)
|
||||
return;
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i > 5) /* { dg-warning "statement may fall through" } */
|
||||
bar (1);
|
||||
else if (i > 10)
|
||||
return;
|
||||
else if (i > 15)
|
||||
return;
|
||||
else
|
||||
bar (4);
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i > 5)
|
||||
return;
|
||||
else if (i > 10)
|
||||
return;
|
||||
else if (i > 15) /* { dg-warning "statement may fall through" } */
|
||||
return;
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i > 5)
|
||||
return;
|
||||
else if (i > 10)
|
||||
return;
|
||||
else if (i > 15)
|
||||
return;
|
||||
else
|
||||
bar (4); /* { dg-warning "statement may fall through" } */
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i > 5)
|
||||
return;
|
||||
else if (i > 10)
|
||||
return;
|
||||
else if (i > 15)
|
||||
return;
|
||||
else
|
||||
return;
|
||||
case 2:
|
||||
__builtin_abort ();
|
||||
}
|
||||
}
|
109
gcc/testsuite/c-c++-common/Wimplicit-fallthrough-5.c
Normal file
109
gcc/testsuite/c-c++-common/Wimplicit-fallthrough-5.c
Normal file
@ -0,0 +1,109 @@
|
||||
/* PR c/7652 */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-Wimplicit-fallthrough" } */
|
||||
|
||||
extern void bar (int);
|
||||
extern void die (void) __attribute__((noreturn));
|
||||
|
||||
/* Test may_fallthru-ness. */
|
||||
|
||||
void
|
||||
f (int i)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
bar (0);
|
||||
__attribute__((fallthrough));
|
||||
case 2:;
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
bar (0);
|
||||
return;
|
||||
case 2:;
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
bar (0);
|
||||
break;
|
||||
case 2:;
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
bar (0);
|
||||
goto L1;
|
||||
L1:
|
||||
case 2:;
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
bar (0);
|
||||
die ();
|
||||
case 2:;
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
int i, j, k;
|
||||
bar (0);
|
||||
__attribute__((fallthrough));
|
||||
}
|
||||
case 2:;
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
int i, j, k;
|
||||
bar (0);
|
||||
return;
|
||||
}
|
||||
case 2:;
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
int i, j, k;
|
||||
bar (0);
|
||||
break;
|
||||
}
|
||||
case 2:;
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
int i, j, k;
|
||||
bar (0);
|
||||
goto L2;
|
||||
}
|
||||
L2:
|
||||
case 2:;
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
int i, j, k;
|
||||
bar (0);
|
||||
die ();
|
||||
}
|
||||
case 2:;
|
||||
}
|
||||
}
|
305
gcc/testsuite/c-c++-common/Wimplicit-fallthrough-6.c
Normal file
305
gcc/testsuite/c-c++-common/Wimplicit-fallthrough-6.c
Normal file
@ -0,0 +1,305 @@
|
||||
/* PR c/7652 */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-Wimplicit-fallthrough" } */
|
||||
|
||||
extern void bar (int);
|
||||
|
||||
/* Test nested scopes. */
|
||||
|
||||
void
|
||||
f (int i)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
int j;
|
||||
}
|
||||
case 2:
|
||||
bar (99);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
int j = 10; /* { dg-warning "statement may fall through" } */
|
||||
}
|
||||
case 2:
|
||||
bar (99);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
int k = 9;
|
||||
k++;
|
||||
{
|
||||
int j = 10;
|
||||
j++; /* { dg-warning "statement may fall through" } */
|
||||
}
|
||||
}
|
||||
case 2:
|
||||
bar (99);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
int k = 9;
|
||||
k++;
|
||||
{
|
||||
int j = 10;
|
||||
j++;
|
||||
{
|
||||
bar (1); /* { dg-warning "statement may fall through" } */
|
||||
}
|
||||
}
|
||||
}
|
||||
case 2:
|
||||
bar (99);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
int j = 0;
|
||||
bar (j);
|
||||
__attribute__((fallthrough));
|
||||
}
|
||||
case 2:
|
||||
bar (99);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
int j = 0;
|
||||
{
|
||||
int k = j + 5;
|
||||
bar (k);
|
||||
__attribute__((fallthrough));
|
||||
}
|
||||
}
|
||||
case 2:
|
||||
bar (99);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
int j = 0;
|
||||
bar (j);
|
||||
return;
|
||||
}
|
||||
case 2:
|
||||
bar (99);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
int j = 0;
|
||||
bar (j);
|
||||
goto L1;
|
||||
}
|
||||
L1:
|
||||
case 2:
|
||||
bar (99);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
{ /* { dg-warning "statement may fall through" "" { target c } 120 } */
|
||||
int j = 0;
|
||||
bar (j);
|
||||
if (j == 8)
|
||||
return; /* { dg-warning "statement may fall through" "" { target c++ } 124 } */
|
||||
}
|
||||
case 2:
|
||||
bar (99);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
int j = 0;
|
||||
bar (j);
|
||||
if (j == 8)
|
||||
return;
|
||||
else
|
||||
return;
|
||||
}
|
||||
case 2:
|
||||
bar (99);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
{ /* { dg-warning "statement may fall through" "" { target c } 148 } */
|
||||
int j = 0;
|
||||
bar (j);
|
||||
if (j == 8)
|
||||
bar (1);
|
||||
else
|
||||
return; /* { dg-warning "statement may fall through" "" { target c++ } 154 } */
|
||||
}
|
||||
case 2:
|
||||
bar (99);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
int j = 0;
|
||||
bar (j);
|
||||
if (j == 8)
|
||||
return;
|
||||
else
|
||||
bar (2); /* { dg-warning "statement may fall through" } */
|
||||
}
|
||||
case 2:
|
||||
bar (99);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
{ /* { dg-warning "statement may fall through" "" { target c } 178 } */
|
||||
int j = 0;
|
||||
bar (j);
|
||||
if (j == 8)
|
||||
bar (1);
|
||||
else
|
||||
bar (2); /* { dg-warning "statement may fall through" "" { target c++ } 184 } */
|
||||
}
|
||||
case 2:
|
||||
bar (99);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
int j = 0;
|
||||
bar (j);
|
||||
if (j == 8)
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
bar (99);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
int j = 0;
|
||||
bar (j);
|
||||
if (j == 8)
|
||||
return;
|
||||
else
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
bar (99);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
int j = 0;
|
||||
bar (j);
|
||||
if (j == 8)
|
||||
bar (1);
|
||||
else
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
bar (99);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
int j = 0;
|
||||
bar (j);
|
||||
if (j == 8)
|
||||
return;
|
||||
else
|
||||
bar (2);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
bar (99);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
int j = 0;
|
||||
bar (j);
|
||||
if (j == 8)
|
||||
bar (1);
|
||||
else
|
||||
bar (2);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
bar (99);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
int j = 9;
|
||||
while (1);
|
||||
}
|
||||
case 2:
|
||||
bar (99);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
{ /* { dg-warning "statement may fall through" "" { target c } 282 } */
|
||||
int j = 9;
|
||||
switch (j); /* { dg-warning "statement may fall through" "" { target c++ } 284 } */
|
||||
}
|
||||
case 2:
|
||||
bar (99);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
int j = 0;
|
||||
bar (j);
|
||||
if (j == 8)
|
||||
bar (1);
|
||||
else
|
||||
bar (2);
|
||||
__attribute__((fallthrough));
|
||||
}
|
||||
case 2:
|
||||
bar (99);
|
||||
}
|
||||
}
|
124
gcc/testsuite/c-c++-common/Wimplicit-fallthrough-7.c
Normal file
124
gcc/testsuite/c-c++-common/Wimplicit-fallthrough-7.c
Normal file
@ -0,0 +1,124 @@
|
||||
/* PR c/7652 */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-Wimplicit-fallthrough" } */
|
||||
|
||||
extern void bar (int);
|
||||
extern int bar2 (void);
|
||||
extern int *map;
|
||||
void
|
||||
f (int i)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
bar (0); /* { dg-warning "statement may fall through" } */
|
||||
static int i = 10;
|
||||
case 2:
|
||||
bar (99);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
{ /* { dg-warning "statement may fall through" "" { target c } 23 } */
|
||||
int a[i]; /* { dg-warning "statement may fall through" "" { target c++ } 24 } */
|
||||
}
|
||||
case 2:
|
||||
bar (99);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
for (int j = 0; j < 10; j++) /* { dg-warning "statement may fall through" "" { target c } 33 } */
|
||||
map[j] = j; /* { dg-warning "statement may fall through" "" { target c++ } 34 } */
|
||||
case 2:
|
||||
bar (99);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
do /* { dg-warning "statement may fall through" "" { target c++ } 42 } */
|
||||
bar (2);
|
||||
while (--i); /* { dg-warning "statement may fall through" "" { target c } 44 } */
|
||||
case 2:
|
||||
bar (99);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
switch (i + 2)
|
||||
case 4:
|
||||
bar (1); /* { dg-warning "statement may fall through" } */
|
||||
case 5:
|
||||
bar (5);
|
||||
return;
|
||||
}
|
||||
case 2:
|
||||
bar (99);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:;
|
||||
case 2:;
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i & 1) /* { dg-warning "statement may fall through" } */
|
||||
{
|
||||
bar (23);
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
bar (99);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i > 9) /* { dg-warning "statement may fall through" } */
|
||||
{
|
||||
bar (9);
|
||||
if (i == 10)
|
||||
{
|
||||
bar (10);
|
||||
break;
|
||||
}
|
||||
}
|
||||
case 2:
|
||||
bar (99);
|
||||
}
|
||||
|
||||
int r;
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
r = bar2 ();
|
||||
if (r) /* { dg-warning "statement may fall through" } */
|
||||
break;
|
||||
case 2:
|
||||
bar (99);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
r = bar2 ();
|
||||
if (r)
|
||||
return;
|
||||
if (!i) /* { dg-warning "statement may fall through" } */
|
||||
return;
|
||||
case 2:
|
||||
bar (99);
|
||||
}
|
||||
}
|
101
gcc/testsuite/c-c++-common/Wimplicit-fallthrough-8.c
Normal file
101
gcc/testsuite/c-c++-common/Wimplicit-fallthrough-8.c
Normal file
@ -0,0 +1,101 @@
|
||||
/* PR c/7652 */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-Wimplicit-fallthrough" } */
|
||||
|
||||
extern void grace (int);
|
||||
|
||||
int
|
||||
fn1 (int i)
|
||||
{
|
||||
switch (i)
|
||||
case 1:
|
||||
if (i == 5)
|
||||
grace (0);
|
||||
else
|
||||
goto done;
|
||||
done:;
|
||||
}
|
||||
|
||||
int
|
||||
fn2 (int i)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i == 5) /* { dg-warning "statement may fall through" } */
|
||||
grace (0);
|
||||
else
|
||||
goto done;
|
||||
case 2:
|
||||
--i;
|
||||
}
|
||||
done:;
|
||||
}
|
||||
|
||||
int
|
||||
fn3 (int i)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i == 5)
|
||||
goto done;
|
||||
else
|
||||
goto done;
|
||||
}
|
||||
done:;
|
||||
}
|
||||
|
||||
int
|
||||
fn4 (int i)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i == 5)
|
||||
{
|
||||
grace (1);
|
||||
goto done;
|
||||
}
|
||||
else
|
||||
goto done;
|
||||
case 2:;
|
||||
}
|
||||
done:;
|
||||
}
|
||||
|
||||
int
|
||||
fn5 (int i)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i == 5)
|
||||
{
|
||||
grace (1);
|
||||
goto done;
|
||||
}
|
||||
else
|
||||
grace (4); /* { dg-warning "statement may fall through" } */
|
||||
case 2:
|
||||
grace (9);
|
||||
}
|
||||
done:;
|
||||
}
|
||||
|
||||
int
|
||||
fn6 (int i)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (i == 5) /* { dg-warning "statement may fall through" } */
|
||||
{
|
||||
grace (1);
|
||||
goto done;
|
||||
}
|
||||
case 2:
|
||||
grace (8);
|
||||
}
|
||||
done:;
|
||||
}
|
26
gcc/testsuite/c-c++-common/Wimplicit-fallthrough-9.c
Normal file
26
gcc/testsuite/c-c++-common/Wimplicit-fallthrough-9.c
Normal file
@ -0,0 +1,26 @@
|
||||
/* PR c/7652 */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-Wimplicit-fallthrough" } */
|
||||
|
||||
/* Test we don't remove FALLTHROUGH () too early. */
|
||||
|
||||
extern void h (int);
|
||||
|
||||
void
|
||||
g (int i)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 3:
|
||||
h (7);
|
||||
__attribute__((fallthrough));
|
||||
case 4:;
|
||||
}
|
||||
}
|
||||
case 2:;
|
||||
}
|
||||
}
|
57
gcc/testsuite/c-c++-common/attr-fallthrough-1.c
Normal file
57
gcc/testsuite/c-c++-common/attr-fallthrough-1.c
Normal file
@ -0,0 +1,57 @@
|
||||
/* PR c/7652 */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-Wall -Wextra -Wpedantic" } */
|
||||
|
||||
extern void bar (int);
|
||||
void
|
||||
fn (int i)
|
||||
{
|
||||
__attribute__((fallthrough)) int j = 0; /* { dg-warning "ignored|attribute not followed" } */
|
||||
|
||||
if (j)
|
||||
__attribute__((fallthrough)); /* { dg-error "invalid use" } */
|
||||
|
||||
__attribute__((fallthrough)); /* { dg-error "invalid use" } */
|
||||
switch (i)
|
||||
{
|
||||
__attribute__((fallthrough)); /* { dg-warning "statement will never" } */
|
||||
case 1:
|
||||
i++;
|
||||
__attribute__((fallthrough));
|
||||
case 2:
|
||||
if (i) /* { dg-warning "statement may fall through" } */
|
||||
bar (2);
|
||||
else
|
||||
__attribute__((fallthrough));
|
||||
case 3:
|
||||
if (i > 1)
|
||||
__attribute__((fallthrough));
|
||||
else
|
||||
return;
|
||||
case 4:
|
||||
if (i)
|
||||
__attribute__((fallthrough)); /* { dg-warning "not preceding" } */
|
||||
__attribute__((fallthrough));
|
||||
case 5:
|
||||
;
|
||||
__attribute__((fallthrough));
|
||||
case 6:
|
||||
if (i) /* { dg-warning "statement may fall through" } */
|
||||
bar (6);
|
||||
else
|
||||
{
|
||||
__attribute__((fallthrough));
|
||||
}
|
||||
case 7:
|
||||
if (i > 1)
|
||||
{
|
||||
__attribute__((fallthrough));
|
||||
}
|
||||
else
|
||||
bar (7); /* { dg-warning "statement may fall through" } */
|
||||
default:
|
||||
--j;
|
||||
}
|
||||
|
||||
__attribute__((fallthrough)); /* { dg-error "invalid use" } */
|
||||
}
|
54
gcc/testsuite/c-c++-common/attr-fallthrough-2.c
Normal file
54
gcc/testsuite/c-c++-common/attr-fallthrough-2.c
Normal file
@ -0,0 +1,54 @@
|
||||
/* PR c/7652 */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-Wall -Wextra -Wpedantic -Wno-unused -Wno-implicit-fallthrough" } */
|
||||
|
||||
extern void bar (int);
|
||||
void
|
||||
fn (int i)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
bar (1);
|
||||
__attribute__((used));
|
||||
/* { dg-warning "empty declaration" "" { target c } 13 } */
|
||||
/* { dg-warning "ignored" "" { target c++ } 13 } */
|
||||
case 2:
|
||||
bar (1);
|
||||
__attribute__((foo));
|
||||
/* { dg-warning "empty declaration" "" { target c } 18 } */
|
||||
/* { dg-warning "ignored" "" { target c++ } 18 } */
|
||||
case 3:
|
||||
bar (1);
|
||||
__attribute__((fallthrough)) /* { dg-warning "not followed" "" { target c } } */
|
||||
case 4: /* { dg-error "expected" } */
|
||||
bar (1);
|
||||
__attribute__((fallthrough)) 1;
|
||||
/* { dg-error "expected" "" { target c } 26 } */
|
||||
/* { dg-warning "not followed" "" { target *-*-* } 26 } */
|
||||
case 5:
|
||||
bar (1);
|
||||
__attribute__((fallthrough)) int i; /* { dg-warning "ignored|not followed" } */
|
||||
case 6:
|
||||
bar (1);
|
||||
__attribute__((fallthrough ("x"))); /* { dg-warning "specified with a parameter" } */
|
||||
case 7:
|
||||
bar (1);
|
||||
__attribute__((fallthrough, fallthrough)); /* { dg-warning "attribute specified multiple times" } */
|
||||
case 8:
|
||||
bar (1);
|
||||
__attribute__((fallthrough));
|
||||
case 9:
|
||||
__attribute__((fallthrough));
|
||||
/* { dg-warning "not preceding" "" { target *-*-* } 42 } */
|
||||
bar (1);
|
||||
case 10:
|
||||
bar (1);
|
||||
__attribute__((unused, fallthrough)); /* { dg-warning "attribute ignored" } */
|
||||
case 11:
|
||||
bar (1);
|
||||
__attribute__((fallthrough, unused)); /* { dg-warning "attribute ignored" } */
|
||||
default:
|
||||
bar (99);
|
||||
}
|
||||
}
|
57
gcc/testsuite/g++.dg/cpp0x/fallthrough1.C
Normal file
57
gcc/testsuite/g++.dg/cpp0x/fallthrough1.C
Normal file
@ -0,0 +1,57 @@
|
||||
// PR c/7652
|
||||
// { dg-do compile { target c++11 } }
|
||||
// { dg-options "-Wextra -Wall -Wpedantic" }
|
||||
|
||||
extern void bar (int);
|
||||
void
|
||||
fn (int i)
|
||||
{
|
||||
[[gnu::fallthrough]] int j = 0; // { dg-warning "attribute ignored" }
|
||||
|
||||
if (j)
|
||||
[[gnu::fallthrough]]; // { dg-error "invalid use" }
|
||||
|
||||
[[gnu::fallthrough]]; // { dg-error "invalid use" }
|
||||
switch (i)
|
||||
{
|
||||
[[gnu::fallthrough]]; // { dg-warning "statement will never" }
|
||||
case 1:
|
||||
i++;
|
||||
[[gnu::fallthrough]];
|
||||
case 2:
|
||||
if (i) // { dg-warning "statement may fall through" }
|
||||
bar (2);
|
||||
else
|
||||
[[gnu::fallthrough]];
|
||||
case 3:
|
||||
if (i > 1)
|
||||
[[gnu::fallthrough]];
|
||||
else
|
||||
return;
|
||||
case 4:
|
||||
if (i)
|
||||
[[gnu::fallthrough]]; // { dg-warning "not preceding" }
|
||||
[[gnu::fallthrough]];
|
||||
case 5:
|
||||
;
|
||||
[[gnu::fallthrough]];
|
||||
case 6:
|
||||
if (i) // { dg-warning "statement may fall through" }
|
||||
bar (6);
|
||||
else
|
||||
{
|
||||
[[gnu::fallthrough]];
|
||||
}
|
||||
case 7:
|
||||
if (i > 1)
|
||||
{
|
||||
[[gnu::fallthrough]];
|
||||
}
|
||||
else
|
||||
bar (7); // { dg-warning "statement may fall through" }
|
||||
default:
|
||||
--j;
|
||||
}
|
||||
|
||||
[[gnu::fallthrough]]; // { dg-error "invalid use" }
|
||||
}
|
21
gcc/testsuite/g++.dg/cpp0x/fallthrough2.C
Normal file
21
gcc/testsuite/g++.dg/cpp0x/fallthrough2.C
Normal file
@ -0,0 +1,21 @@
|
||||
// PR c/7652
|
||||
// { dg-do compile { target c++11 } }
|
||||
// { dg-options "-Wextra -Wall -Wpedantic" }
|
||||
|
||||
extern void bar (int);
|
||||
|
||||
void
|
||||
f (int i)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
bar (1);
|
||||
[[fallthrough]]; // { dg-warning ".fallthrough. is a C\\+\\+17 feature" }
|
||||
case 3:
|
||||
bar (1);
|
||||
[[gnu::fallthrough, gnu::fallthrough]]; // { dg-warning ".fallthrough. attribute specified multiple times" }
|
||||
case 2:
|
||||
bar (2);
|
||||
}
|
||||
}
|
20
gcc/testsuite/g++.dg/cpp1z/fallthrough1.C
Normal file
20
gcc/testsuite/g++.dg/cpp1z/fallthrough1.C
Normal file
@ -0,0 +1,20 @@
|
||||
// PR c/7652
|
||||
// { dg-do compile }
|
||||
// { dg-options "-std=c++1z -Wextra -Wall -Wpedantic" }
|
||||
|
||||
// Check that we accept attribute [[fallthrough]].
|
||||
|
||||
extern void bar (int);
|
||||
|
||||
void
|
||||
f (int i)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
bar (1);
|
||||
[[fallthrough]];
|
||||
case 2:
|
||||
bar (2);
|
||||
}
|
||||
}
|
@ -21,7 +21,7 @@ void
|
||||
f3()
|
||||
{
|
||||
// The next line would be OK in C but is a syntax error in C++.
|
||||
l2: __attribute__ ((unused)) f9(); // { dg-error "expected" }
|
||||
l2: __attribute__ ((unused)) f9(); // { dg-warning "ignored" }
|
||||
// We still get an unused label warning--this is
|
||||
// optional and can be removed if it ever changes.
|
||||
// { dg-warning "not used" "expected" { target *-*-* } 24 }
|
||||
|
22
gcc/testsuite/gcc.dg/Wimplicit-fallthrough-1.c
Normal file
22
gcc/testsuite/gcc.dg/Wimplicit-fallthrough-1.c
Normal file
@ -0,0 +1,22 @@
|
||||
/* PR c/7652 */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-Wimplicit-fallthrough -Wdeclaration-after-statement" } */
|
||||
|
||||
/* Test we don't print bogus "mixed declarations and code" warning. */
|
||||
|
||||
int
|
||||
f (int b)
|
||||
{
|
||||
switch (b)
|
||||
{
|
||||
case 0:
|
||||
b++;
|
||||
__attribute__((fallthrough));
|
||||
case 1:
|
||||
b--;
|
||||
__attribute__((unused)) int a; /* { dg-warning "mixed declarations and code" } */
|
||||
case 2:
|
||||
break;
|
||||
}
|
||||
return 99;
|
||||
}
|
38
gcc/testsuite/obj-c++.dg/Wimplicit-fallthrough-1.mm
Normal file
38
gcc/testsuite/obj-c++.dg/Wimplicit-fallthrough-1.mm
Normal file
@ -0,0 +1,38 @@
|
||||
/* PR c/7652 */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-Wimplicit-fallthrough" } */
|
||||
/* Test taken from
|
||||
<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0188r0.pdf>. */
|
||||
|
||||
extern void f (int);
|
||||
|
||||
void
|
||||
foo (int n)
|
||||
{
|
||||
switch (n)
|
||||
{
|
||||
case 22:
|
||||
case 33:
|
||||
f (1); /* { dg-warning "statement may fall through" } */
|
||||
case 44:
|
||||
f (2);
|
||||
__attribute__((fallthrough));
|
||||
case 55:
|
||||
if (n > 10)
|
||||
{
|
||||
f (3);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
f (4);
|
||||
__attribute__((fallthrough));
|
||||
}
|
||||
case 66:
|
||||
f (5);
|
||||
__attribute__((fallthrough)); /* { dg-warning "not preceding" } */
|
||||
f (6); /* { dg-warning "statement may fall through" } */
|
||||
case 77:
|
||||
f (7);
|
||||
}
|
||||
}
|
38
gcc/testsuite/objc.dg/Wimplicit-fallthrough-1.m
Normal file
38
gcc/testsuite/objc.dg/Wimplicit-fallthrough-1.m
Normal file
@ -0,0 +1,38 @@
|
||||
/* PR c/7652 */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-Wimplicit-fallthrough" } */
|
||||
/* Test taken from
|
||||
<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0188r0.pdf>. */
|
||||
|
||||
extern void f (int);
|
||||
|
||||
void
|
||||
foo (int n)
|
||||
{
|
||||
switch (n)
|
||||
{
|
||||
case 22:
|
||||
case 33:
|
||||
f (1); /* { dg-warning "statement may fall through" } */
|
||||
case 44:
|
||||
f (2);
|
||||
__attribute__((fallthrough));
|
||||
case 55:
|
||||
if (n > 10)
|
||||
{
|
||||
f (3);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
f (4);
|
||||
__attribute__((fallthrough));
|
||||
}
|
||||
case 66:
|
||||
f (5);
|
||||
__attribute__((fallthrough)); /* { dg-warning "not preceding" } */
|
||||
f (6); /* { dg-warning "statement may fall through" } */
|
||||
case 77:
|
||||
f (7);
|
||||
}
|
||||
}
|
@ -1077,6 +1077,9 @@ struct GTY(()) tree_base {
|
||||
TRANSACTION_EXPR_RELAXED in
|
||||
TRANSACTION_EXPR
|
||||
|
||||
FALLTHROUGH_LABEL_P in
|
||||
LABEL_DECL
|
||||
|
||||
private_flag:
|
||||
|
||||
TREE_PRIVATE in
|
||||
|
@ -1885,8 +1885,8 @@ find_deriving_biv_for_expr (struct ivopts_data *data, tree expr)
|
||||
iv = find_deriving_biv_for_expr (data, e2);
|
||||
if (iv)
|
||||
return iv;
|
||||
gcc_fallthrough ();
|
||||
|
||||
/* Fallthru. */
|
||||
CASE_CONVERT:
|
||||
/* Casts are simple. */
|
||||
return find_deriving_biv_for_expr (data, e1);
|
||||
|
@ -774,6 +774,11 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
|
||||
computed gotos. */
|
||||
#define FORCED_LABEL(NODE) (LABEL_DECL_CHECK (NODE)->base.side_effects_flag)
|
||||
|
||||
/* Whether a case or a user-defined label is allowed to fall through to.
|
||||
This is used to implement -Wimplicit-fallthrough. */
|
||||
#define FALLTHROUGH_LABEL_P(NODE) \
|
||||
(LABEL_DECL_CHECK (NODE)->base.public_flag)
|
||||
|
||||
/* Nonzero means this expression is volatile in the C sense:
|
||||
its address should be of type `volatile WHATEVER *'.
|
||||
In other words, the declared item is volatile qualified.
|
||||
|
@ -4173,7 +4173,7 @@ output_addressed_constants (tree exp)
|
||||
case POINTER_PLUS_EXPR:
|
||||
case MINUS_EXPR:
|
||||
output_addressed_constants (TREE_OPERAND (exp, 1));
|
||||
/* Fall through. */
|
||||
gcc_fallthrough ();
|
||||
|
||||
CASE_CONVERT:
|
||||
case VIEW_CONVERT_EXPR:
|
||||
|
@ -1,3 +1,13 @@
|
||||
2016-09-26 Marek Polacek <polacek@redhat.com>
|
||||
Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR c/7652
|
||||
* include/cpplib.h (PREV_FALLTHROUGH): Define.
|
||||
* internal.h (CPP_FALLTHRU): Define.
|
||||
* lex.c (fallthrough_comment_p): New function.
|
||||
(_cpp_lex_direct): Set PREV_FALLTHROUGH on tokens succeeding a falls
|
||||
through comment.
|
||||
|
||||
2016-09-23 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
PR preprocessor/77672
|
||||
|
@ -185,7 +185,8 @@ struct GTY(()) cpp_string {
|
||||
#define STRINGIFY_ARG (1 << 2) /* If macro argument to be stringified. */
|
||||
#define PASTE_LEFT (1 << 3) /* If on LHS of a ## operator. */
|
||||
#define NAMED_OP (1 << 4) /* C++ named operators. */
|
||||
#define NO_EXPAND (1 << 5) /* Do not macro-expand this token. */
|
||||
#define PREV_FALLTHROUGH (1 << 5) /* On a token preceeded by FALLTHROUGH
|
||||
comment. */
|
||||
#define BOL (1 << 6) /* Token at beginning of line. */
|
||||
#define PURE_ZERO (1 << 7) /* Single 0 digit, used by the C++ frontend,
|
||||
set in c-lex.c. */
|
||||
@ -193,6 +194,7 @@ struct GTY(()) cpp_string {
|
||||
#define SP_PREV_WHITE (1 << 9) /* If whitespace before a ##
|
||||
operator, or before this token
|
||||
after a # operator. */
|
||||
#define NO_EXPAND (1 << 10) /* Do not macro-expand this token. */
|
||||
|
||||
/* Specify which field, if any, of the cpp_token union is used. */
|
||||
|
||||
|
100
libcpp/lex.c
100
libcpp/lex.c
@ -2032,6 +2032,94 @@ save_comment (cpp_reader *pfile, cpp_token *token, const unsigned char *from,
|
||||
store_comment (pfile, token);
|
||||
}
|
||||
|
||||
/* Returns true if comment at COMMENT_START is a recognized FALLTHROUGH
|
||||
comment. */
|
||||
|
||||
static bool
|
||||
fallthrough_comment_p (cpp_reader *pfile, const unsigned char *comment_start)
|
||||
{
|
||||
const unsigned char *from = comment_start + 1;
|
||||
/* Whole comment contents:
|
||||
-fallthrough
|
||||
@fallthrough@
|
||||
*/
|
||||
if (*from == '-' || *from == '@')
|
||||
{
|
||||
size_t len = sizeof "fallthrough" - 1;
|
||||
if ((size_t) (pfile->buffer->cur - from - 1) < len)
|
||||
return false;
|
||||
if (memcmp (from + 1, "fallthrough", len))
|
||||
return false;
|
||||
if (*from == '@')
|
||||
{
|
||||
if (from[len + 1] != '@')
|
||||
return false;
|
||||
len++;
|
||||
}
|
||||
from += 1 + len;
|
||||
}
|
||||
/* Whole comment contents (regex):
|
||||
[ \t]*FALL(S | |-)?THR(OUGH|U)\.?[ \t]*
|
||||
[ \t]*Fall(s | |-)?[Tt]hr(ough|u)\.?[ \t]*
|
||||
[ \t]*fall(s | |-)?thr(ough|u)\.?[ \t]*
|
||||
*/
|
||||
else
|
||||
{
|
||||
while (*from == ' ' || *from == '\t')
|
||||
from++;
|
||||
unsigned char f = *from;
|
||||
if (f != 'F' && f != 'f')
|
||||
return false;
|
||||
if ((size_t) (pfile->buffer->cur - from) < sizeof "fallthrough")
|
||||
return false;
|
||||
bool all_upper = false;
|
||||
if (f == 'F' && memcmp (from + 1, "ALL", sizeof "ALL" - 1) == 0)
|
||||
all_upper = true;
|
||||
else if (memcmp (from + 1, "all", sizeof "all" - 1))
|
||||
return false;
|
||||
if (from[sizeof "fall" - 1] == (all_upper ? 'S' : 's')
|
||||
&& from[sizeof "falls" - 1] == ' ')
|
||||
from += sizeof "falls " - 1;
|
||||
else if (from[sizeof "fall" - 1] == ' '
|
||||
|| from[sizeof "fall" - 1] == '-')
|
||||
from += sizeof "fall " - 1;
|
||||
else if (from[sizeof "fall" - 1] != (all_upper ? 'T' : 't'))
|
||||
return false;
|
||||
else
|
||||
from += sizeof "fall" - 1;
|
||||
if ((f == 'f' || *from != 'T') && (all_upper || *from != 't'))
|
||||
return false;
|
||||
if ((size_t) (pfile->buffer->cur - from) < sizeof "thru")
|
||||
return false;
|
||||
if (memcmp (from + 1, all_upper ? "HRU" : "hru", sizeof "hru" - 1))
|
||||
{
|
||||
if ((size_t) (pfile->buffer->cur - from) < sizeof "through")
|
||||
return false;
|
||||
if (memcmp (from + 1, all_upper ? "HROUGH" : "hrough",
|
||||
sizeof "hrough" - 1))
|
||||
return false;
|
||||
from += sizeof "through" - 1;
|
||||
}
|
||||
else
|
||||
from += sizeof "thru" - 1;
|
||||
if (*from == '.')
|
||||
from++;
|
||||
while (*from == ' ' || *from == '\t')
|
||||
from++;
|
||||
}
|
||||
/* C block comment. */
|
||||
if (*comment_start == '*')
|
||||
{
|
||||
if (*from != '*' || from[1] != '/')
|
||||
return false;
|
||||
}
|
||||
/* C++ line comment. */
|
||||
else if (*from != '\n')
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Allocate COUNT tokens for RUN. */
|
||||
void
|
||||
_cpp_init_tokenrun (tokenrun *run, unsigned int count)
|
||||
@ -2310,7 +2398,7 @@ _cpp_lex_direct (cpp_reader *pfile)
|
||||
{
|
||||
cppchar_t c;
|
||||
cpp_buffer *buffer;
|
||||
const unsigned char *comment_start;
|
||||
const unsigned char *comment_start = NULL;
|
||||
cpp_token *result = pfile->cur_token++;
|
||||
|
||||
fresh_line:
|
||||
@ -2337,6 +2425,8 @@ _cpp_lex_direct (cpp_reader *pfile)
|
||||
}
|
||||
return result;
|
||||
}
|
||||
if (buffer != pfile->buffer)
|
||||
comment_start = NULL;
|
||||
if (!pfile->keep_tokens)
|
||||
{
|
||||
pfile->cur_run = &pfile->base_run;
|
||||
@ -2443,6 +2533,11 @@ _cpp_lex_direct (cpp_reader *pfile)
|
||||
result->flags |= NAMED_OP;
|
||||
result->type = (enum cpp_ttype) result->val.node.node->directive_index;
|
||||
}
|
||||
|
||||
/* Signal FALLTHROUGH comment followed by another token. */
|
||||
if (comment_start
|
||||
&& fallthrough_comment_p (pfile, comment_start))
|
||||
result->flags |= PREV_FALLTHROUGH;
|
||||
break;
|
||||
|
||||
case '\'':
|
||||
@ -2534,6 +2629,9 @@ _cpp_lex_direct (cpp_reader *pfile)
|
||||
goto update_tokens_line;
|
||||
}
|
||||
|
||||
if (fallthrough_comment_p (pfile, comment_start))
|
||||
result->flags |= PREV_FALLTHROUGH;
|
||||
|
||||
/* Save the comment as a token in its own right. */
|
||||
save_comment (pfile, result, comment_start, c);
|
||||
break;
|
||||
|
@ -1,3 +1,8 @@
|
||||
2016-09-26 Marek Polacek <polacek@redhat.com>
|
||||
|
||||
PR c/7652
|
||||
* libsupc++/hash_bytes.cc: Add [[gnu::fallthrough]].
|
||||
|
||||
2016-09-25 François Dumont <fdumont@gcc.gnu.org>
|
||||
|
||||
* src/c++11/debug.cc: Include debug/vector. Include cctype. Remove
|
||||
|
@ -95,8 +95,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
{
|
||||
case 3:
|
||||
hash ^= static_cast<unsigned char>(buf[2]) << 16;
|
||||
[[gnu::fallthrough]];
|
||||
case 2:
|
||||
hash ^= static_cast<unsigned char>(buf[1]) << 8;
|
||||
[[gnu::fallthrough]];
|
||||
case 1:
|
||||
hash ^= static_cast<unsigned char>(buf[0]);
|
||||
hash *= m;
|
||||
|
Loading…
Reference in New Issue
Block a user