From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 8189 invoked by alias); 23 Sep 2014 17:42:45 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 8179 invoked by uid 89); 23 Sep 2014 17:42:45 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-3.0 required=5.0 tests=AWL,BAYES_00,RP_MATCHES_RCVD,SPF_HELO_PASS,SPF_PASS autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Tue, 23 Sep 2014 17:42:43 +0000 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s8NHgejm016318 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 23 Sep 2014 13:42:40 -0400 Received: from redhat.com (ovpn-116-32.ams2.redhat.com [10.36.116.32]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s8NHganL001156 (version=TLSv1/SSLv3 cipher=AES128-GCM-SHA256 bits=128 verify=NO); Tue, 23 Sep 2014 13:42:38 -0400 Date: Tue, 23 Sep 2014 17:42:00 -0000 From: Marek Polacek To: Jason Merrill Cc: GCC Patches , "Joseph S. Myers" , Jakub Jelinek , Jan Hubicka Subject: Re: [C/C++ PATCH] Handle enum bit-fields for -Wswitch (PR c/61405, PR c/53874) Message-ID: <20140923174235.GL743@redhat.com> References: <20140919132944.GA743@redhat.com> <541C867B.8050802@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <541C867B.8050802@redhat.com> User-Agent: Mutt/1.5.23 (2014-03-12) X-SW-Source: 2014-09/txt/msg02006.txt.bz2 On Fri, Sep 19, 2014 at 03:39:39PM -0400, Jason Merrill wrote: > On 09/19/2014 09:29 AM, Marek Polacek wrote: > >But we also started to warn on > >CPP_KEYWORD and two others: "case value not in enumerated type". > >Fixed by moving CPP_KEYWORD, CPP_TEMPLATE_ID, and CPP_NESTED_NAME_SPECIFIER > >into enum cpp_ttype. Not sure if this is going to hurt something else. > > Wait, -Wswitch warns if any of the case labels don't correspond to > enumerators? Apparently so, it complains about Yeah. > enum E { a=1,b=2,c=4 } e; > > int main() > { > switch (e) > { > case a|b: break; > default: break; > } > } > > That seems bogus. The docs say, > > "'case' labels outside the enumeration range also provoke warnings when this > option is used (even if there is a 'default' label)." > > but 3 is within the range 1-4. Note that even if we allowed this (don't warn if case value is within the range of an enum), this wouldn't help with the CPP_KEYWORD, since CPP_KEYWORD is outside the range of cpp_ttype enum values. > If this is working as intended, I'm still uneasy about moving the C++ > internal token types into libcpp; instead, I think I'd prefer to work around > the warning by suppressing -Wswitch inside affected functions or moving the > cases to ifs. I still hope we can move the CPP_KEYWORD - that is not C++ only thing; the C FE parser uses that as well (and defined it). I suppressed the warnings just by casting the controlling expression of the switch to an int (two spots, not that bad). How does this look now? Bootstrapped/regtested on x86_64-linux, ok for trunk? 2014-09-23 Marek Polacek PR c/61405 PR c/53874 gcc/ * asan.c (maybe_instrument_call): Add default case. * ipa-pure-const.c (special_builtin_state): Likewise. * predict.c (expr_expected_value_1): Likewise. * lto-streamer-out.c (write_symbol): Initialize variable. gcc/c-family/ * c-common.h (struct c_common_resword): Don't define CPP_KEYWORD. gcc/c/ * c-parser.c: Don't define CPP_KEYWORD. (c_parser_switch_statement): Pass original type to c_finish_case. * c-tree.h (c_finish_case): Update declaration. * c-typeck.c (c_finish_case): Add TYPE parameter. Pass it conditionally to c_do_switch_warnings. gcc/cp/ * semantics.c (finish_switch_cond): Call unlowered_expr_type. * tree.c (bot_manip): Add default case. * parser.c (cp_parser_primary_expression): Cast the controlling expression of a switch to an int. (cp_parser_unqualified_id): Likewise. gcc/testsuite/ * c-c++-common/pr53874.c: New test. * c-c++-common/pr61405.c: New test. libcpp/ * include/cpplib.h (enum cpp_ttype): Define CPP_KEYWORD. diff --git gcc/gcc/asan.c gcc/gcc/asan.c index 2a90d86..bca95df 100644 --- gcc/gcc/asan.c +++ gcc/gcc/asan.c @@ -2024,6 +2024,8 @@ maybe_instrument_call (gimple_stmt_iterator *iter) case BUILT_IN_TRAP: /* Don't instrument these. */ return false; + default: + break; } } tree decl = builtin_decl_implicit (BUILT_IN_ASAN_HANDLE_NO_RETURN); diff --git gcc/gcc/c-family/c-common.h gcc/gcc/c-family/c-common.h index 993a97b..5ec79a0 100644 --- gcc/gcc/c-family/c-common.h +++ gcc/gcc/c-family/c-common.h @@ -327,9 +327,6 @@ struct c_common_resword /* Extra cpp_ttype values for C++. */ -/* A token type for keywords, as opposed to ordinary identifiers. */ -#define CPP_KEYWORD ((enum cpp_ttype) (N_TTYPES + 1)) - /* A token type for template-ids. If a template-id is processed while parsing tentatively, it is replaced with a CPP_TEMPLATE_ID token; the value of the CPP_TEMPLATE_ID is whatever was returned by diff --git gcc/gcc/c/c-parser.c gcc/gcc/c/c-parser.c index 3f4a92b..71f40b7 100644 --- gcc/gcc/c/c-parser.c +++ gcc/gcc/c/c-parser.c @@ -126,11 +126,6 @@ c_parse_init (void) C++). It would then be possible to share more of the C and C++ lexer code, if desired. */ -/* The following local token type is used. */ - -/* A keyword. */ -#define CPP_KEYWORD ((enum cpp_ttype) (N_TTYPES + 1)) - /* More information about the type of a CPP_NAME token. */ typedef enum c_id_kind { /* An ordinary identifier. */ @@ -5232,7 +5227,7 @@ c_parser_switch_statement (c_parser *parser) save_break = c_break_label; c_break_label = NULL_TREE; body = c_parser_c99_block_statement (parser); - c_finish_case (body); + c_finish_case (body, ce.original_type); if (c_break_label) { location_t here = c_parser_peek_token (parser)->location; diff --git gcc/gcc/c/c-tree.h gcc/gcc/c/c-tree.h index 6004d50..fc145a85 100644 --- gcc/gcc/c/c-tree.h +++ gcc/gcc/c/c-tree.h @@ -618,7 +618,7 @@ extern void process_init_element (location_t, struct c_expr, bool, extern tree build_compound_literal (location_t, tree, tree, bool); extern void check_compound_literal_type (location_t, struct c_type_name *); extern tree c_start_case (location_t, location_t, tree, bool); -extern void c_finish_case (tree); +extern void c_finish_case (tree, tree); extern tree build_asm_expr (location_t, tree, tree, tree, tree, tree, bool); extern tree build_asm_stmt (tree, tree); extern int c_types_compatible_p (tree, tree); diff --git gcc/gcc/c/c-typeck.c gcc/gcc/c/c-typeck.c index da71ab2..f69c28b 100644 --- gcc/gcc/c/c-typeck.c +++ gcc/gcc/c/c-typeck.c @@ -9486,10 +9486,11 @@ do_case (location_t loc, tree low_value, tree high_value) return label; } -/* Finish the switch statement. */ +/* Finish the switch statement. TYPE is the original type of the + controlling expression of the switch, or NULL_TREE. */ void -c_finish_case (tree body) +c_finish_case (tree body, tree type) { struct c_switch *cs = c_switch_stack; location_t switch_location; @@ -9499,7 +9500,7 @@ c_finish_case (tree body) /* Emit warnings as needed. */ switch_location = EXPR_LOCATION (cs->switch_expr); c_do_switch_warnings (cs->cases, switch_location, - TREE_TYPE (cs->switch_expr), + type ? type : TREE_TYPE (cs->switch_expr), SWITCH_COND (cs->switch_expr)); /* Pop the stack. */ diff --git gcc/gcc/cp/parser.c gcc/gcc/cp/parser.c index 9764794..0c2acbe 100644 --- gcc/gcc/cp/parser.c +++ gcc/gcc/cp/parser.c @@ -4172,7 +4172,7 @@ cp_parser_primary_expression (cp_parser *parser, /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); - switch (token->type) + switch ((int) token->type) { /* literal: integer-literal @@ -4858,7 +4858,7 @@ cp_parser_unqualified_id (cp_parser* parser, /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); - switch (token->type) + switch ((int) token->type) { case CPP_NAME: { diff --git gcc/gcc/cp/semantics.c gcc/gcc/cp/semantics.c index 6e04e5e..2728f58 100644 --- gcc/gcc/cp/semantics.c +++ gcc/gcc/cp/semantics.c @@ -1127,7 +1127,8 @@ finish_switch_cond (tree cond, tree switch_stmt) error ("switch quantity not an integer"); cond = error_mark_node; } - orig_type = TREE_TYPE (cond); + /* We want unlowered type here to handle enum bit-fields. */ + orig_type = unlowered_expr_type (cond); if (cond != error_mark_node) { /* Warn if the condition has boolean value. */ diff --git gcc/gcc/cp/tree.c gcc/gcc/cp/tree.c index d0e1180..a7bb38b 100644 --- gcc/gcc/cp/tree.c +++ gcc/gcc/cp/tree.c @@ -2345,6 +2345,8 @@ bot_manip (tree* tp, int* walk_subtrees, void* data) case BUILT_IN_FILE: case BUILT_IN_LINE: SET_EXPR_LOCATION (*tp, input_location); + default: + break; } } return t; diff --git gcc/gcc/ipa-pure-const.c gcc/gcc/ipa-pure-const.c index 459d08d..b5ded3e 100644 --- gcc/gcc/ipa-pure-const.c +++ gcc/gcc/ipa-pure-const.c @@ -451,6 +451,8 @@ special_builtin_state (enum pure_const_state_e *state, bool *looping, *looping = true; *state = IPA_CONST; return true; + default: + break; } return false; } diff --git gcc/gcc/lto-streamer-out.c gcc/gcc/lto-streamer-out.c index b516c7b..cff48ee 100644 --- gcc/gcc/lto-streamer-out.c +++ gcc/gcc/lto-streamer-out.c @@ -2422,7 +2422,7 @@ write_symbol (struct streamer_tree_cache_d *cache, { const char *name; enum gcc_plugin_symbol_kind kind; - enum gcc_plugin_symbol_visibility visibility; + enum gcc_plugin_symbol_visibility visibility = GCCPV_DEFAULT; unsigned slot_num; uint64_t size; const char *comdat; diff --git gcc/gcc/predict.c gcc/gcc/predict.c index 56e45d9..b5556db 100644 --- gcc/gcc/predict.c +++ gcc/gcc/predict.c @@ -1902,6 +1902,8 @@ expr_expected_value_1 (tree type, tree op0, enum tree_code code, if (predictor) *predictor = PRED_COMPARE_AND_SWAP; return boolean_true_node; + default: + break; } } diff --git gcc/gcc/testsuite/c-c++-common/pr53874.c gcc/gcc/testsuite/c-c++-common/pr53874.c index e69de29..153f997 100644 --- gcc/gcc/testsuite/c-c++-common/pr53874.c +++ gcc/gcc/testsuite/c-c++-common/pr53874.c @@ -0,0 +1,35 @@ +/* PR c/53874 */ +/* { dg-do compile } */ +/* { dg-options "-Wswitch-enum" } */ + +enum E { A, B, C }; +struct S { enum E e:2; }; +typedef struct S TS; + +int +fn0 (struct S *s) +{ + switch (s->e) /* { dg-warning "enumeration value .C. not handled in switch" } */ + { + case A: + return 1; + case B: + return 2; + default: + return 0; + } +} + +int +fn1 (TS *s) +{ + switch (s->e) /* { dg-warning "enumeration value .C. not handled in switch" } */ + { + case A: + return 1; + case B: + return 2; + default: + return 0; + } +} diff --git gcc/gcc/testsuite/c-c++-common/pr61405.c gcc/gcc/testsuite/c-c++-common/pr61405.c index e69de29..9c05a84 100644 --- gcc/gcc/testsuite/c-c++-common/pr61405.c +++ gcc/gcc/testsuite/c-c++-common/pr61405.c @@ -0,0 +1,31 @@ +/* PR c/61405 */ +/* { dg-do compile } */ +/* { dg-options "-Wswitch" } */ + +enum E { A, B, C }; +struct S { enum E e:2; }; +typedef struct S TS; + +int +fn0 (struct S *s) +{ + switch (s->e) /* { dg-warning "enumeration value .C. not handled in switch" } */ + { + case A: + return 1; + case B: + return 2; + } +} + +int +fn1 (TS *s) +{ + switch (s->e) /* { dg-warning "enumeration value .C. not handled in switch" } */ + { + case A: + return 1; + case B: + return 2; + } +} diff --git gcc/libcpp/include/cpplib.h gcc/libcpp/include/cpplib.h index 62d271b..06d18d4 100644 --- gcc/libcpp/include/cpplib.h +++ gcc/libcpp/include/cpplib.h @@ -153,6 +153,9 @@ enum cpp_ttype TTYPE_TABLE N_TTYPES, + /* A token type for keywords, as opposed to ordinary identifiers. */ + CPP_KEYWORD, + /* Positions in the table. */ CPP_LAST_EQ = CPP_LSHIFT, CPP_FIRST_DIGRAPH = CPP_HASH, Marek