This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] Fix PR c/5163
- From: Richard Henderson <rth at redhat dot com>
- To: Jakub Jelinek <jakub at redhat dot com>
- Cc: aoliva at redhat dot com, aj at suse dot de, gcc-patches at gcc dot gnu dot org
- Date: Mon, 24 Dec 2001 00:42:12 -0800
- Subject: Re: [PATCH] Fix PR c/5163
- References: <20011221234357.M542@sunsite.ms.mff.cuni.cz>
On Fri, Dec 21, 2001 at 11:43:57PM +0100, Jakub Jelinek wrote:
> (or why is actually a DECL_EXTERNAL ever marked DECL_INLINE).
This, I think, is the root of the problem. I've applied
the following patch.
r~
PR c/5163:
* c-decl.c (duplicate_decls): As needed, set DECL_INLINE when
we have a function body associated. Minor cleanups.
(grokdeclarator): Do not set DECL_INLINE without a function body.
* gcc.dg/20011223-1.c: New.
* gcc.dg/inline-1.c: New.
Index: c-decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-decl.c,v
retrieving revision 1.284
diff -c -p -d -r1.284 c-decl.c
*** c-decl.c 2001/12/17 01:18:39 1.284
--- c-decl.c 2001/12/24 07:25:03
*************** duplicate_decls (newdecl, olddecl, diffe
*** 1974,1983 ****
/* If either decl says `inline', this fn is inline,
unless its definition was passed already. */
if (DECL_DECLARED_INLINE_P (newdecl)
! && DECL_DECLARED_INLINE_P (olddecl) == 0)
! DECL_DECLARED_INLINE_P (olddecl) = 1;
!
! DECL_DECLARED_INLINE_P (newdecl) = DECL_DECLARED_INLINE_P (olddecl);
DECL_UNINLINABLE (newdecl) = DECL_UNINLINABLE (olddecl)
= (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl));
--- 1974,1981 ----
/* If either decl says `inline', this fn is inline,
unless its definition was passed already. */
if (DECL_DECLARED_INLINE_P (newdecl)
! || DECL_DECLARED_INLINE_P (olddecl))
! DECL_DECLARED_INLINE_P (newdecl) = 1;
DECL_UNINLINABLE (newdecl) = DECL_UNINLINABLE (olddecl)
= (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl));
*************** duplicate_decls (newdecl, olddecl, diffe
*** 2003,2011 ****
DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
}
}
/* Also preserve various other info from the definition. */
- else if (! new_is_definition)
- DECL_NUM_STMTS (newdecl) = DECL_NUM_STMTS (olddecl);
if (! new_is_definition)
{
DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
--- 2001,2008 ----
DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
}
}
+
/* Also preserve various other info from the definition. */
if (! new_is_definition)
{
DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
*************** duplicate_decls (newdecl, olddecl, diffe
*** 2016,2027 ****
DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
DECL_SAVED_TREE (newdecl) = DECL_SAVED_TREE (olddecl);
DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
! if (DECL_INLINE (newdecl))
! DECL_ABSTRACT_ORIGIN (newdecl)
! = (different_binding_level
! ? DECL_ORIGIN (olddecl)
! : DECL_ABSTRACT_ORIGIN (olddecl));
}
}
if (different_binding_level)
--- 2013,2039 ----
DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
DECL_SAVED_TREE (newdecl) = DECL_SAVED_TREE (olddecl);
+ DECL_NUM_STMTS (newdecl) = DECL_NUM_STMTS (olddecl);
DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
!
! /* Set DECL_INLINE on the declaration if we've got a body
! from which to instantiate. */
! if (DECL_INLINE (olddecl) && ! DECL_UNINLINABLE (newdecl))
! {
! DECL_INLINE (newdecl) = 1;
! DECL_ABSTRACT_ORIGIN (newdecl)
! = (different_binding_level
! ? DECL_ORIGIN (olddecl)
! : DECL_ABSTRACT_ORIGIN (olddecl));
! }
! }
! else
! {
! /* If a previous declaration said inline, mark the
! definition as inlinable. */
! if (DECL_DECLARED_INLINE_P (newdecl)
! && ! DECL_UNINLINABLE (newdecl))
! DECL_INLINE (newdecl) = 1;
}
}
if (different_binding_level)
*************** grokdeclarator (declarator, declspecs, d
*** 5049,5064 ****
else if (inlinep)
{
/* Assume that otherwise the function can be inlined. */
- DECL_INLINE (decl) = 1;
DECL_DECLARED_INLINE_P (decl) = 1;
! if (specbits & (1 << (int) RID_EXTERN))
! current_extern_inline = 1;
}
/* If -finline-functions, assume it can be inlined. This does
two things: let the function be deferred until it is actually
needed, and let dwarf2 know that the function is inlinable. */
! else if (flag_inline_trees == 2)
{
DECL_INLINE (decl) = 1;
DECL_DECLARED_INLINE_P (decl) = 0;
--- 5061,5083 ----
else if (inlinep)
{
/* Assume that otherwise the function can be inlined. */
DECL_DECLARED_INLINE_P (decl) = 1;
! /* Do not mark bare declarations as DECL_INLINE. Doing so
! in the presence of multiple declarations can result in
! the abstract origin pointing between the declarations,
! which will confuse dwarf2out. */
! if (initialized)
! {
! DECL_INLINE (decl) = 1;
! if (specbits & (1 << (int) RID_EXTERN))
! current_extern_inline = 1;
! }
}
/* If -finline-functions, assume it can be inlined. This does
two things: let the function be deferred until it is actually
needed, and let dwarf2 know that the function is inlinable. */
! else if (flag_inline_trees == 2 && initialized)
{
DECL_INLINE (decl) = 1;
DECL_DECLARED_INLINE_P (decl) = 0;
Index: testsuite/gcc.dg/20011223-1.c
===================================================================
RCS file: 20011223-1.c
diff -N 20011223-1.c
*** /dev/null Tue May 5 13:32:27 1998
--- 20011223-1.c Sun Dec 23 23:25:03 2001
***************
*** 0 ****
--- 1,12 ----
+ /* Origin: PR c/5163 from aj@suse.de. */
+ /* { dg-do compile } */
+ /* { dg-options "-O3 -g" } */
+
+ extern int bar (int);
+
+ int
+ foo (void)
+ {
+ extern int bar (int);
+ return bar (5);
+ }
Index: testsuite/gcc.dg/inline-1.c
===================================================================
RCS file: inline-1.c
diff -N inline-1.c
*** /dev/null Tue May 5 13:32:27 1998
--- inline-1.c Sun Dec 23 23:25:03 2001
***************
*** 0 ****
--- 1,28 ----
+ /* Verify that DECL_INLINE gets copied between DECLs properly. */
+ /* { dg-do compile } */
+ /* { dg-options "-O1" } */
+ /* { dg-final { scan-assembler-not "xyzzy" } } */
+
+ /* Test that declaration followed by definition inlines. */
+ static inline int xyzzy0 (int);
+ static int xyzzy0 (int x) { return x; }
+ int test0 (void)
+ {
+ return xyzzy0 (5);
+ }
+
+ /* Test that definition following declaration inlines. */
+ static int xyzzy1 (int);
+ static inline int xyzzy1 (int x) { return x; }
+ int test1 (void)
+ {
+ return xyzzy1 (5);
+ }
+
+ /* Test that redeclaration inside a function body inlines. */
+ extern inline int xyzzy2 (int x) { return x; }
+ int test2 (void)
+ {
+ extern int xyzzy2 (int);
+ return xyzzy2 (5);
+ }