aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2001-12-24 00:45:59 -0800
committerRichard Henderson <rth@gcc.gnu.org>2001-12-24 00:45:59 -0800
commitb79d521356bff7a7db09804fb97c666013760665 (patch)
tree0760756073317f0da8196fdf280c98f1a6b41166
parent6b98090114cf344b8859c0f07053abcad84e6761 (diff)
downloadgcc-b79d521356bff7a7db09804fb97c666013760665.zip
gcc-b79d521356bff7a7db09804fb97c666013760665.tar.gz
gcc-b79d521356bff7a7db09804fb97c666013760665.tar.bz2
re PR debug/5163 (Internal compiler error in add_abstract_origin_attribute, at dwarf2out.c:9296)
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. From-SVN: r48302
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/c-decl.c49
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/20011223-1.c12
-rw-r--r--gcc/testsuite/gcc.dg/inline-1.c28
5 files changed, 86 insertions, 15 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7df5b18..c526245 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,12 @@
2001-12-23 Richard Henderson <rth@redhat.com>
+ 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.
+
+2001-12-23 Richard Henderson <rth@redhat.com>
+
* stmt.c (resolve_operand_names): Handle operand modifiers.
2001-12-23 Richard Henderson <rth@redhat.com>
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index c7e1e0a..495425b 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -1974,10 +1974,8 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
/* 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_DECLARED_INLINE_P (olddecl))
+ DECL_DECLARED_INLINE_P (newdecl) = 1;
DECL_UNINLINABLE (newdecl) = DECL_UNINLINABLE (olddecl)
= (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl));
@@ -2003,9 +2001,8 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
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);
@@ -2016,12 +2013,27 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
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);
- if (DECL_INLINE (newdecl))
- DECL_ABSTRACT_ORIGIN (newdecl)
- = (different_binding_level
- ? DECL_ORIGIN (olddecl)
- : DECL_ABSTRACT_ORIGIN (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)
@@ -5049,16 +5061,23 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
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;
+ /* 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)
+ else if (flag_inline_trees == 2 && initialized)
{
DECL_INLINE (decl) = 1;
DECL_DECLARED_INLINE_P (decl) = 0;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index cddb9ab..c2bb361 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2001-12-24 Richard Henderson <rth@redhat.com>
+
+ * gcc.dg/20011223-1.c: New.
+ * gcc.dg/inline-1.c: New.
+
2001-12-23 Richard Henderson <rth@redhat.com>
* gcc.dg/asm-4.c: Test operand modifiers.
diff --git a/gcc/testsuite/gcc.dg/20011223-1.c b/gcc/testsuite/gcc.dg/20011223-1.c
new file mode 100644
index 0000000..53f7f20
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/20011223-1.c
@@ -0,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);
+}
diff --git a/gcc/testsuite/gcc.dg/inline-1.c b/gcc/testsuite/gcc.dg/inline-1.c
new file mode 100644
index 0000000..17a9a2f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/inline-1.c
@@ -0,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);
+}