2007-12-12 20:33:17 +00:00
|
|
|
2007-11-06 Jakub Jelinek <jakub@redhat.com>
|
2007-10-16 14:18:55 +00:00
|
|
|
|
|
|
|
PR tree-optimization/33763
|
|
|
|
* gcc.dg/pr33763.c: New test.
|
2007-12-12 20:33:17 +00:00
|
|
|
* g++.dg/opt/inline13.C: New test.
|
2007-10-16 14:18:55 +00:00
|
|
|
|
2007-12-12 20:33:17 +00:00
|
|
|
2007-11-06 Jan Hubicka <jh@suse.cz>
|
2007-10-16 14:18:55 +00:00
|
|
|
|
|
|
|
PR tree-optimization/33763
|
|
|
|
* tree-inline.c (expand_call_inline): Silently ignore always_inline
|
|
|
|
attribute for redefined extern inline functions.
|
|
|
|
|
2007-12-12 20:33:17 +00:00
|
|
|
--- gcc/tree-inline.c.jj 2007-11-06 09:29:04.000000000 +0100
|
|
|
|
+++ gcc/tree-inline.c 2007-11-06 16:19:12.000000000 +0100
|
2009-01-16 18:34:38 +00:00
|
|
|
@@ -3157,6 +3157,12 @@ expand_call_inline (basic_block bb, gimp
|
|
|
|
goto egress;
|
|
|
|
|
2007-10-16 14:18:55 +00:00
|
|
|
if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn))
|
|
|
|
+ /* For extern inline functions that get redefined we always
|
|
|
|
+ silently ignored alway_inline flag. Better behaviour would
|
|
|
|
+ be to be able to keep both bodies and use extern inline body
|
|
|
|
+ for inlining, but we can't do that because frontends overwrite
|
|
|
|
+ the body. */
|
|
|
|
+ && !cg_edge->callee->local.redefined_extern_inline
|
|
|
|
/* Avoid warnings during early inline pass. */
|
2009-01-16 18:34:38 +00:00
|
|
|
&& cgraph_global_info_ready)
|
2007-10-16 14:18:55 +00:00
|
|
|
{
|
2007-12-12 20:33:17 +00:00
|
|
|
--- gcc/testsuite/gcc.dg/pr33763.c.jj 2007-11-06 16:19:12.000000000 +0100
|
|
|
|
+++ gcc/testsuite/gcc.dg/pr33763.c 2007-11-06 16:19:12.000000000 +0100
|
2007-10-16 14:18:55 +00:00
|
|
|
@@ -0,0 +1,60 @@
|
|
|
|
+/* PR tree-optimization/33763 */
|
|
|
|
+/* { dg-do compile } */
|
|
|
|
+/* { dg-options "-O2" } */
|
|
|
|
+
|
|
|
|
+typedef struct
|
|
|
|
+{
|
|
|
|
+ void *a;
|
|
|
|
+ void *b;
|
|
|
|
+} T;
|
|
|
|
+extern void *foo (const char *, const char *);
|
|
|
|
+extern void *bar (void *, const char *, T);
|
|
|
|
+extern int baz (const char *, int);
|
|
|
|
+
|
|
|
|
+extern inline __attribute__ ((always_inline, gnu_inline)) int
|
|
|
|
+baz (const char *x, int y)
|
|
|
|
+{
|
|
|
|
+ return 2;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int
|
|
|
|
+baz (const char *x, int y)
|
|
|
|
+{
|
|
|
|
+ return 1;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int xa, xb;
|
|
|
|
+
|
|
|
|
+static void *
|
|
|
|
+inl (const char *x, const char *y)
|
|
|
|
+{
|
|
|
|
+ T t = { &xa, &xb };
|
|
|
|
+ int *f = (int *) __builtin_malloc (sizeof (int));
|
|
|
|
+ const char *z;
|
|
|
|
+ int o = 0;
|
|
|
|
+ void *r = 0;
|
|
|
|
+
|
|
|
|
+ for (z = y; *z; z++)
|
|
|
|
+ {
|
|
|
|
+ if (*z == 'r')
|
|
|
|
+ o |= 1;
|
|
|
|
+ if (*z == 'w')
|
|
|
|
+ o |= 2;
|
|
|
|
+ }
|
|
|
|
+ if (o == 1)
|
|
|
|
+ *f = baz (x, 0);
|
|
|
|
+ if (o == 2)
|
|
|
|
+ *f = baz (x, 1);
|
|
|
|
+ if (o == 3)
|
|
|
|
+ *f = baz (x, 2);
|
|
|
|
+
|
|
|
|
+ if (o && *f > 0)
|
|
|
|
+ r = bar (f, "w", t);
|
|
|
|
+ return r;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void *
|
|
|
|
+foo (const char *x, const char *y)
|
|
|
|
+{
|
|
|
|
+ return inl (x, y);
|
|
|
|
+}
|
2007-12-12 20:33:17 +00:00
|
|
|
--- gcc/testsuite/g++.dg/opt/inline13.C.jj 2007-11-06 16:20:20.000000000 +0100
|
|
|
|
+++ gcc/testsuite/g++.dg/opt/inline13.C 2007-11-06 16:21:30.000000000 +0100
|
2007-10-16 14:18:55 +00:00
|
|
|
@@ -0,0 +1,60 @@
|
|
|
|
+// PR tree-optimization/33763
|
|
|
|
+// { dg-do compile }
|
|
|
|
+// { dg-options "-O2" }
|
|
|
|
+
|
|
|
|
+typedef struct
|
|
|
|
+{
|
|
|
|
+ void *a;
|
|
|
|
+ void *b;
|
|
|
|
+} T;
|
|
|
|
+extern void *foo (const char *, const char *);
|
|
|
|
+extern void *bar (void *, const char *, T);
|
|
|
|
+extern int baz (const char *, int);
|
|
|
|
+
|
|
|
|
+extern inline __attribute__ ((always_inline, gnu_inline)) int
|
|
|
|
+baz (const char *x, int y)
|
|
|
|
+{
|
|
|
|
+ return 2;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int
|
|
|
|
+baz (const char *x, int y)
|
|
|
|
+{
|
|
|
|
+ return 1;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int xa, xb;
|
|
|
|
+
|
|
|
|
+static void *
|
|
|
|
+inl (const char *x, const char *y)
|
|
|
|
+{
|
|
|
|
+ T t = { &xa, &xb };
|
|
|
|
+ int *f = (int *) __builtin_malloc (sizeof (int));
|
|
|
|
+ const char *z;
|
|
|
|
+ int o = 0;
|
|
|
|
+ void *r = 0;
|
|
|
|
+
|
|
|
|
+ for (z = y; *z; z++)
|
|
|
|
+ {
|
|
|
|
+ if (*z == 'r')
|
|
|
|
+ o |= 1;
|
|
|
|
+ if (*z == 'w')
|
|
|
|
+ o |= 2;
|
|
|
|
+ }
|
|
|
|
+ if (o == 1)
|
|
|
|
+ *f = baz (x, 0);
|
|
|
|
+ if (o == 2)
|
|
|
|
+ *f = baz (x, 1);
|
|
|
|
+ if (o == 3)
|
|
|
|
+ *f = baz (x, 2);
|
|
|
|
+
|
|
|
|
+ if (o && *f > 0)
|
|
|
|
+ r = bar (f, "w", t);
|
|
|
|
+ return r;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void *
|
|
|
|
+foo (const char *x, const char *y)
|
|
|
|
+{
|
|
|
|
+ return inl (x, y);
|
|
|
|
+}
|