Patchwork [C] Warn if inline attributes conflict (PR c/18079)

login
register
mail settings
Submitter Marek Polacek
Date April 8, 2014, 5:15 p.m.
Message ID <20140408171548.GB11972@redhat.com>
Download mbox | patch
Permalink /patch/337700/
State New
Headers show

Comments

Marek Polacek - April 8, 2014, 5:15 p.m.
On Mon, Mar 31, 2014 at 10:06:18AM +0200, Richard Biener wrote:
> > Sorry for the nit, but maybe it'd be better to use %qs for the second
> > attributes, so that we can use the same translation string for all conflicts.
> > Same with the later messages (where the quotes that come with %qs are
> > probably needed too).
> 
> Good point, patch is pre-approved (also adjusting the two other conflict
> warnings to spell out that the attribute is ignored).

Yes, that will be better, thanks and sorry for the delay.  That patch
is staged for stage1 though, so I'll commit the following variant
instead once the stage1 opens.

2014-04-08  Marek Polacek  <polacek@redhat.com>

	PR c/18079
c/
	* c-decl.c (diagnose_mismatched_decls): Warn for mismatched
	always_inline/noinline and hot/cold attributes.
c-family/
	* c-common.c (handle_noinline_attribute): Warn if the attribute
	conflicts with always_inline attribute.
	(handle_always_inline_attribute): Warn if the attribute conflicts
	with noinline attribute.
testsuite/
	* gcc.dg/pr18079.c: New test.
	* gcc.dg/pr18079-2.c: New test.


	Marek

Patch

diff --git gcc/c-family/c-common.c gcc/c-family/c-common.c
index 03731b4..0cd3c10 100644
--- gcc/c-family/c-common.c
+++ gcc/c-family/c-common.c
@@ -6564,8 +6564,8 @@  handle_hot_attribute (tree *node, tree name, tree ARG_UNUSED (args),
     {
       if (lookup_attribute ("cold", DECL_ATTRIBUTES (*node)) != NULL)
 	{
-	  warning (OPT_Wattributes, "%qE attribute conflicts with attribute %s",
-		   name, "cold");
+	  warning (OPT_Wattributes, "%qE attribute ignored due to conflict "
+		   "with attribute %qs", name, "cold");
 	  *no_add_attrs = true;
 	}
       /* Most of the rest of the hot processing is done later with
@@ -6592,8 +6592,8 @@  handle_cold_attribute (tree *node, tree name, tree ARG_UNUSED (args),
     {
       if (lookup_attribute ("hot", DECL_ATTRIBUTES (*node)) != NULL)
 	{
-	  warning (OPT_Wattributes, "%qE attribute conflicts with attribute %s",
-		   name, "hot");
+	  warning (OPT_Wattributes, "%qE attribute ignored due to conflict "
+		   "with attribute %qs", name, "hot");
 	  *no_add_attrs = true;
 	}
       /* Most of the rest of the cold processing is done later with
@@ -6666,7 +6666,16 @@  handle_noinline_attribute (tree *node, tree name,
 			   int ARG_UNUSED (flags), bool *no_add_attrs)
 {
   if (TREE_CODE (*node) == FUNCTION_DECL)
-    DECL_UNINLINABLE (*node) = 1;
+    {
+      if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (*node)))
+	{
+	  warning (OPT_Wattributes, "%qE attribute ignored due to conflict "
+		   "with attribute %qs", name, "always_inline");
+	  *no_add_attrs = true;
+	}
+      else
+	DECL_UNINLINABLE (*node) = 1;
+    }
   else
     {
       warning (OPT_Wattributes, "%qE attribute ignored", name);
@@ -6704,9 +6713,16 @@  handle_always_inline_attribute (tree *node, tree name,
 {
   if (TREE_CODE (*node) == FUNCTION_DECL)
     {
-      /* Set the attribute and mark it for disregarding inline
-	 limits.  */
-      DECL_DISREGARD_INLINE_LIMITS (*node) = 1;
+      if (lookup_attribute ("noinline", DECL_ATTRIBUTES (*node)))
+	{
+	  warning (OPT_Wattributes, "%qE attribute ignored due to conflict "
+		   "with %qs attribute", name, "noinline");
+	  *no_add_attrs = true;
+	}
+      else
+	/* Set the attribute and mark it for disregarding inline
+	   limits.  */
+	DECL_DISREGARD_INLINE_LIMITS (*node) = 1;
     }
   else
     {
diff --git gcc/c/c-decl.c gcc/c/c-decl.c
index df84980..e30876c 100644
--- gcc/c/c-decl.c
+++ gcc/c/c-decl.c
@@ -2099,18 +2099,38 @@  diagnose_mismatched_decls (tree newdecl, tree olddecl,
       /* 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);
-	}
+	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);
-	}
+	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");
     }
   else /* PARM_DECL, VAR_DECL */
     {
diff --git gcc/testsuite/gcc.dg/pr18079-2.c gcc/testsuite/gcc.dg/pr18079-2.c
index e69de29..5091dd41b 100644
--- gcc/testsuite/gcc.dg/pr18079-2.c
+++ gcc/testsuite/gcc.dg/pr18079-2.c
@@ -0,0 +1,16 @@ 
+/* PR c/18079 */
+/* { dg-do compile } */
+/* { dg-options "-Wall" } */
+
+__attribute__ ((always_inline)) void fndecl1 (void);
+__attribute__ ((noinline)) void fndecl1 (void); /* { dg-warning "attribute noinline follows declaration with attribute always_inline" } */
+
+__attribute__ ((noinline)) void fndecl2 (void);
+__attribute__ ((always_inline)) void fndecl2 (void); /* { dg-warning "attribute always_inline follows declaration with attribute noinline" } */
+
+
+__attribute__ ((hot)) void fndecl3 (void);
+__attribute__ ((cold)) void fndecl3 (void); /* { dg-warning "attribute cold follows declaration with attribute hot" } */
+
+__attribute__ ((cold)) void fndecl4 (void);
+__attribute__ ((hot)) void fndecl4 (void); /* { dg-warning "attribute hot follows declaration with attribute cold" } */
diff --git gcc/testsuite/gcc.dg/pr18079.c gcc/testsuite/gcc.dg/pr18079.c
index e69de29..b84cdeb 100644
--- gcc/testsuite/gcc.dg/pr18079.c
+++ gcc/testsuite/gcc.dg/pr18079.c
@@ -0,0 +1,33 @@ 
+/* PR c/18079 */
+/* { dg-do compile } */
+/* { dg-options "-Wall" } */
+
+__attribute__ ((noinline))
+__attribute__ ((always_inline))
+int
+fn1 (int r)
+{ /* { dg-warning "attribute ignored due to conflict" } */
+  return r & 4;
+}
+
+__attribute__ ((noinline, always_inline))
+int
+fn2 (int r)
+{ /* { dg-warning "attribute ignored due to conflict" } */
+  return r & 4;
+}
+
+__attribute__ ((always_inline))
+__attribute__ ((noinline))
+inline int
+fn3 (int r)
+{ /* { dg-warning "attribute ignored due to conflict" } */
+  return r & 8;
+}
+
+__attribute__ ((always_inline, noinline))
+inline int
+fn4 (int r)
+{ /* { dg-warning "attribute ignored due to conflict" } */
+  return r & 8;
+}