This commit is contained in:
Jakub Jelinek 2007-08-31 21:09:32 +00:00
parent 34b340a5bb
commit 95df1c0db6
5 changed files with 796 additions and 7 deletions

608
gcc41-c++-gnu_inline.patch Normal file
View File

@ -0,0 +1,608 @@
2007-08-31 Jakub Jelinek <jakub@redhat.com>
* cp-tree.h (cp_disregard_inline_limits): New prototype.
* decl.c (cp_disregard_inline_limits): New function.
* cp-objcp-common.h
(LANG_HOOKS_TREE_INLINING_DISREGARD_INLINE_LIMITS): Define.
2007-08-30 Jakub Jelinek <jakub@redhat.com>
* gcc.dg/inline-24.c: New test.
* g++.dg/opt/inline11.C: New test.
2007-08-27 Alexandre Oliva <aoliva@redhat.com>
* doc/extend.texi (gnu_inline funtion attribute): Document C++
behavior.
* decl.c (GNU_INLINE_P): New.
(duplicate_decls): Handle gnu_inline. Merge attributes and
some flags in overriding definitions.
(redeclaration_error_message): Handle gnu_inline.
(start_preparsed_function): Likewise.
* g++.dg/ext/gnu-inline-common.h: New.
* g++.dg/ext/gnu-inline-global-reject.C: New.
* g++.dg/ext/gnu-inline-global.C: New.
* g++.dg/ext/gnu-inline-namespace.C: New.
* g++.dg/ext/gnu-inline-anon-namespace.C: New.
* g++.dg/ext/gnu-inline-class.C: New.
* g++.dg/ext/gnu-inline-class-static.C: New.
* g++.dg/ext/gnu-inline-template-class.C: New.
* g++.dg/ext/gnu-inline-template-func.C: New.
--- gcc/cp/cp-tree.h.jj 2007-08-31 09:47:43.000000000 +0200
+++ gcc/cp/cp-tree.h 2007-08-31 14:09:08.000000000 +0200
@@ -4417,6 +4417,7 @@ extern linkage_kind decl_linkage (tree)
extern tree cp_walk_subtrees (tree*, int*, walk_tree_fn,
void*, struct pointer_set_t*);
extern int cp_cannot_inline_tree_fn (tree*);
+extern int cp_disregard_inline_limits (tree);
extern tree cp_add_pending_fn_decls (void*,tree);
extern int cp_auto_var_in_fn_p (tree,tree);
extern tree fold_if_not_in_template (tree);
--- gcc/cp/decl.c.jj 2007-08-31 09:47:43.000000000 +0200
+++ gcc/cp/decl.c 2007-08-31 14:27:12.000000000 +0200
@@ -1097,6 +1097,10 @@ check_redeclaration_exception_specificat
}
}
+#define GNU_INLINE_P(fn) (DECL_DECLARED_INLINE_P (fn) \
+ && lookup_attribute ("gnu_inline", \
+ DECL_ATTRIBUTES (fn)))
+
/* If NEWDECL is a redeclaration of OLDDECL, merge the declarations.
If the redeclaration is invalid, a diagnostic is issued, and the
error_mark_node is returned. Otherwise, OLDDECL is returned.
@@ -1626,19 +1630,45 @@ duplicate_decls (tree newdecl, tree oldd
= chainon (DECL_TEMPLATE_SPECIALIZATIONS (olddecl),
DECL_TEMPLATE_SPECIALIZATIONS (newdecl));
+ DECL_ATTRIBUTES (old_result)
+ = (*targetm.merge_decl_attributes) (old_result, new_result);
+
if (DECL_FUNCTION_TEMPLATE_P (newdecl))
{
- DECL_INLINE (old_result)
- |= DECL_INLINE (new_result);
- DECL_DECLARED_INLINE_P (old_result)
- |= DECL_DECLARED_INLINE_P (new_result);
- check_redeclaration_exception_specification (newdecl, olddecl);
+ if (GNU_INLINE_P (old_result) != GNU_INLINE_P (new_result)
+ && DECL_INITIAL (new_result))
+ {
+ if (DECL_INITIAL (old_result))
+ {
+ DECL_INLINE (old_result) = 0;
+ DECL_UNINLINABLE (old_result) = 1;
+ }
+ else
+ {
+ DECL_INLINE (old_result) = DECL_INLINE (new_result);
+ DECL_UNINLINABLE (old_result) = DECL_UNINLINABLE (new_result);
+ }
+ DECL_EXTERNAL (old_result) = DECL_EXTERNAL (new_result);
+ DECL_NOT_REALLY_EXTERN (old_result)
+ = DECL_NOT_REALLY_EXTERN (new_result);
+ DECL_INTERFACE_KNOWN (old_result)
+ = DECL_INTERFACE_KNOWN (new_result);
+ DECL_DECLARED_INLINE_P (old_result)
+ = DECL_DECLARED_INLINE_P (new_result);
+ }
+ else
+ {
+ DECL_INLINE (old_result)
+ |= DECL_INLINE (new_result);
+ DECL_DECLARED_INLINE_P (old_result)
+ |= DECL_DECLARED_INLINE_P (new_result);
+ check_redeclaration_exception_specification (newdecl, olddecl);
+ }
}
/* If the new declaration is a definition, update the file and
line information on the declaration. */
- if (DECL_INITIAL (old_result) == NULL_TREE
- && DECL_INITIAL (new_result) != NULL_TREE)
+ if (DECL_INITIAL (new_result) != NULL_TREE)
{
DECL_SOURCE_LOCATION (olddecl)
= DECL_SOURCE_LOCATION (old_result)
@@ -1795,9 +1825,29 @@ duplicate_decls (tree newdecl, tree oldd
new_template = NULL_TREE;
if (DECL_LANG_SPECIFIC (newdecl) && DECL_LANG_SPECIFIC (olddecl))
{
- DECL_INTERFACE_KNOWN (newdecl) |= DECL_INTERFACE_KNOWN (olddecl);
- DECL_NOT_REALLY_EXTERN (newdecl) |= DECL_NOT_REALLY_EXTERN (olddecl);
- DECL_COMDAT (newdecl) |= DECL_COMDAT (olddecl);
+ bool old_decl_gnu_inline;
+
+ if ((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);
+ }
+ else
+ old_decl_gnu_inline = false;
+
+ if (!old_decl_gnu_inline)
+ {
+ DECL_INTERFACE_KNOWN (newdecl) |= DECL_INTERFACE_KNOWN (olddecl);
+ DECL_NOT_REALLY_EXTERN (newdecl) |= DECL_NOT_REALLY_EXTERN (olddecl);
+ DECL_COMDAT (newdecl) |= DECL_COMDAT (olddecl);
+ }
DECL_TEMPLATE_INSTANTIATED (newdecl)
|= DECL_TEMPLATE_INSTANTIATED (olddecl);
@@ -1871,6 +1921,13 @@ duplicate_decls (tree newdecl, tree oldd
/* [temp.expl.spec/14] We don't inline explicit specialization
just because the primary template says so. */
}
+ else if (new_defines_function && DECL_INITIAL (olddecl))
+ {
+ /* C++ is always in in unit-at-a-time mode, so we never
+ inline re-defined extern inline functions. */
+ DECL_INLINE (newdecl) = 0;
+ DECL_UNINLINABLE (newdecl) = 1;
+ }
else
{
if (DECL_PENDING_INLINE_INFO (newdecl) == 0)
@@ -2113,9 +2170,25 @@ redeclaration_error_message (tree newdec
{
if (DECL_NAME (olddecl) == NULL_TREE)
return "%q#D not declared in class";
- else
+ else if (!GNU_INLINE_P (olddecl)
+ || GNU_INLINE_P (newdecl))
return "redefinition of %q#D";
}
+
+ if (DECL_DECLARED_INLINE_P (olddecl) && DECL_DECLARED_INLINE_P (newdecl))
+ {
+ bool olda = GNU_INLINE_P (olddecl);
+ bool newa = GNU_INLINE_P (newdecl);
+
+ if (olda != newa)
+ {
+ if (newa)
+ return "%q+D redeclared inline with %<gnu_inline%> attribute";
+ else
+ return "%q+D redeclared inline without %<gnu_inline%> attribute";
+ }
+ }
+
return 0;
}
else if (TREE_CODE (newdecl) == TEMPLATE_DECL)
@@ -2141,9 +2214,24 @@ redeclaration_error_message (tree newdec
ot = DECL_TEMPLATE_RESULT (olddecl);
if (DECL_TEMPLATE_INFO (ot))
ot = DECL_TEMPLATE_RESULT (template_for_substitution (ot));
- if (DECL_INITIAL (nt) && DECL_INITIAL (ot))
+ if (DECL_INITIAL (nt) && DECL_INITIAL (ot)
+ && (!GNU_INLINE_P (ot) || GNU_INLINE_P (nt)))
return "redefinition of %q#D";
+ if (DECL_DECLARED_INLINE_P (ot) && DECL_DECLARED_INLINE_P (nt))
+ {
+ bool olda = GNU_INLINE_P (ot);
+ bool newa = GNU_INLINE_P (nt);
+
+ if (olda != newa)
+ {
+ if (newa)
+ return "%q+D redeclared inline with %<gnu_inline%> attribute";
+ else
+ return "%q+D redeclared inline without %<gnu_inline%> attribute";
+ }
+ }
+
return NULL;
}
else if (TREE_CODE (newdecl) == VAR_DECL
@@ -10447,6 +10535,14 @@ start_preparsed_function (tree decl1, tr
&& lookup_attribute ("noinline", attrs))
warning (0, "inline function %q+D given attribute noinline", decl1);
+ /* Handle gnu_inline attribute. */
+ if (GNU_INLINE_P (decl1))
+ {
+ DECL_EXTERNAL (decl1) = 1;
+ DECL_NOT_REALLY_EXTERN (decl1) = 0;
+ DECL_INTERFACE_KNOWN (decl1) = 1;
+ }
+
if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl1))
/* This is a constructor, we must ensure that any default args
introduced by this definition are propagated to the clones
@@ -10702,8 +10798,9 @@ start_preparsed_function (tree decl1, tr
else
{
/* This is a definition, not a reference.
- So clear DECL_EXTERNAL. */
- DECL_EXTERNAL (decl1) = 0;
+ So clear DECL_EXTERNAL, unless this is a GNU extern inline. */
+ if (!GNU_INLINE_P (decl1))
+ DECL_EXTERNAL (decl1) = 0;
if ((DECL_DECLARED_INLINE_P (decl1)
|| DECL_TEMPLATE_INSTANTIATION (decl1))
@@ -11698,4 +11795,17 @@ cxx_comdat_group (tree decl)
return IDENTIFIER_POINTER (name);
}
+/* We want to inline __gnu_inline__ functions even if this would
+ violate inlining limits. Some glibc and linux constructs depend on
+ such functions always being inlined when optimizing. */
+
+int
+cp_disregard_inline_limits (tree fn)
+{
+ if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)) != NULL)
+ return 1;
+
+ return (!flag_really_no_inline && GNU_INLINE_P (fn));
+}
+
#include "gt-cp-decl.h"
--- gcc/cp/cp-objcp-common.h.jj 2007-02-20 22:37:34.000000000 +0100
+++ gcc/cp/cp-objcp-common.h 2007-08-31 13:58:32.000000000 +0200
@@ -107,6 +107,9 @@ extern tree objcp_tsubst_copy_and_build
#undef LANG_HOOKS_TREE_INLINING_CANNOT_INLINE_TREE_FN
#define LANG_HOOKS_TREE_INLINING_CANNOT_INLINE_TREE_FN \
cp_cannot_inline_tree_fn
+#undef LANG_HOOKS_TREE_INLINING_DISREGARD_INLINE_LIMITS
+#define LANG_HOOKS_TREE_INLINING_DISREGARD_INLINE_LIMITS \
+ cp_disregard_inline_limits
#undef LANG_HOOKS_TREE_INLINING_ADD_PENDING_FN_DECLS
#define LANG_HOOKS_TREE_INLINING_ADD_PENDING_FN_DECLS \
cp_add_pending_fn_decls
--- gcc/doc/extend.texi.jj 2007-08-31 09:47:40.000000000 +0200
+++ gcc/doc/extend.texi 2007-08-31 13:00:28.000000000 +0200
@@ -1587,8 +1587,8 @@ refer to the single copy in the library.
definitions of the functions need not be precisely the same, although
if they do not have the same effect your program may behave oddly.
-If the function is neither @code{extern} nor @code{static}, then the
-function is compiled as a standalone function, as well as being
+In C, if the function is neither @code{extern} nor @code{static}, then
+the function is compiled as a standalone function, as well as being
inlined where possible.
This is how GCC traditionally handled functions declared
@@ -1606,6 +1606,10 @@ assume that it is always present, whethe
In versions prior to 4.3, the only effect of explicitly including it is
to disable warnings about using inline functions in C99 mode.
+In C++, this attribute does not depend on @code{extern} in any way,
+but it still requires the @code{inline} keyword to enable its special
+behavior.
+
@cindex @code{flatten} function attribute
@item flatten
Generally, inlining into a function is limited. For a function marked with
--- gcc/testsuite/gcc.dg/inline-24.c.jj 2007-08-31 14:11:45.000000000 +0200
+++ gcc/testsuite/gcc.dg/inline-24.c 2007-08-30 18:43:55.000000000 +0200
@@ -0,0 +1,28 @@
+/* Verify that gnu_inline inlines disregard inlining limits. */
+/* { dg-do link } */
+/* { dg-options "-O2" } */
+
+extern int foo (int);
+extern int baz (int);
+
+extern inline __attribute__((gnu_inline))
+int foo (int x)
+{
+ int i;
+ if (!__builtin_constant_p (x))
+ {
+#define B(n) baz (1##n) + baz (2##n) + baz (3##n) \
+ + baz (4##n) + baz (5##n) + baz (6##n)
+#define C(n) B(1##n) + B(2##n) + B(3##n) + B(4##n) + B(5##n) + B(6##n)
+#define D(n) C(1##n) + C(2##n) + C(3##n) + C(4##n) + C(5##n) + C(6##n)
+ return D(0) + D(1) + D(2) + D(3) + D(4)
+ + D(5) + D(6) + D(7) + D(8) + D(9);
+ }
+ return 0;
+}
+
+int
+main (void)
+{
+ return foo (0);
+}
--- gcc/testsuite/g++.dg/opt/inline11.C.jj 2007-08-31 14:12:05.000000000 +0200
+++ gcc/testsuite/g++.dg/opt/inline11.C 2007-08-30 18:43:55.000000000 +0200
@@ -0,0 +1,28 @@
+/* Verify that gnu_inline inlines disregard inlining limits. */
+/* { dg-do link } */
+/* { dg-options "-O2" } */
+
+extern int foo (int);
+extern int baz (int);
+
+extern inline __attribute__((gnu_inline))
+int foo (int x)
+{
+ int i;
+ if (!__builtin_constant_p (x))
+ {
+#define B(n) baz (1##n) + baz (2##n) + baz (3##n) \
+ + baz (4##n) + baz (5##n) + baz (6##n)
+#define C(n) B(1##n) + B(2##n) + B(3##n) + B(4##n) + B(5##n) + B(6##n)
+#define D(n) C(1##n) + C(2##n) + C(3##n) + C(4##n) + C(5##n) + C(6##n)
+ return D(0) + D(1) + D(2) + D(3) + D(4)
+ + D(5) + D(6) + D(7) + D(8) + D(9);
+ }
+ return 0;
+}
+
+int
+main (void)
+{
+ return foo (0);
+}
--- gcc/testsuite/g++.dg/ext/gnu-inline-global-reject.C.jj 2007-08-31 13:00:28.000000000 +0200
+++ gcc/testsuite/g++.dg/ext/gnu-inline-global-reject.C 2007-08-31 13:00:28.000000000 +0200
@@ -0,0 +1,55 @@
+/* Test __attribute__((gnu_inline)).
+
+ Check that we reject various forms of duplicate definitions.
+*/
+
+/* { dg-do compile } */
+
+#include "gnu-inline-common.h"
+
+#undef fn
+#define fn pfx(func_decl_inline_before)
+decl(inline, fn) // { dg-error "previous" "" }
+gnuindef(fn, 0) // { dg-error "redeclared" "" }
+
+#undef fn
+#define fn pfx(func_decl_inline_after)
+gnuindef(fn, 0) // { dg-error "previous" "" }
+decl(inline, fn) // { dg-error "redeclared" "" }
+
+#undef fn
+#define fn pfx(func_def_gnuin_redef)
+gnuindef(fn, 0) // { dg-error "previous" "" }
+gnuindef(fn, 1) // { dg-error "redefinition" "" }
+
+#undef fn
+#define fn pfx(func_def_inline_redef)
+def(inline, fn, 0) // { dg-error "previous" "" }
+def(inline, fn, 1) // { dg-error "redefinition" "" }
+
+#undef fn
+#define fn pfx(func_def_inline_after)
+gnuindef(fn, 0) // { dg-error "previous" "" }
+def(inline, fn, 1) // { dg-error "redeclare" "" }
+
+#undef fn
+#define fn pfx(func_def_inline_before)
+def(inline, fn, 0) // { dg-error "previous" "" }
+gnuindef(fn, 1) // { dg-error "redefinition" "" }
+
+#undef fn
+#define fn pfx(func_def_before)
+def(, fn, 0) // { dg-error "previous" "" }
+gnuindef(fn, 1) // { dg-error "redefinition" "" }
+
+#undef fn
+#define fn pfx(func_decl_static_inline_before)
+decl(static inline, fn) // { dg-error "previous" "" }
+gnuindef(fn, 0) // { dg-error "redeclared" "" }
+
+#undef fn
+#define fn pfx(func_def_static_inline_after)
+decl(static, fn)
+gnuindef(fn, 0) // { dg-error "previous" "" }
+decl(static, fn)
+def(static inline, fn, 1) // { dg-error "redeclare" "" }
--- gcc/testsuite/g++.dg/ext/gnu-inline-template-func.C.jj 2007-08-31 13:00:28.000000000 +0200
+++ gcc/testsuite/g++.dg/ext/gnu-inline-template-func.C 2007-08-31 13:00:28.000000000 +0200
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O" } */ // such that static functions are optimized out
+/* { dg-final { scan-assembler "func1" } } */
+/* { dg-final { scan-assembler "func2" } } */
+/* { dg-final { scan-assembler-not "func3" } } */
+/* { dg-final { scan-assembler "func4" } } */
+/* { dg-final { scan-assembler-not "func5" } } */
+
+#define defpfx template <typename T>
+
+#include "gnu-inline-global.C"
+
+template int func1<int>(void);
+template int func2<int>(void);
+template int func3<int>(void);
+template int func4<int>(void);
+template int func5<int>(void);
--- gcc/testsuite/g++.dg/ext/gnu-inline-common.h.jj 2007-08-31 13:00:28.000000000 +0200
+++ gcc/testsuite/g++.dg/ext/gnu-inline-common.h 2007-08-31 13:00:28.000000000 +0200
@@ -0,0 +1,24 @@
+#ifndef gnu
+# define gnu_inline __attribute__((gnu_inline)) inline
+#endif
+
+#define declspec(spec, name) spec int name (void)
+#ifdef IN_CLASS
+# define decl(spec, name)
+#else
+# define decl(spec, name) defpfx declspec(spec, name);
+#endif
+#define def(spec, name, ret) defpfx declspec(spec, name) { return ret; }
+#define gnuindef(name, ret) def(gnu_inline, name, ret)
+
+#ifndef pfx
+# ifdef IN_CLASS
+# define pfx(x) IN_CLASS::x
+# else
+# define pfx(x) x
+# endif
+#endif
+
+#ifndef defpfx
+# define defpfx
+#endif
--- gcc/testsuite/g++.dg/ext/gnu-inline-anon-namespace.C.jj 2007-08-31 13:00:28.000000000 +0200
+++ gcc/testsuite/g++.dg/ext/gnu-inline-anon-namespace.C 2007-08-31 13:00:28.000000000 +0200
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O" } */ // such that static functions are optimized out
+/* { dg-final { scan-assembler-not "func1" } } */
+/* { dg-final { scan-assembler-not "func2" } } */
+/* { dg-final { scan-assembler-not "func3" } } */
+/* { dg-final { scan-assembler-not "func4" } } */
+/* { dg-final { scan-assembler-not "func5" } } */
+
+namespace {
+#include "gnu-inline-global.C"
+}
--- gcc/testsuite/g++.dg/ext/gnu-inline-class-static.C.jj 2007-08-31 13:00:28.000000000 +0200
+++ gcc/testsuite/g++.dg/ext/gnu-inline-class-static.C 2007-08-31 13:00:28.000000000 +0200
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O" } */ // such that static functions are optimized out
+/* { dg-final { scan-assembler "func1" } } */
+/* { dg-final { scan-assembler "func2" } } */
+/* { dg-final { scan-assembler-not "func3" } } */
+/* { dg-final { scan-assembler "func4" } } */
+/* { dg-final { scan-assembler "func5" } } */
+
+#undef IN_CLASS
+#define IN_CLASS gnu_test_static
+
+struct IN_CLASS {
+ static int func1(void);
+ static int func2(void);
+ static int func3(void);
+ static int func4(void);
+ static int func5(void);
+};
+
+#include "gnu-inline-global.C"
--- gcc/testsuite/g++.dg/ext/gnu-inline-global.C.jj 2007-08-31 13:00:28.000000000 +0200
+++ gcc/testsuite/g++.dg/ext/gnu-inline-global.C 2007-08-31 13:00:28.000000000 +0200
@@ -0,0 +1,50 @@
+/* Test __attribute__((gnu_inline)).
+
+ Check that __attribute__((gnu_inline)) has no effect, in the
+ absence of extern and/or inline.
+
+ Check that we don't get out-of-line definitions for extern inline
+ gnu_inline functions, regardless of declarations or definitions.
+
+ Check that such functions can be overridden by out-of-line
+ definitions.
+
+ */
+
+/* { dg-do compile } */
+/* { dg-options "-O" } */ // such that static functions are optimized out
+/* { dg-final { scan-assembler "func1" } } */
+/* { dg-final { scan-assembler "func2" } } */
+/* { dg-final { scan-assembler-not "func3" } } */
+/* { dg-final { scan-assembler "func4" } } */
+/* { dg-final { scan-assembler-not "func5" } } */
+
+#include "gnu-inline-common.h"
+
+#undef fn
+#define fn pfx(func1) // must be emitted out-of-line
+gnuindef(fn, 0)
+def(, fn, 2)
+
+#undef fn
+#define fn pfx(func2) // must be emitted out-of-line
+decl(extern, fn)
+gnuindef(fn, 0)
+def(, fn, 2)
+
+#undef fn
+#define fn pfx(func3) // must not be emitted
+decl(extern, fn)
+gnuindef(fn, 0)
+
+#undef fn
+#define fn pfx(func4) // must be emitted out-of-line
+decl(extern, fn)
+gnuindef(fn, 0)
+def(, fn, 1)
+
+#undef fn
+#define fn pfx(func5) // must NOT be emitted, because it's static and unused
+decl(static, fn)
+gnuindef(fn, 0)
+def(, fn, 1)
--- gcc/testsuite/g++.dg/ext/gnu-inline-template-class.C.jj 2007-08-31 13:00:28.000000000 +0200
+++ gcc/testsuite/g++.dg/ext/gnu-inline-template-class.C 2007-08-31 13:00:28.000000000 +0200
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O" } */ // such that static functions are optimized out
+/* { dg-final { scan-assembler "func1" } } */
+/* { dg-final { scan-assembler "func2" } } */
+/* { dg-final { scan-assembler-not "func3" } } */
+/* { dg-final { scan-assembler "func4" } } */
+/* { dg-final { scan-assembler "func5" } } */
+
+template <typename T> struct gnu_test {
+ int func1(void);
+ int func2(void);
+ int func3(void);
+ int func4(void);
+ int func5(void);
+};
+
+#define defpfx template <typename T>
+#define IN_CLASS gnu_test<T>
+
+#include "gnu-inline-global.C"
+
+template struct gnu_test<int>;
--- gcc/testsuite/g++.dg/ext/gnu-inline-namespace.C.jj 2007-08-31 13:00:28.000000000 +0200
+++ gcc/testsuite/g++.dg/ext/gnu-inline-namespace.C 2007-08-31 13:00:28.000000000 +0200
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O" } */ // such that static functions are optimized out
+/* { dg-final { scan-assembler "func1" } } */
+/* { dg-final { scan-assembler "func2" } } */
+/* { dg-final { scan-assembler-not "func3" } } */
+/* { dg-final { scan-assembler "func4" } } */
+/* { dg-final { scan-assembler-not "func5" } } */
+
+namespace gnu_test {
+#include "gnu-inline-global.C"
+}
--- gcc/testsuite/g++.dg/ext/gnu-inline-class.C.jj 2007-08-31 13:00:28.000000000 +0200
+++ gcc/testsuite/g++.dg/ext/gnu-inline-class.C 2007-08-31 13:00:28.000000000 +0200
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O" } */ // such that static functions are optimized out
+/* { dg-final { scan-assembler "func1" } } */
+/* { dg-final { scan-assembler "func2" } } */
+/* { dg-final { scan-assembler-not "func3" } } */
+/* { dg-final { scan-assembler "func4" } } */
+/* { dg-final { scan-assembler "func5" } } */
+
+#define IN_CLASS gnu_test
+
+struct IN_CLASS {
+ int func1(void);
+ int func2(void);
+ int func3(void);
+ int func4(void);
+ int func5(void);
+};
+
+#include "gnu-inline-global.C"

82
gcc41-ppc-sync-qihi.patch Normal file
View File

@ -0,0 +1,82 @@
2007-08-29 Jakub Jelinek <jakub@redhat.com>
* config/rs6000/rs6000.c (rs6000_emit_sync): For QI or HI mode
used_m, even if it is 32-bit aligned, adjust used_m MEM to have
SImode and update m. Don't run gen_lowpart_common on arbitrary
memory address, force it to register first.
* gcc.dg/sync-2.c (AI_ALIGN): Define if not defined.
(AI): Add AI_ALIGN.
* gcc.dg/sync-3.c: New test.
--- gcc/config/rs6000/rs6000.c.jj 2007-08-27 14:56:36.000000000 +0200
+++ gcc/config/rs6000/rs6000.c 2007-08-29 22:15:41.000000000 +0200
@@ -12757,14 +12757,16 @@ rs6000_emit_sync (enum rtx_code code, en
ishift = GET_MODE_BITSIZE (SImode) - GET_MODE_BITSIZE (mode);
shift = GEN_INT (ishift);
+ used_m = change_address (used_m, SImode, 0);
}
else
{
rtx addrSI, aligned_addr;
int shift_mask = mode == QImode ? 0x18 : 0x10;
- addrSI = force_reg (SImode, gen_lowpart_common (SImode,
- XEXP (used_m, 0)));
+ addrSI = gen_lowpart_common (SImode,
+ force_reg (Pmode, XEXP (used_m, 0)));
+ addrSI = force_reg (SImode, addrSI);
shift = gen_reg_rtx (SImode);
emit_insn (gen_rlwinm (shift, addrSI, GEN_INT (3),
@@ -12777,14 +12779,14 @@ rs6000_emit_sync (enum rtx_code code, en
1, OPTAB_LIB_WIDEN);
used_m = change_address (used_m, SImode, aligned_addr);
set_mem_align (used_m, 32);
- /* It's safe to keep the old alias set of USED_M, because
- the operation is atomic and only affects the original
- USED_M. */
- if (GET_CODE (m) == NOT)
- m = gen_rtx_NOT (SImode, used_m);
- else
- m = used_m;
}
+ /* It's safe to keep the old alias set of USED_M, because
+ the operation is atomic and only affects the original
+ USED_M. */
+ if (GET_CODE (m) == NOT)
+ m = gen_rtx_NOT (SImode, used_m);
+ else
+ m = used_m;
if (GET_CODE (op) == NOT)
{
--- gcc/testsuite/gcc.dg/sync-2.c.jj 2006-10-05 00:25:32.000000000 +0200
+++ gcc/testsuite/gcc.dg/sync-2.c 2007-08-29 21:49:47.000000000 +0200
@@ -8,7 +8,11 @@
extern void abort (void);
extern void *memcpy (void *, const void *, __SIZE_TYPE__);
-static char AI[18];
+#ifndef AI_ALIGN
+#define AI_ALIGN
+#endif
+
+static char AI[18] AI_ALIGN;
static char init_qi[18] = { 3,5,7,9,0,0,0,0,-1,0,0,0,0,0,-1,0,0,0 };
static char test_qi[18] = { 3,5,7,9,1,4,22,-12,7,8,9,7,1,-12,7,8,9,7 };
--- gcc/testsuite/gcc.dg/sync-3.c.jj 2007-08-29 21:49:59.000000000 +0200
+++ gcc/testsuite/gcc.dg/sync-3.c 2007-08-29 22:00:31.000000000 +0200
@@ -0,0 +1,10 @@
+/* { dg-do run } */
+/* { dg-require-effective-target sync_char_short } */
+/* { dg-options "-O2" } */
+/* { dg-options "-march=i486 -O2" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */
+/* { dg-options "-mcpu=v9 -O2" { target sparc*-*-* } } */
+
+/* Test functionality of the intrinsics for 'short' and 'char'. */
+
+#define AI_ALIGN __attribute__((__aligned__ (4)))
+#include "sync-2.c"

View File

@ -0,0 +1,86 @@
2007-08-27 Jakub Jelinek <jakub@redhat.com>
* config/rs6000/rs6000.c (rs6000_elf_end_indicate_exec_stack): New.
* config/rs6000/linux64.h (TARGET_ASM_FILE_END): Use
rs6000_elf_end_indicate_exec_stack.
* config/ia64/ia64.c (ia64_linux_file_end): new.
* config/ia64/linux.h (TARGET_ASM_FILE_END): Use ia64_linux_file_end.
--- gcc/config/rs6000/rs6000.c.jj 2007-06-27 12:10:19.000000000 +0200
+++ gcc/config/rs6000/rs6000.c 2007-08-27 19:27:24.000000000 +0200
@@ -638,6 +638,7 @@ static void rs6000_file_start (void);
static unsigned int rs6000_elf_section_type_flags (tree, const char *, int);
static void rs6000_elf_asm_out_constructor (rtx, int);
static void rs6000_elf_asm_out_destructor (rtx, int);
+static void rs6000_elf_end_indicate_exec_stack (void) ATTRIBUTE_UNUSED;
static void rs6000_elf_select_section (tree, int, unsigned HOST_WIDE_INT);
static void rs6000_elf_unique_section (tree, int);
static void rs6000_elf_select_rtx_section (enum machine_mode, rtx,
@@ -18896,6 +18897,20 @@ rs6000_elf_declare_function_name (FILE *
}
ASM_OUTPUT_LABEL (file, name);
}
+
+static void
+rs6000_elf_end_indicate_exec_stack (void)
+{
+ if (TARGET_32BIT)
+ file_end_indicate_exec_stack ();
+ else
+ {
+ int saved_trampolines_created = trampolines_created;
+ trampolines_created = 0;
+ file_end_indicate_exec_stack ();
+ trampolines_created = saved_trampolines_created;
+ }
+}
#endif
#if TARGET_XCOFF
--- gcc/config/rs6000/linux64.h.jj 2006-11-08 17:53:15.000000000 +0100
+++ gcc/config/rs6000/linux64.h 2007-08-27 19:25:09.000000000 +0200
@@ -549,7 +549,7 @@ while (0)
#undef DRAFT_V4_STRUCT_RET
#define DRAFT_V4_STRUCT_RET (!TARGET_64BIT)
-#define TARGET_ASM_FILE_END file_end_indicate_exec_stack
+#define TARGET_ASM_FILE_END rs6000_elf_end_indicate_exec_stack
#define TARGET_POSIX_IO
--- gcc/config/ia64/linux.h.jj 2006-07-14 18:00:58.000000000 +0200
+++ gcc/config/ia64/linux.h 2007-08-27 19:21:12.000000000 +0200
@@ -5,7 +5,7 @@
#define TARGET_VERSION fprintf (stderr, " (IA-64) Linux");
-#define TARGET_ASM_FILE_END file_end_indicate_exec_stack
+#define TARGET_ASM_FILE_END ia64_linux_file_end
/* This is for -profile to use -lc_p instead of -lc. */
#undef CC1_SPEC
--- gcc/config/ia64/ia64.c.jj 2007-01-05 23:54:11.000000000 +0100
+++ gcc/config/ia64/ia64.c 2007-08-27 19:21:43.000000000 +0200
@@ -246,6 +246,8 @@ static void ia64_hpux_add_extern_decl (t
ATTRIBUTE_UNUSED;
static void ia64_hpux_file_end (void)
ATTRIBUTE_UNUSED;
+static void ia64_linux_file_end (void)
+ ATTRIBUTE_UNUSED;
static void ia64_init_libfuncs (void)
ATTRIBUTE_UNUSED;
static void ia64_hpux_init_libfuncs (void)
@@ -9096,4 +9098,13 @@ ia64_invalid_binary_op (int op ATTRIBUTE
return NULL;
}
+static void
+ia64_linux_file_end (void)
+{
+ int saved_trampolines_created = trampolines_created;
+ trampolines_created = 0;
+ file_end_indicate_exec_stack ();
+ trampolines_created = saved_trampolines_created;
+}
+
#include "gt-ia64.h"

View File

@ -46,7 +46,7 @@
@@ -0,0 +1,44 @@
+/* PR middle-end/32912 */
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+/* { dg-options "-O2 -w" } */
+
+extern void abort (void);
+
@ -92,7 +92,7 @@
+++ gcc/testsuite/gcc.dg/pr32912-2.c 2007-08-20 15:55:32.000000000 +0200
@@ -0,0 +1,45 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+/* { dg-options "-O2 -w" } */
+
+extern void abort (void);
+

View File

@ -1,6 +1,6 @@
%define DATE 20070821
%define gcc_version 4.1.2
%define gcc_release 19
%define gcc_release 20
%define _unpackaged_files_terminate_build 0
%define multilib_64_archs sparc64 ppc64 s390x x86_64
%define include_gappletviewer 1
@ -144,10 +144,13 @@ Patch27: gcc41-pr32912.patch
Patch28: gcc41-sparc-niagara.patch
Patch29: gcc41-ppc-tramp.patch
Patch30: gcc41-rh253102.patch
Patch31: gcc41-c++-gnu_inline.patch
Patch32: gcc41-ppc-sync-qihi.patch
Patch33: gcc41-ppc64-ia64-GNU-stack.patch
# On ARM EABI systems, we do want -gnueabi to be part of the
# target triple.
%ifnarch %{arm}
# On ARM EABI systems, we do want -gnueabi to be part of the
# target triple.
%ifnarch %{arm}
%define _gnu %{nil}
%endif
%ifarch sparc
@ -457,6 +460,9 @@ which are required to run programs compiled with the GNAT.
%patch28 -p0 -b .sparc-niagara~
%patch29 -p0 -b .ppc-tramp~
%patch30 -p0 -b .rh253102~
%patch31 -p0 -b .c++-gnu_inline~
%patch32 -p0 -b .ppc-sync-qihi~
%patch33 -p0 -b .ppc64-ia64-GNU-stack~
sed -i -e 's/4\.1\.3/4.1.2/' gcc/BASE-VER gcc/version.c
sed -i -e 's/" (Red Hat[^)]*)"/" (Red Hat %{version}-%{gcc_release})"/' gcc/version.c
@ -1591,6 +1597,13 @@ fi
%doc rpm.doc/changelogs/libmudflap/ChangeLog*
%changelog
* Fri Aug 31 2007 Jakub Jelinek <jakub@redhat.com> 4.1.2-20
- backport __attribute__((__gnu_inline__)) support for C++
- fix ppc/ppc64 __sync_* builtins with aligned 8 or 16-bit values
- don't set executable flag on .note.GNU-stack on ppc64/ia64 even
when trampolines are used - trampolines on those architectures
don't need executable stack
* Tue Aug 21 2007 Jakub Jelinek <jakub@redhat.com> 4.1.2-19
- update from gcc-4_1-branch (-r127528:127672)
- PR c++/32112
@ -1624,7 +1637,7 @@ fi
to binutils that support it (Roland McGrath)
- backport ARM fixes from trunk (#246800)
- PRs middle-end/24998, target/28516, target/30486
- fix simplify_plus_minus with ppc{,64} power6 tuning (regression from
- fix simplify_plus_minus with ppc{,64} power6 tuning (regression from
4.1.1-52.el5.2, #247256)
* Wed Jul 4 2007 Jakub Jelinek <jakub@redhat.com> 4.1.2-15