This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[C++ gnu_inline] fix ICE inlining after definition and redeclaration


Jakub found an error in my earlier patch.  If a gnu_inline function
was redeclared without a new definition, and then called, we'd ICE
when inlining it.  Here's a patch that fixes it, by arranging for the
linkage flags to not be affected by mere redeclarations, only by
actual redefinitions.

Jakub offered to test it, so I haven't, other than by compiling by
hand the test included in the patch.  Ok to install after Jakub
completes testing it?

:ADDPATCH c++/gnu_inline:

Index: gcc/cp/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* decl.c (duplicate_decls): Preserve linkage flags for mere
	redeclarations of gnu_inline definitions.

Index: gcc/testsuite/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* g++.dg/ext/gnu-inline-global-redecl.C: New.

Index: gcc/cp/decl.c
===================================================================
--- gcc/cp/decl.c.orig	2007-09-28 00:02:33.000000000 -0300
+++ gcc/cp/decl.c	2007-10-01 16:33:10.000000000 -0300
@@ -1846,24 +1846,24 @@ duplicate_decls (tree newdecl, tree oldd
   new_template = NULL_TREE;
   if (DECL_LANG_SPECIFIC (newdecl) && DECL_LANG_SPECIFIC (olddecl))
     {
-      bool old_decl_gnu_inline;
+      bool new_redefines_gnu_inline = false;
 
-      if ((DECL_INTERFACE_KNOWN (olddecl)
-	   && TREE_CODE (olddecl) == FUNCTION_DECL)
-	  || (TREE_CODE (olddecl) == TEMPLATE_DECL
-	      && TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) == FUNCTION_DECL))
+      if (new_defines_function
+	  && ((DECL_INTERFACE_KNOWN (olddecl)
+	       && TREE_CODE (olddecl) == FUNCTION_DECL)
+	      || (TREE_CODE (olddecl) == TEMPLATE_DECL
+		  && (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl))
+		      == FUNCTION_DECL))))
 	{
 	  tree fn = olddecl;
 
 	  if (TREE_CODE (fn) == TEMPLATE_DECL)
 	    fn = DECL_TEMPLATE_RESULT (olddecl);
 
-	  old_decl_gnu_inline = GNU_INLINE_P (fn) && DECL_INITIAL (fn);
+	  new_redefines_gnu_inline = GNU_INLINE_P (fn) && DECL_INITIAL (fn);
 	}
-      else
-	old_decl_gnu_inline = false;
 
-      if (!old_decl_gnu_inline)
+      if (!new_redefines_gnu_inline)
 	{
 	  DECL_INTERFACE_KNOWN (newdecl) |= DECL_INTERFACE_KNOWN (olddecl);
 	  DECL_NOT_REALLY_EXTERN (newdecl) |= DECL_NOT_REALLY_EXTERN (olddecl);
Index: gcc/testsuite/g++.dg/ext/gnu-inline-global-redecl.C
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc/testsuite/g++.dg/ext/gnu-inline-global-redecl.C	2007-10-01 16:45:49.000000000 -0300
@@ -0,0 +1,19 @@
+/* Test __attribute__((gnu_inline)).
+
+   Check that we don't get out-of-line definitions for extern inline
+   gnu_inline functions, regardless of redeclaration.
+
+ */
+
+/* { dg-do link } */
+/* { dg-options "-O" } */ // such that static functions are optimized out
+
+#include "gnu-inline-common.h"
+
+decl(extern, fn)
+gnuindef(fn, 0)
+decl(extern, fn)
+
+int main () {
+  fn ();
+}
-- 
Alexandre Oliva         http://www.lsd.ic.unicamp.br/~oliva/
FSF Latin America Board Member         http://www.fsfla.org/
Red Hat Compiler Engineer   aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist  oliva@{lsd.ic.unicamp.br, gnu.org}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]