diff mbox

[PATH] PR/49139 fix always_inline failures diagnostics

Message ID 4DE49EBE.30804@st.com
State New
Headers show

Commit Message

Christian Bruel May 31, 2011, 7:54 a.m. UTC
Hello,

The attached patch fixes a few diagnostic discrepancies for 
always_inline failures.

Illustrated by the fail_always_inline[12].c attached cases, the current 
behavior is one of:

- success (with and without -Winline), silently not honoring always_inline
    gcc fail_always_inline1.c -S -Winline -O0 -fpic
    gcc fail_always_inline1.c -S -O2 -fpic

- error: with -Winline but not without
    gcc fail_always_inline1.c -S -Winline -O2 -fpic

- error: without -Winline
    gcc fail_always_inline2.c -S -fno-early-inlining -O2
    or the original c++ attachment in this defect

note that -Winline never warns, as stated in the documentation

This simple patch consistently emits a warning (changing the sorry 
unimplemented message) whenever the attribute is not honored.

My first will was to generate and error instead of the warning, but 
since it is possible that inlines is only performed at LTO time, an 
error would be inapropriate (Note that today this is not possible with 
-Winline that would abort).

Another alternative I considered would be to emit the warning under 
-Winline rather than unconditionally, but this more a user misuse of the 
attribute, so should always be warned anyway. Or maybe a new 
-Winline-always that would be activated under -Wall ? Other opinion 
welcomed.

Tested with standard bootstrap and regression on x86.

Comments, and/or OK for trunk ?

Many thanks,

Christian

2010-05-25  Christian Bruel  <christian.bruel@st.com>
	
	PR 49139
	* ipa-inline-transform.c (inline_transform):force call to 
optimize_inline_calls error if function is always_inline.
	* tree-inline.c (tree_inlinable_function_p): always warn.
	(expand_call_inline): Likewise.
	
2010-05-25  Christian Bruel  <christian.bruel@st.com>
	
	* gcc.db/always_inline.c: Removed -Winline. Update checks
	* gcc.db/always_inline2.c: Likewise.
	* gcc.db/always_inline3.c: Likewise.
	* gcc.db/fail_always_inline1.c: New test.
	* gcc.db/fail_always_inline2.c: New test.
/* { dg-do compile { target fpic } } */
/* { dg-options "-fpic" } */

__attribute((always_inline)) void
 bar() { } /* { dg-warning "can be overwriten at linktime" } */

void
f()
{
  bar(); /* { dg-warning "called from here" "" } */
}
/* { dg-do compile { target fpic } } */
/* { dg-options "-fpic -fno-early-inlining" } */

inline void foo() { foo2(); }

__attribute((always_inline)) void
 bar() { } /* { dg-warning "can be overwriten at linktime" } */

void
f()
{
  foo();
  bar(); /* { dg-warning "called from here" "" } */
}

Comments

Richard Biener May 31, 2011, 9:18 a.m. UTC | #1
On Tue, May 31, 2011 at 9:54 AM, Christian Bruel <christian.bruel@st.com> wrote:
> Hello,
>
> The attached patch fixes a few diagnostic discrepancies for always_inline
> failures.
>
> Illustrated by the fail_always_inline[12].c attached cases, the current
> behavior is one of:
>
> - success (with and without -Winline), silently not honoring always_inline
>   gcc fail_always_inline1.c -S -Winline -O0 -fpic
>   gcc fail_always_inline1.c -S -O2 -fpic
>
> - error: with -Winline but not without
>   gcc fail_always_inline1.c -S -Winline -O2 -fpic
>
> - error: without -Winline
>   gcc fail_always_inline2.c -S -fno-early-inlining -O2
>   or the original c++ attachment in this defect
>
> note that -Winline never warns, as stated in the documentation
>
> This simple patch consistently emits a warning (changing the sorry
> unimplemented message) whenever the attribute is not honored.
>
> My first will was to generate and error instead of the warning, but since it
> is possible that inlines is only performed at LTO time, an error would be
> inapropriate (Note that today this is not possible with -Winline that would
> abort).
>
> Another alternative I considered would be to emit the warning under -Winline
> rather than unconditionally, but this more a user misuse of the attribute,
> so should always be warned anyway. Or maybe a new -Winline-always that would
> be activated under -Wall ? Other opinion welcomed.
>
> Tested with standard bootstrap and regression on x86.
>
> Comments, and/or OK for trunk ?

The patch is not ok, we may not fail to inline an always_inline
function.  To make this more consistent I proposed to warn
whenever you take the address of an always_inline function
(because then you can confuse GCC by indirectly calling
such function which we might inline dependent on optimization
setting and which we might discover we didn't inline only
dependent on optimization setting).  Honza proposed to move
the sorry()ing to when we feel the need to output the
always_inline function, thus when it was not optimized away,
but that would require us not preserving the body (do we?)
with -fpreserve-inline-functions.

For fail_always_inline1.c we should diagnose the appearant
misuse of always_inline with a warning, drop the attribute
but keep DECL_DISREGARD_INLINE_LIMITS set.

Same for fail_always_inline2.c.

I agree that sorry()ing for those cases is odd.  EIther we
should reject the declarations upfront
("always-inline function will not be inlinable"), or we should
emit a warning of that kind and make sure to not sorry later.

Richard.

> Many thanks,
>
> Christian
>
> 2010-05-25  Christian Bruel  <christian.bruel@st.com>
>
>        PR 49139
>        * ipa-inline-transform.c (inline_transform):force call to
> optimize_inline_calls error if function is always_inline.
>        * tree-inline.c (tree_inlinable_function_p): always warn.
>        (expand_call_inline): Likewise.
>
> 2010-05-25  Christian Bruel  <christian.bruel@st.com>
>
>        * gcc.db/always_inline.c: Removed -Winline. Update checks
>        * gcc.db/always_inline2.c: Likewise.
>        * gcc.db/always_inline3.c: Likewise.
>        * gcc.db/fail_always_inline1.c: New test.
>        * gcc.db/fail_always_inline2.c: New test.
>
>
>
>
>
Jakub Jelinek May 31, 2011, 9:25 a.m. UTC | #2
On Tue, May 31, 2011 at 11:18:18AM +0200, Richard Guenther wrote:
> The patch is not ok, we may not fail to inline an always_inline
> function.  To make this more consistent I proposed to warn
> whenever you take the address of an always_inline function
> (because then you can confuse GCC by indirectly calling
> such function which we might inline dependent on optimization
> setting and which we might discover we didn't inline only
> dependent on optimization setting).  Honza proposed to move

That would warn on a lot of valid programs.  Even
#include <unistd.h>
void *readptr = read;
would warn, because read is both extern and
extern __inline __attribute__ ((__always_inline__, __artificial__, __gnu_inline__, __warn_unused_result__)) ssize_t
read (int __fd, void *__buf, size_t __nbytes)
{
  ...
}
wrapper.  Similarly dozens of other functions.  glibc relies on
extern inline gnu_inline behavior there, if you take address, the
extern is used instead of the inline.

	Jakub
diff mbox

Patch

Index: gcc/ipa-inline-transform.c
===================================================================
--- gcc/ipa-inline-transform.c	(revision 174264)
+++ gcc/ipa-inline-transform.c	(working copy)
@@ -302,9 +302,20 @@ 
 
   for (e = node->callees; e; e = e->next_callee)
     {
-      cgraph_redirect_edge_call_stmt_to_callee (e);
+      gimple call = cgraph_redirect_edge_call_stmt_to_callee (e);
+
+      if (!inline_p)
+	{
       if (!e->inline_failed || warn_inline)
         inline_p = true;
+	  else
+	    {
+	      tree fn = gimple_call_fndecl (call);
+	      
+	      if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)))
+		inline_p = true;
+	    }
+	}
     }
 
   if (inline_p)
Index: gcc/ChangeLog
===================================================================
--- gcc/ChangeLog	(revision 174264)
+++ gcc/ChangeLog	(working copy)
@@ -1,3 +1,11 @@ 
+2010-05-25  Christian Bruel  <christian.bruel@st.com>
+	
+	PR 49139
+	* ipa-inline-transform.c (inline_transform): force optimize_inline_calls
+	error checking if always_inline seen.
+	* tree-inline.c (tree_inlinable_function_p): use error instead of sorry.
+	(expand_call_inline): Likewise.
+	
 2011-05-25  Ian Lance Taylor  <iant@google.com>
 
 	* godump.c (go_format_type): Output the first field with a usable
Index: gcc/testsuite/gcc.dg/always_inline.c
===================================================================
--- gcc/testsuite/gcc.dg/always_inline.c	(revision 174264)
+++ gcc/testsuite/gcc.dg/always_inline.c	(working copy)
@@ -1,8 +1,8 @@ 
 /* { dg-do compile } */
-/* { dg-options "-Winline -O2" } */
+/* { dg-options "-O2" } */
 #include <stdarg.h>
 inline __attribute__ ((always_inline)) void
-e(int t, ...) /* { dg-message "sorry\[^\n\]*variable argument" "" } */
+e(int t, ...) /* { dg-warning "variable argument" } */
 {
   va_list q;
   va_start (q, t);
Index: gcc/testsuite/gcc.dg/always_inline2.c
===================================================================
--- gcc/testsuite/gcc.dg/always_inline2.c	(revision 174264)
+++ gcc/testsuite/gcc.dg/always_inline2.c	(working copy)
@@ -1,8 +1,8 @@ 
 /* { dg-do compile } */
-/* { dg-options "-Winline -O2" } */
-inline __attribute__ ((always_inline)) void t(void); /* { dg-message "sorry\[^\n\]*body not available" "" } */
+/* { dg-options "-O2" } */
+inline __attribute__ ((always_inline)) void t(void); /* { dg-warning "body not available" } */
 void
 q(void)
 {
-  t(); 				/* { dg-message "sorry\[^\n\]*called from here" "" } */
+  t(); 				/* { dg-warning "called from here" } */
 }
Index: gcc/testsuite/gcc.dg/always_inline3.c
===================================================================
--- gcc/testsuite/gcc.dg/always_inline3.c	(revision 174264)
+++ gcc/testsuite/gcc.dg/always_inline3.c	(working copy)
@@ -1,11 +1,11 @@ 
 /* { dg-do compile } */
-/* { dg-options "-Winline -O2" } */
+/* { dg-options "-O2" } */
 int do_something_evil (void);
 inline __attribute__ ((always_inline)) void
-q2(void) /* { dg-message "sorry\[^\n\]*recursive" "" } */
+q2(void) /* { dg-warning "recursive inlining" } */
 {
   if (do_something_evil ())
     return;
-  q2(); 			/* { dg-message "sorry\[^\n\]*called from here" "" } */
+  q2(); 			/* { dg-warning "called from here" } */
   q2(); /* With -O2 we don't warn here, it is eliminated by tail recursion.  */
 }
Index: gcc/testsuite/ChangeLog
===================================================================
--- gcc/testsuite/ChangeLog	(revision 174264)
+++ gcc/testsuite/ChangeLog	(working copy)
@@ -1,3 +1,9 @@ 
+2010-05-25  Christian Bruel  <christian.bruel@st.com>
+	
+	* gcc.db/always_inline.c: Removed -Winline. Update checks
+	* gcc.db/always_inline2.c: Likewise.
+	* gcc.db/always_inline3.c: Likewise.
+	
 2011-05-26  Fabien Chêne  <fabien@gcc.gnu.org>
 	* g++.dg/init/pr25811-3.C: New.
 	* g++.dg/init/pr25811-4.C: New.
Index: gcc/tree-inline.c
===================================================================
--- gcc/tree-inline.c	(revision 174264)
+++ gcc/tree-inline.c	(working copy)
@@ -3192,7 +3192,7 @@ 
 	 As a bonus we can now give more details about the reason why a
 	 function is not inlinable.  */
       if (always_inline)
-	sorry (inline_forbidden_reason, fn);
+	warning (0, inline_forbidden_reason, fn);
       else if (do_warning)
 	warning (OPT_Winline, inline_forbidden_reason, fn);
 
@@ -3744,9 +3744,9 @@ 
 	  /* Avoid warnings during early inline pass. */
 	  && cgraph_global_info_ready)
 	{
-	  sorry ("inlining failed in call to %q+F: %s", fn,
-		 _(cgraph_inline_failed_string (reason)));
-	  sorry ("called from here");
+	  warning (0, "inlining failed in call to always_inline %q+F: %s", fn,
+		 cgraph_inline_failed_string (reason));
+	  warning (0, "called from here");
 	}
       else if (warn_inline
 	       && DECL_DECLARED_INLINE_P (fn)