re PR c++/71024 (Missing warning for contradictory attributes)
authorMarek Polacek <polacek@redhat.com>
Wed, 11 May 2016 17:07:37 +0000 (17:07 +0000)
committerMarek Polacek <mpolacek@gcc.gnu.org>
Wed, 11 May 2016 17:07:37 +0000 (17:07 +0000)
PR c++/71024
* c-common.c (diagnose_mismatched_attributes): New function.
* c-common.h (diagnose_mismatched_attributes): Declare.

* c-decl.c (diagnose_mismatched_decls): Factor out code to
diagnose_mismatched_attributes and call it.

* decl.c (duplicate_decls): Call diagnose_mismatched_decls.

* c-c++-common/attributes-3.c: New test.

From-SVN: r236129

gcc/c-family/ChangeLog
gcc/c-family/c-common.c
gcc/c-family/c-common.h
gcc/c/ChangeLog
gcc/c/c-decl.c
gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/attributes-3.c [new file with mode: 0644]

index e1ba43945c64dc9a9504946189d032e58e698e50..0b31517a1188f20005340a7a6fa27038df5294b3 100644 (file)
@@ -1,3 +1,9 @@
+2016-05-11  Marek Polacek  <polacek@redhat.com>
+
+       PR c++/71024
+       * c-common.c (diagnose_mismatched_attributes): New function.
+       * c-common.h (diagnose_mismatched_attributes): Declare.
+
 2016-05-04  Marek Polacek  <polacek@redhat.com>
 
        * c.opt (Wdangling-else): New option.
index 63a18c866ebd3f270b9a97f667d99d670d092e34..665448c2298b694b28730b2ba9b21c41d00a7bd4 100644 (file)
@@ -12824,4 +12824,58 @@ get_source_date_epoch ()
   return (time_t) epoch;
 }
 
+/* Check and possibly warn if two declarations have contradictory
+   attributes, such as always_inline vs. noinline.  */
+
+bool
+diagnose_mismatched_attributes (tree olddecl, tree newdecl)
+{
+  bool warned = false;
+
+  tree a1 = lookup_attribute ("optimize", DECL_ATTRIBUTES (olddecl));
+  tree a2 = lookup_attribute ("optimize", DECL_ATTRIBUTES (newdecl));
+  /* An optimization attribute applied on a declaration after the
+     definition is likely not what the user wanted.  */
+  if (a2 != NULL_TREE
+      && DECL_SAVED_TREE (olddecl) != NULL_TREE
+      && (a1 == NULL_TREE || !attribute_list_equal (a1, a2)))
+    warned |= warning (OPT_Wattributes,
+                      "optimization attribute on %qD follows "
+                      "definition but the attribute doesn%'t match",
+                      newdecl);
+
+  /* Diagnose inline __attribute__ ((noinline)) which is silly.  */
+  if (DECL_DECLARED_INLINE_P (newdecl)
+      && DECL_UNINLINABLE (olddecl)
+      && lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
+    warned |= warning (OPT_Wattributes, "inline declaration of %qD follows "
+                      "declaration with attribute noinline", newdecl);
+  else if (DECL_DECLARED_INLINE_P (olddecl)
+          && DECL_UNINLINABLE (newdecl)
+          && lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
+    warned |= warning (OPT_Wattributes, "declaration of %q+D with attribute "
+                      "noinline follows inline declaration ", newdecl);
+  else if (lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl))
+          && lookup_attribute ("always_inline", DECL_ATTRIBUTES (olddecl)))
+    warned |= warning (OPT_Wattributes, "declaration of %q+D with attribute "
+                      "%qs follows declaration with attribute %qs",
+                      newdecl, "noinline", "always_inline");
+  else if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (newdecl))
+          && lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
+    warned |= warning (OPT_Wattributes, "declaration of %q+D with attribute "
+                      "%qs follows declaration with attribute %qs",
+                      newdecl, "always_inline", "noinline");
+  else if (lookup_attribute ("cold", DECL_ATTRIBUTES (newdecl))
+          && lookup_attribute ("hot", DECL_ATTRIBUTES (olddecl)))
+    warned |= warning (OPT_Wattributes, "declaration of %q+D with attribute "
+                      "%qs follows declaration with attribute %qs",
+                      newdecl, "cold", "hot");
+  else if (lookup_attribute ("hot", DECL_ATTRIBUTES (newdecl))
+          && lookup_attribute ("cold", DECL_ATTRIBUTES (olddecl)))
+    warned |= warning (OPT_Wattributes, "declaration of %q+D with attribute "
+                      "%qs follows declaration with attribute %qs",
+                      newdecl, "hot", "cold");
+  return warned;
+}
+
 #include "gt-c-family-c-common.h"
index 4454d0847248f1fde24b08d18ecbc1e08ee7fa00..0ee9f56712357653479162795011d2c13155a23a 100644 (file)
@@ -850,6 +850,7 @@ extern bool keyword_is_type_qualifier (enum rid);
 extern bool keyword_is_decl_specifier (enum rid);
 extern bool cxx_fundamental_alignment_p (unsigned);
 extern bool pointer_to_zero_sized_aggr_p (tree);
+extern bool diagnose_mismatched_attributes (tree, tree);
 
 #define c_sizeof(LOC, T)  c_sizeof_or_alignof_type (LOC, T, true, false, 1)
 #define c_alignof(LOC, T) c_sizeof_or_alignof_type (LOC, T, false, false, 1)
index 9387c73b35ee5113bb48d98703a5eaea3e7f41ae..70444002652bb499179655f4723ff2de61218b57 100644 (file)
@@ -1,3 +1,9 @@
+2016-05-11  Marek Polacek  <polacek@redhat.com>
+
+       PR c++/71024
+       * c-decl.c (diagnose_mismatched_decls): Factor out code to
+       diagnose_mismatched_attributes and call it.
+
 2016-05-10  Marek Polacek  <polacek@redhat.com>
 
        PR c/70255
index 9c09536c18edc8a694446f127d48c3be4401fb5e..6ba0e0e52a55be2de5399bda32bb743faa1bf7ec 100644 (file)
@@ -2227,55 +2227,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
     }
 
   if (TREE_CODE (newdecl) == FUNCTION_DECL)
-    {
-      tree a1 = lookup_attribute ("optimize", DECL_ATTRIBUTES (olddecl));
-      tree a2 = lookup_attribute ("optimize", DECL_ATTRIBUTES (newdecl));
-      /* An optimization attribute applied on a declaration after the
-        definition is likely not what the user wanted.  */
-      if (a2 != NULL_TREE
-         && DECL_SAVED_TREE (olddecl) != NULL_TREE
-         && (a1 == NULL_TREE || !attribute_list_equal (a1, a2)))
-       warned |= warning (OPT_Wattributes,
-                          "optimization attribute on %qD follows "
-                          "definition but the attribute doesn%'t match",
-                          newdecl);
-
-      /* Diagnose inline __attribute__ ((noinline)) which is silly.  */
-      if (DECL_DECLARED_INLINE_P (newdecl)
-         && lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
-       warned |= warning (OPT_Wattributes,
-                          "inline declaration of %qD follows "
-                          "declaration with attribute noinline", newdecl);
-      else if (DECL_DECLARED_INLINE_P (olddecl)
-              && lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
-       warned |= warning (OPT_Wattributes,
-                          "declaration of %q+D with attribute "
-                          "noinline follows inline declaration ", newdecl);
-      else if (lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl))
-              && lookup_attribute ("always_inline", DECL_ATTRIBUTES (olddecl)))
-       warned |= warning (OPT_Wattributes,
-                          "declaration of %q+D with attribute "
-                          "%qs follows declaration with attribute %qs",
-                          newdecl, "noinline", "always_inline");
-      else if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (newdecl))
-              && lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
-       warned |= warning (OPT_Wattributes,
-                          "declaration of %q+D with attribute "
-                          "%qs follows declaration with attribute %qs",
-                          newdecl, "always_inline", "noinline");
-      else if (lookup_attribute ("cold", DECL_ATTRIBUTES (newdecl))
-              && lookup_attribute ("hot", DECL_ATTRIBUTES (olddecl)))
-       warned |= warning (OPT_Wattributes,
-                          "declaration of %q+D with attribute %qs follows "
-                          "declaration with attribute %qs", newdecl, "cold",
-                          "hot");
-      else if (lookup_attribute ("hot", DECL_ATTRIBUTES (newdecl))
-              && lookup_attribute ("cold", DECL_ATTRIBUTES (olddecl)))
-       warned |= warning (OPT_Wattributes,
-                          "declaration of %q+D with attribute %qs follows "
-                          "declaration with attribute %qs", newdecl, "hot",
-                          "cold");
-    }
+    warned |= diagnose_mismatched_attributes (olddecl, newdecl);
   else /* PARM_DECL, VAR_DECL */
     {
       /* Redeclaration of a parameter is a constraint violation (this is
index 9006b341a7a3d34f7d1013db5088c40995583115..fda48a700b94a44d77745553e21695bee13b6358 100644 (file)
@@ -1,3 +1,8 @@
+2016-05-11  Marek Polacek  <polacek@redhat.com>
+
+       PR c++/71024
+       * decl.c (duplicate_decls): Call diagnose_mismatched_decls.
+
 2016-05-05  Jakub Jelinek  <jakub@redhat.com>
 
        * parser.c (cp_parser_selection_statement): For RID_SWITCH,
index 8dbc730f3a697ee3358a867f68b54b14eebe6c63..126d8707e459d304f1918d7f6c2151b98d7e9f27 100644 (file)
@@ -1389,38 +1389,14 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
   if (DECL_P (olddecl)
       && TREE_CODE (newdecl) == FUNCTION_DECL
       && TREE_CODE (olddecl) == FUNCTION_DECL
-      && (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl)))
-    {
-      if (DECL_DECLARED_INLINE_P (newdecl)
-         && DECL_UNINLINABLE (newdecl)
-         && lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
-       /* Already warned elsewhere.  */;
-      else if (DECL_DECLARED_INLINE_P (olddecl)
-              && DECL_UNINLINABLE (olddecl)
-              && lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
-       /* Already warned.  */;
-      else if (DECL_DECLARED_INLINE_P (newdecl)
-              && DECL_UNINLINABLE (olddecl)
-              && lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
-       {
-         if (warning_at (DECL_SOURCE_LOCATION (newdecl),
-                         OPT_Wattributes, "function %qD redeclared as inline",
-                         newdecl))
-           inform (DECL_SOURCE_LOCATION (olddecl),
-                   "previous declaration of %qD with attribute noinline",
-                   olddecl);
-       }
-      else if (DECL_DECLARED_INLINE_P (olddecl)
-              && DECL_UNINLINABLE (newdecl)
-              && lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
-       {
-         if (warning_at (DECL_SOURCE_LOCATION (newdecl),
-                         OPT_Wattributes, "function %qD redeclared with "
-                         "attribute noinline", newdecl))
-           inform (DECL_SOURCE_LOCATION (olddecl),
-                   "previous declaration of %qD was inline",
-                   olddecl);
-       }
+      && diagnose_mismatched_attributes (olddecl, newdecl))
+    {
+      if (DECL_INITIAL (olddecl))
+       inform (DECL_SOURCE_LOCATION (olddecl),
+               "previous definition of %q+D was here", olddecl);
+      else
+       inform (DECL_SOURCE_LOCATION (olddecl),
+               "previous declaration of %qD was here", olddecl);
     }
 
   /* Check for redeclaration and other discrepancies.  */
index 839d0a0fa6a42cbb89cb22ee43012c6e15f1c17f..93c8706aca6df53a0f347a9c59239053b1bd5770 100644 (file)
@@ -1,3 +1,8 @@
+2016-05-11  Marek Polacek  <polacek@redhat.com>
+
+       PR c++/71024
+       * c-c++-common/attributes-3.c: New test.
+
 2016-05-11  Nathan Sidwell  <nathan@acm.org>
 
        * gcc.dg/pr68671.c: Xfail on PTX -- assembler crash.
diff --git a/gcc/testsuite/c-c++-common/attributes-3.c b/gcc/testsuite/c-c++-common/attributes-3.c
new file mode 100644 (file)
index 0000000..821278c
--- /dev/null
@@ -0,0 +1,27 @@
+/* PR c++/71024 */
+/* { dg-do compile } */
+/* { dg-prune-output "declared but never defined" } */
+
+void
+fn0 (void) /* { dg-message "previous definition" } */
+{
+}
+extern void __attribute__((optimize ("O2"))) fn0 (void); /* { dg-warning "optimization attribute" } */
+
+extern __attribute__((noinline)) int fn1 (void); /* { dg-message "previous declaration" } */
+extern inline int fn1 (void); /* { dg-warning "inline declaration of" } */
+
+extern inline int fn2 (void); /* { dg-message "previous declaration" } */
+extern __attribute__((noinline)) int fn2 (void); /* { dg-warning "attribute noinline follows inline declaration" } */
+
+extern __attribute__((always_inline)) int fn3 (void); /* { dg-message "previous declaration" } */
+extern __attribute__((noinline)) int fn3 (void); /* { dg-warning "attribute .noinline. follows declaration with attribute .always_inline." } */
+
+extern __attribute__((noinline)) int fn4 (void); /* { dg-message "previous declaration" } */
+extern __attribute__((always_inline)) int fn4 (void); /* { dg-warning "attribute .always_inline. follows declaration with attribute .noinline." } */
+
+extern __attribute__((hot)) int fn5 (void); /* { dg-message "previous declaration" } */
+extern __attribute__((cold)) int fn5 (void); /* { dg-warning "attribute .cold. follows declaration with attribute .hot." } */
+
+extern __attribute__((cold)) int fn6 (void); /* { dg-message "previous declaration" } */
+extern __attribute__((hot)) int fn6 (void); /* { dg-warning "attribute .hot. follows declaration with attribute .cold." } */