Bootstrapped/regtested on x86_64-linux, ok for trunk? 2019-07-08 Matthew Beliveau PR c++/90590 * c-warn.c (c_do_switch_warnings): Suppress warning for enumerators with reserved names that are in a system header. * c-c++-common/pr90590-1.c: New test. * c-c++-common/pr90590-1.h: New test. * c-c++-common/pr90590-2.c: New test. * c-c++-common/pr90590-2.h: New test. diff --git gcc/c-family/c-warn.c gcc/c-family/c-warn.c index b5d09e761d7..56ad23dd29c 100644 --- gcc/c-family/c-warn.c +++ gcc/c-family/c-warn.c @@ -34,6 +34,7 @@ along with GCC; see the file COPYING3. If not see #include "gcc-rich-location.h" #include "gimplify.h" #include "c-family/c-indentation.h" +#include "c-family/c-spellcheck.h" #include "calls.h" #include "stor-layout.h" @@ -1592,8 +1593,12 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location, for (chain = TYPE_VALUES (type); chain; chain = TREE_CHAIN (chain)) { tree value = TREE_VALUE (chain); + tree decl = NULL_TREE; if (TREE_CODE (value) == CONST_DECL) - value = DECL_INITIAL (value); + { + decl = value; + value = DECL_INITIAL (value); + } node = splay_tree_lookup (cases, (splay_tree_key) value); if (node) { @@ -1628,6 +1633,19 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location, if (cond && tree_int_cst_compare (cond, value)) continue; + /* If the enumerator is defined in a system header and uses a reserved + name, then we continue to avoid throwing a warning. */ + if (decl == NULL_TREE) + decl = lookup_name (TREE_PURPOSE (chain)); + if (decl && TREE_CODE (decl) == CONST_DECL) + { + const char *name = IDENTIFIER_POINTER (DECL_NAME (decl)); + location_t loc = DECL_SOURCE_LOCATION (decl); + if (in_system_header_at (loc) + && name_reserved_for_implementation_p (name)) + continue; + } + /* If there is a default_node, the only relevant option is Wswitch-enum. Otherwise, if both are enabled then we prefer to warn using -Wswitch because -Wswitch is enabled by -Wall diff --git gcc/testsuite/c-c++-common/pr90590-1.c gcc/testsuite/c-c++-common/pr90590-1.c new file mode 100644 index 00000000000..4997a3082d5 --- /dev/null +++ gcc/testsuite/c-c++-common/pr90590-1.c @@ -0,0 +1,15 @@ +// PR c++/90590 +// { dg-options -Wswitch } +#include "pr90590-1.h" + +void +g () +{ + enum E e = _A; + switch (e) // { dg-bogus "enumeration value '_C' not handled in switch" } + { + case _A: + case _B: + break; + } +} diff --git gcc/testsuite/c-c++-common/pr90590-1.h gcc/testsuite/c-c++-common/pr90590-1.h new file mode 100644 index 00000000000..22f1a7d5d52 --- /dev/null +++ gcc/testsuite/c-c++-common/pr90590-1.h @@ -0,0 +1,2 @@ +#pragma GCC system_header +enum E { _A, _B, _C }; diff --git gcc/testsuite/c-c++-common/pr90590-2.c gcc/testsuite/c-c++-common/pr90590-2.c new file mode 100644 index 00000000000..8aa65cf0afd --- /dev/null +++ gcc/testsuite/c-c++-common/pr90590-2.c @@ -0,0 +1,8 @@ +#include "pr90590-2.h" + +void +fn () +{ + switch (c.b) // { dg-bogus "enumeration value" } + ; +} diff --git gcc/testsuite/c-c++-common/pr90590-2.h gcc/testsuite/c-c++-common/pr90590-2.h new file mode 100644 index 00000000000..e4f8635576f --- /dev/null +++ gcc/testsuite/c-c++-common/pr90590-2.h @@ -0,0 +1,4 @@ +#pragma GCC system_header +struct { + enum { _A } b; +} c;