diff --git a/gcc41-c++-gnu_inline.patch b/gcc41-c++-gnu_inline.patch new file mode 100644 index 0000000..5175a3d --- /dev/null +++ b/gcc41-c++-gnu_inline.patch @@ -0,0 +1,608 @@ +2007-08-31 Jakub Jelinek + + * 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 + + * gcc.dg/inline-24.c: New test. + * g++.dg/opt/inline11.C: New test. + +2007-08-27 Alexandre Oliva + + * 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 % attribute"; ++ else ++ return "%q+D redeclared inline without % 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 % attribute"; ++ else ++ return "%q+D redeclared inline without % 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 ++ ++#include "gnu-inline-global.C" ++ ++template int func1(void); ++template int func2(void); ++template int func3(void); ++template int func4(void); ++template int func5(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 struct gnu_test { ++ int func1(void); ++ int func2(void); ++ int func3(void); ++ int func4(void); ++ int func5(void); ++}; ++ ++#define defpfx template ++#define IN_CLASS gnu_test ++ ++#include "gnu-inline-global.C" ++ ++template struct gnu_test; +--- 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" diff --git a/gcc41-ppc-sync-qihi.patch b/gcc41-ppc-sync-qihi.patch new file mode 100644 index 0000000..cf73e8a --- /dev/null +++ b/gcc41-ppc-sync-qihi.patch @@ -0,0 +1,82 @@ +2007-08-29 Jakub Jelinek + + * 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" diff --git a/gcc41-ppc64-ia64-GNU-stack.patch b/gcc41-ppc64-ia64-GNU-stack.patch new file mode 100644 index 0000000..655f0fe --- /dev/null +++ b/gcc41-ppc64-ia64-GNU-stack.patch @@ -0,0 +1,86 @@ +2007-08-27 Jakub Jelinek + + * 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" diff --git a/gcc41.spec b/gcc41.spec index dedb119..b483750 100644 --- a/gcc41.spec +++ b/gcc41.spec @@ -1,6 +1,6 @@ %define DATE 20070821 %define gcc_version 4.1.2 -%define gcc_release 18 +%define gcc_release 20 %define _unpackaged_files_terminate_build 0 %define multilib_64_archs sparc64 ppc64 s390x x86_64 %define include_gappletviewer 1 @@ -142,6 +142,9 @@ 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. @@ -455,6 +458,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 @@ -879,7 +885,7 @@ mv -f $RPM_BUILD_ROOT%{_prefix}/%{_lib}/libgfortran.*a . mv -f $RPM_BUILD_ROOT%{_prefix}/%{_lib}/libgfortranbegin.*a . mv -f $RPM_BUILD_ROOT%{_prefix}/%{_lib}/libobjc.*a . mv -f $RPM_BUILD_ROOT%{_prefix}/%{_lib}/libgomp.*a . -mv -f $RPM_BUILD_ROOT%{_prefix}/%{_lib}/libmudflap{,th}.*a . +mv -f $RPM_BUILD_ROOT%{_prefix}/%{_lib}/libmudflap{,th}.*a $FULLLPATH/ mv -f $RPM_BUILD_ROOT%{_prefix}/include/mf-runtime.h include/ %ifarch sparc ppc @@ -901,9 +907,12 @@ mv -f $RPM_BUILD_ROOT%{_prefix}/lib64/libgfortran.*a 64/ mv -f $RPM_BUILD_ROOT%{_prefix}/lib64/libgfortranbegin.*a 64/ mv -f $RPM_BUILD_ROOT%{_prefix}/lib64/libobjc.*a 64/ mv -f $RPM_BUILD_ROOT%{_prefix}/lib64/libgomp.*a 64/ -mv -f $RPM_BUILD_ROOT%{_prefix}/lib64/libmudflap{,th}.*a 64/ ln -sf lib32/libstdc++.a libstdc++.a ln -sf ../lib64/libstdc++.a 64/libstdc++.a +ln -sf lib32/libmudflap.a libmudflap.a +ln -sf ../lib64/libmudflap.a 64/libmudflap.a +ln -sf lib32/libmudflapth.a libmudflapth.a +ln -sf ../lib64/libmudflapth.a 64/libmudflapth.a %endif %ifarch %{multilib_64_archs} mkdir -p 32 @@ -923,11 +932,14 @@ mv -f $RPM_BUILD_ROOT%{_prefix}/lib/libgfortran.*a 32/ mv -f $RPM_BUILD_ROOT%{_prefix}/lib/libgfortranbegin.*a 32/ mv -f $RPM_BUILD_ROOT%{_prefix}/lib/libobjc.*a 32/ mv -f $RPM_BUILD_ROOT%{_prefix}/lib/libgomp.*a 32/ -mv -f $RPM_BUILD_ROOT%{_prefix}/lib/libmudflap{,th}.*a 32/ %endif %ifarch sparc64 ppc64 ln -sf ../lib32/libstdc++.a 32/libstdc++.a ln -sf lib64/libstdc++.a libstdc++.a +ln -sf ../lib32/libmudflap.a 32/libmudflap.a +ln -sf lib64/libmudflap.a libmudflap.a +ln -sf ../lib32/libmudflapth.a 32/libmudflapth.a +ln -sf lib64/libmudflapth.a libmudflapth.a %if %{build_java} ln -sf ../lib32/libgcj_bc.so 32/libgcj_bc.so ln -sf lib64/libgcj_bc.so libgcj_bc.so @@ -935,6 +947,8 @@ ln -sf lib64/libgcj_bc.so libgcj_bc.so %else %ifarch %{multilib_64_archs} ln -sf ../../../%{multilib_32_arch}-%{_vendor}-%{_target_os}/%{gcc_version}/libstdc++.a 32/libstdc++.a +ln -sf ../../../%{multilib_32_arch}-%{_vendor}-%{_target_os}/%{gcc_version}/libmudflap.a 32/libmudflap.a +ln -sf ../../../%{multilib_32_arch}-%{_vendor}-%{_target_os}/%{gcc_version}/libmudflapth.a 32/libmudflapth.a %if %{build_java} ln -sf ../../../%{multilib_32_arch}-%{_vendor}-%{_target_os}/%{gcc_version}/libgcj_bc.so 32/libgcj_bc.so %endif @@ -1211,6 +1225,10 @@ fi %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_version}/64/libgcc_s.so %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_version}/64/libgomp.a %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_version}/64/libgomp.so +%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_version}/64/libmudflap.a +%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_version}/64/libmudflapth.a +%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_version}/64/libmudflap.so +%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_version}/64/libmudflapth.so %endif %ifarch %{multilib_64_archs} %dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_version}/32 @@ -1221,6 +1239,16 @@ fi %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_version}/32/libgcc_s.so %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_version}/32/libgomp.a %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_version}/32/libgomp.so +%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_version}/32/libmudflap.a +%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_version}/32/libmudflapth.a +%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_version}/32/libmudflap.so +%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_version}/32/libmudflapth.so +%endif +%ifarch sparc sparc64 ppc ppc64 +%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_version}/libmudflap.a +%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_version}/libmudflapth.a +%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_version}/libmudflap.so +%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_version}/libmudflapth.so %endif %dir %{_prefix}/libexec/getconf %{_prefix}/libexec/getconf/default @@ -1568,27 +1596,34 @@ fi %dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_version} %dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_version}/include %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_version}/include/mf-runtime.h +%ifarch sparc ppc +%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_version}/lib32 +%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_version}/lib32/libmudflap.a +%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_version}/lib32/libmudflapth.a +%endif +%ifarch sparc64 ppc64 +%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_version}/lib64 +%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_version}/lib64/libmudflap.a +%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_version}/lib64/libmudflapth.a +%endif +%ifnarch sparc sparc64 ppc ppc64 %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_version}/libmudflap.a %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_version}/libmudflapth.a %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_version}/libmudflap.so %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_version}/libmudflapth.so -%ifarch sparc ppc -%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_version}/64 -%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_version}/64/libmudflap.a -%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_version}/64/libmudflapth.a -%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_version}/64/libmudflap.so -%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_version}/64/libmudflapth.so -%endif -%ifarch %{multilib_64_archs} -%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_version}/32 -%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_version}/32/libmudflap.a -%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_version}/32/libmudflapth.a -%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_version}/32/libmudflap.so -%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_version}/32/libmudflapth.so %endif %doc rpm.doc/changelogs/libmudflap/ChangeLog* %changelog +* Sat Sep 1 2007 Jakub Jelinek 4.1.2-20.fc7 +- fix libmudflap-devel multilib conflict on ppc/ppc64 and sparc/sparc64 + (#270281) +- 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 + * Mon Aug 27 2007 Jakub Jelinek 4.1.2-18.fc7 - update from gcc-4_1-branch (-r124365:127672) - PRs c++/32112, c++/17763, rtl-optimization/32450, target/31331,