4.1.2-20
This commit is contained in:
parent
34b340a5bb
commit
95df1c0db6
608
gcc41-c++-gnu_inline.patch
Normal file
608
gcc41-c++-gnu_inline.patch
Normal 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
82
gcc41-ppc-sync-qihi.patch
Normal 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"
|
86
gcc41-ppc64-ia64-GNU-stack.patch
Normal file
86
gcc41-ppc64-ia64-GNU-stack.patch
Normal 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"
|
@ -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);
|
||||
+
|
||||
|
15
gcc41.spec
15
gcc41.spec
@ -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,6 +144,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.
|
||||
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user