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

Reply via email to