PR c/81544 complaints that we aren't detecting clashing noreturn / warn_unused_result attributes so this patch adds that checking. Martin plans to do more systematic checking in this area but meanwhile we might want to go with this.
Bootstrapped/regtested on x86_64-linux, ok for trunk? 2017-07-25 Marek Polacek <pola...@redhat.com> PR c/81544 * c-common.h (diagnose_mismatched_attributes): Update decl. * c-warn.c (diagnose_mismatched_attributes): Add OLDTYPE and NEWTYPE parameters. Diagnose clashing noreturn / warn_unused_result attributes. * c-decl.c (diagnose_mismatched_decls): Pass OLDTYPE and NEWTYPE down to diagnose_mismatched_attributes. * decl.c (duplicate_decls): Pass the types of OLDDECL and NEWDECL down to diagnose_mismatched_attributes. * c-c++-common/attributes-4.c: New test. diff --git gcc/c-family/c-common.h gcc/c-family/c-common.h index a29f1ade25d..7c4b2a0e108 100644 --- gcc/c-family/c-common.h +++ gcc/c-family/c-common.h @@ -1537,7 +1537,7 @@ extern void maybe_warn_unused_local_typedefs (void); extern void maybe_warn_bool_compare (location_t, enum tree_code, tree, tree); extern bool maybe_warn_shift_overflow (location_t, tree, tree); extern void warn_duplicated_cond_add_or_warn (location_t, tree, vec<tree> **); -extern bool diagnose_mismatched_attributes (tree, tree); +extern bool diagnose_mismatched_attributes (tree, tree, tree, tree); extern tree do_warn_duplicated_branches_r (tree *, int *, void *); extern void warn_for_multistatement_macros (location_t, location_t, location_t, enum rid); diff --git gcc/c-family/c-warn.c gcc/c-family/c-warn.c index a8b38c1b98d..d3c62a5ad9e 100644 --- gcc/c-family/c-warn.c +++ gcc/c-family/c-warn.c @@ -2125,7 +2125,8 @@ warn_duplicated_cond_add_or_warn (location_t loc, tree cond, vec<tree> **chain) attributes, such as always_inline vs. noinline. */ bool -diagnose_mismatched_attributes (tree olddecl, tree newdecl) +diagnose_mismatched_attributes (tree olddecl, tree newdecl, tree oldtype, + tree newtype) { bool warned = false; @@ -2172,6 +2173,17 @@ diagnose_mismatched_attributes (tree olddecl, tree newdecl) warned |= warning (OPT_Wattributes, "declaration of %q+D with attribute " "%qs follows declaration with attribute %qs", newdecl, "hot", "cold"); + else if (lookup_attribute ("noreturn", DECL_ATTRIBUTES (newdecl)) + && lookup_attribute ("warn_unused_result", + TYPE_ATTRIBUTES (oldtype))) + warned |= warning (OPT_Wattributes, "declaration of %q+D with attribute " + "%qs follows declaration with attribute %qs", + newdecl, "noreturn", "warn_unused_result"); + else if (lookup_attribute ("warn_unused_result", TYPE_ATTRIBUTES (newtype)) + && lookup_attribute ("noreturn", DECL_ATTRIBUTES (olddecl))) + warned |= warning (OPT_Wattributes, "declaration of %q+D with attribute " + "%qs follows declaration with attribute %qs", + newdecl, "warn_unused_result", "noreturn"); return warned; } diff --git gcc/c/c-decl.c gcc/c/c-decl.c index 12fbc18bb94..e995606499f 100644 --- gcc/c/c-decl.c +++ gcc/c/c-decl.c @@ -2234,7 +2234,8 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, } if (TREE_CODE (newdecl) == FUNCTION_DECL) - warned |= diagnose_mismatched_attributes (olddecl, newdecl); + warned |= diagnose_mismatched_attributes (olddecl, newdecl, oldtype, + newtype); else /* PARM_DECL, VAR_DECL */ { /* Redeclaration of a parameter is a constraint violation (this is diff --git gcc/cp/decl.c gcc/cp/decl.c index d98fab370d7..4a67e57c675 100644 --- gcc/cp/decl.c +++ gcc/cp/decl.c @@ -1397,7 +1397,9 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) if (DECL_P (olddecl) && TREE_CODE (newdecl) == FUNCTION_DECL && TREE_CODE (olddecl) == FUNCTION_DECL - && diagnose_mismatched_attributes (olddecl, newdecl)) + && diagnose_mismatched_attributes (olddecl, newdecl, + TREE_TYPE (olddecl), + TREE_TYPE (newdecl))) { if (DECL_INITIAL (olddecl)) inform (DECL_SOURCE_LOCATION (olddecl), diff --git gcc/testsuite/c-c++-common/attributes-4.c gcc/testsuite/c-c++-common/attributes-4.c index e69de29bb2d..2f8b9676ecd 100644 --- gcc/testsuite/c-c++-common/attributes-4.c +++ gcc/testsuite/c-c++-common/attributes-4.c @@ -0,0 +1,8 @@ +/* PR c/81544 */ +/* { dg-do compile } */ + +int __attribute__ ((noreturn)) foo (void); /* { dg-message "previous declaration" } */ +int __attribute__ ((warn_unused_result)) foo (void); /* { dg-warning "attribute .warn_unused_result. follows declaration with attribute .noreturn." } */ + +int __attribute__ ((warn_unused_result)) foo2 (void); /* { dg-message "previous declaration" } */ +int __attribute__ ((noreturn)) foo2 (void); /* { dg-warning "attribute .noreturn. follows declaration with attribute .warn_unused_result." } */ Marek