4.1.2-28
This commit is contained in:
parent
764e3b5c01
commit
e198454f27
@ -1 +1 @@
|
||||
gcc-4.1.2-20070821.tar.bz2
|
||||
gcc-4.1.2-20070925.tar.bz2
|
||||
|
4198
gcc41-artificial-attrib.patch
Normal file
4198
gcc41-artificial-attrib.patch
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,37 +0,0 @@
|
||||
2007-09-06 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR c++/33289
|
||||
* decl.c (builtin_function_1): Set DECL_ANTICIPATED also
|
||||
on __*_chk non-__builtin_* decls.
|
||||
|
||||
* g++.dg/eh/builtin4.C: New test.
|
||||
|
||||
--- gcc/cp/decl.c.jj 2007-08-31 14:28:19.000000000 +0200
|
||||
+++ gcc/cp/decl.c 2007-09-04 21:28:06.000000000 +0200
|
||||
@@ -3517,6 +3529,17 @@ builtin_function_1 (tree decl, tree cont
|
||||
anticipated but not actually declared. */
|
||||
if (name[0] != '_' || name[1] != '_')
|
||||
DECL_ANTICIPATED (decl) = 1;
|
||||
+ else if (strncmp (name + 2, "builtin_", strlen ("builtin_")) != 0)
|
||||
+ {
|
||||
+ size_t len = strlen (name);
|
||||
+
|
||||
+ /* Treat __*_chk fortification functions as anticipated as well,
|
||||
+ unless they are __builtin_*. */
|
||||
+ if (len > strlen ("___chk")
|
||||
+ && memcmp (name + len - strlen ("_chk"),
|
||||
+ "_chk", strlen ("_chk") + 1) == 0)
|
||||
+ DECL_ANTICIPATED (decl) = 1;
|
||||
+ }
|
||||
|
||||
return decl;
|
||||
}
|
||||
--- gcc/testsuite/g++.dg/eh/builtin4.C.jj 2007-09-04 22:06:06.000000000 +0200
|
||||
+++ gcc/testsuite/g++.dg/eh/builtin4.C 2007-09-04 22:07:03.000000000 +0200
|
||||
@@ -0,0 +1,6 @@
|
||||
+// PR c++/33289
|
||||
+// { dg-do compile }
|
||||
+
|
||||
+typedef __SIZE_TYPE__ size_t;
|
||||
+extern "C" int __sprintf_chk (char *__restrict, int, size_t, const char *, ...) throw ();
|
||||
+extern "C" int __sprintf_chk (char *__restrict, int, size_t, const char *, ...) throw ();
|
@ -1,134 +0,0 @@
|
||||
2007-09-06 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* builtin-attrs.def (ATTR_NONNULL_3): New.
|
||||
(DEF_FORMAT_ATTRIBUTE): Use just ATTR_NONNULL_##FA instead of
|
||||
ATTR_NOTHROW_NONNULL_##FA.
|
||||
(DEF_FORMAT_ATTRIBUTE_NOTHROW, DEF_FORMAT_ATTRIBUTE_BOTH): New macros.
|
||||
(ATTR_FORMAT_PRINTF_NOTHROW_2_0, ATTR_PRINTF_NOTHROW_2_3,
|
||||
ATTR_FORMAT_PRINTF_NOTHROW_3_0, ATTR_FORMAT_PRINTF_NOTHROW_3_4,
|
||||
ATTR_FORMAT_PRINTF_NOTHROW_4_0, ATTR_PRINTF_NOTHROW_4_5,
|
||||
ATTR_FORMAT_PRINTF_NOTHROW_5_0, ATTR_FORMAT_PRINTF_NOTHROW_5_6,
|
||||
ATTR_FORMAT_SCANF_NOTHROW_2_0, ATTR_FORMAT_SCANF_NOTHROW_2_3,
|
||||
ATTR_FORMAT_STRFTIME_NOTHROW_3_0, ATTR_FORMAT_STRFMON_NOTHROW_3_4):
|
||||
New.
|
||||
(ATTR_FORMAT_PRINTF_4_0, ATTR_PRINTF_4_5, ATTR_FORMAT_PRINTF_5_0,
|
||||
ATTR_FORMAT_PRINTF_5_6, ATTR_FORMAT_STRFTIME_3_0,
|
||||
ATTR_FORMAT_NOTHROW_3_4): Remove.
|
||||
* builtins.def (snprintf, sprintf, sscanf, vsnprintf, vsprintf,
|
||||
vsscanf, strfmon, strftime, __snprintf_chk, __sprintf_chk,
|
||||
__vsnprintf_chk, __vsprintf_chk): Use ATTR_FORMAT_*_NOTHROW_*
|
||||
instead of ATTR_FORMAT_*_*.
|
||||
|
||||
--- gcc/builtin-attrs.def.jj 2007-08-13 15:11:18.000000000 +0200
|
||||
+++ gcc/builtin-attrs.def 2007-09-03 11:26:13.000000000 +0200
|
||||
@@ -118,6 +118,8 @@ DEF_ATTR_TREE_LIST (ATTR_NONNULL_LIST, A
|
||||
DEF_ATTR_TREE_LIST (ATTR_NONNULL_1, ATTR_NONNULL, ATTR_LIST_1, ATTR_NULL)
|
||||
/* Functions whose second parameter is a nonnull pointer. */
|
||||
DEF_ATTR_TREE_LIST (ATTR_NONNULL_2, ATTR_NONNULL, ATTR_LIST_2, ATTR_NULL)
|
||||
+/* Functions whose third parameter is a nonnull pointer. */
|
||||
+DEF_ATTR_TREE_LIST (ATTR_NONNULL_3, ATTR_NONNULL, ATTR_LIST_3, ATTR_NULL)
|
||||
/* Nothrow functions with the sentinel(1) attribute. */
|
||||
DEF_ATTR_TREE_LIST (ATTR_NOTHROW_SENTINEL_1, ATTR_SENTINEL, ATTR_LIST_1, \
|
||||
ATTR_NOTHROW_LIST)
|
||||
@@ -157,24 +159,38 @@ DEF_ATTR_TREE_LIST (ATTR_MALLOC_NOTHROW_
|
||||
DEF_ATTR_TREE_LIST (ATTR_##TYPE##_##VALUES, ATTR_NULL, \
|
||||
ATTR_##TYPE, ATTR_LIST_##VALUES) \
|
||||
DEF_ATTR_TREE_LIST (ATTR_FORMAT_##TYPE##_##VALUES, ATTR_FORMAT, \
|
||||
+ ATTR_##TYPE##_##VALUES, ATTR_NONNULL_##FA)
|
||||
+#define DEF_FORMAT_ATTRIBUTE_NOTHROW(TYPE, FA, VALUES) \
|
||||
+ DEF_ATTR_TREE_LIST (ATTR_##TYPE##_##VALUES, ATTR_NULL, \
|
||||
+ ATTR_##TYPE, ATTR_LIST_##VALUES) \
|
||||
+ DEF_ATTR_TREE_LIST (ATTR_FORMAT_##TYPE##_NOTHROW_##VALUES, ATTR_FORMAT,\
|
||||
+ ATTR_##TYPE##_##VALUES, ATTR_NOTHROW_NONNULL_##FA)
|
||||
+#define DEF_FORMAT_ATTRIBUTE_BOTH(TYPE, FA, VALUES) \
|
||||
+ DEF_ATTR_TREE_LIST (ATTR_##TYPE##_##VALUES, ATTR_NULL, \
|
||||
+ ATTR_##TYPE, ATTR_LIST_##VALUES) \
|
||||
+ DEF_ATTR_TREE_LIST (ATTR_FORMAT_##TYPE##_##VALUES, ATTR_FORMAT, \
|
||||
+ ATTR_##TYPE##_##VALUES, ATTR_NONNULL_##FA) \
|
||||
+ DEF_ATTR_TREE_LIST (ATTR_FORMAT_##TYPE##_NOTHROW_##VALUES, ATTR_FORMAT,\
|
||||
ATTR_##TYPE##_##VALUES, ATTR_NOTHROW_NONNULL_##FA)
|
||||
DEF_FORMAT_ATTRIBUTE(PRINTF,1,1_0)
|
||||
DEF_FORMAT_ATTRIBUTE(PRINTF,1,1_2)
|
||||
-DEF_FORMAT_ATTRIBUTE(PRINTF,2,2_0)
|
||||
-DEF_FORMAT_ATTRIBUTE(PRINTF,2,2_3)
|
||||
-DEF_FORMAT_ATTRIBUTE(PRINTF,3,3_0)
|
||||
-DEF_FORMAT_ATTRIBUTE(PRINTF,3,3_4)
|
||||
-DEF_FORMAT_ATTRIBUTE(PRINTF,4,4_0)
|
||||
-DEF_FORMAT_ATTRIBUTE(PRINTF,4,4_5)
|
||||
-DEF_FORMAT_ATTRIBUTE(PRINTF,5,5_0)
|
||||
-DEF_FORMAT_ATTRIBUTE(PRINTF,5,5_6)
|
||||
+DEF_FORMAT_ATTRIBUTE_BOTH(PRINTF,2,2_0)
|
||||
+DEF_FORMAT_ATTRIBUTE_BOTH(PRINTF,2,2_3)
|
||||
+DEF_FORMAT_ATTRIBUTE_BOTH(PRINTF,3,3_0)
|
||||
+DEF_FORMAT_ATTRIBUTE_BOTH(PRINTF,3,3_4)
|
||||
+DEF_FORMAT_ATTRIBUTE_NOTHROW(PRINTF,4,4_0)
|
||||
+DEF_FORMAT_ATTRIBUTE_NOTHROW(PRINTF,4,4_5)
|
||||
+DEF_FORMAT_ATTRIBUTE_NOTHROW(PRINTF,5,5_0)
|
||||
+DEF_FORMAT_ATTRIBUTE_NOTHROW(PRINTF,5,5_6)
|
||||
DEF_FORMAT_ATTRIBUTE(SCANF,1,1_0)
|
||||
DEF_FORMAT_ATTRIBUTE(SCANF,1,1_2)
|
||||
-DEF_FORMAT_ATTRIBUTE(SCANF,2,2_0)
|
||||
-DEF_FORMAT_ATTRIBUTE(SCANF,2,2_3)
|
||||
-DEF_FORMAT_ATTRIBUTE(STRFTIME,3,3_0)
|
||||
-DEF_FORMAT_ATTRIBUTE(STRFMON,3,3_4)
|
||||
+DEF_FORMAT_ATTRIBUTE_BOTH(SCANF,2,2_0)
|
||||
+DEF_FORMAT_ATTRIBUTE_BOTH(SCANF,2,2_3)
|
||||
+DEF_FORMAT_ATTRIBUTE_NOTHROW(STRFTIME,3,3_0)
|
||||
+DEF_FORMAT_ATTRIBUTE_NOTHROW(STRFMON,3,3_4)
|
||||
#undef DEF_FORMAT_ATTRIBUTE
|
||||
+#undef DEF_FORMAT_ATTRIBUTE_NOTHROW
|
||||
+#undef DEF_FORMAT_ATTRIBUTE_BOTH
|
||||
|
||||
/* Construct a tree for a format_arg attribute. */
|
||||
#define DEF_FORMAT_ARG_ATTRIBUTE(FA) \
|
||||
--- gcc/builtins.def.jj 2007-08-30 18:46:59.000000000 +0200
|
||||
+++ gcc/builtins.def 2007-09-03 10:52:18.000000000 +0200
|
||||
@@ -553,16 +553,16 @@ DEF_EXT_LIB_BUILTIN (BUILT_IN_PUTCHAR
|
||||
DEF_LIB_BUILTIN (BUILT_IN_PUTS, "puts", BT_FN_INT_CONST_STRING, ATTR_NONNULL_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_PUTS_UNLOCKED, "puts_unlocked", BT_FN_INT_CONST_STRING, ATTR_NONNULL_LIST)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_SCANF, "scanf", BT_FN_INT_CONST_STRING_VAR, ATTR_FORMAT_SCANF_1_2)
|
||||
-DEF_C99_BUILTIN (BUILT_IN_SNPRINTF, "snprintf", BT_FN_INT_STRING_SIZE_CONST_STRING_VAR, ATTR_FORMAT_PRINTF_3_4)
|
||||
-DEF_LIB_BUILTIN (BUILT_IN_SPRINTF, "sprintf", BT_FN_INT_STRING_CONST_STRING_VAR, ATTR_FORMAT_PRINTF_2_3)
|
||||
-DEF_LIB_BUILTIN (BUILT_IN_SSCANF, "sscanf", BT_FN_INT_CONST_STRING_CONST_STRING_VAR, ATTR_FORMAT_SCANF_2_3)
|
||||
+DEF_C99_BUILTIN (BUILT_IN_SNPRINTF, "snprintf", BT_FN_INT_STRING_SIZE_CONST_STRING_VAR, ATTR_FORMAT_PRINTF_NOTHROW_3_4)
|
||||
+DEF_LIB_BUILTIN (BUILT_IN_SPRINTF, "sprintf", BT_FN_INT_STRING_CONST_STRING_VAR, ATTR_FORMAT_PRINTF_NOTHROW_2_3)
|
||||
+DEF_LIB_BUILTIN (BUILT_IN_SSCANF, "sscanf", BT_FN_INT_CONST_STRING_CONST_STRING_VAR, ATTR_FORMAT_SCANF_NOTHROW_2_3)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_VFPRINTF, "vfprintf", BT_FN_INT_FILEPTR_CONST_STRING_VALIST_ARG, ATTR_FORMAT_PRINTF_2_0)
|
||||
DEF_C99_BUILTIN (BUILT_IN_VFSCANF, "vfscanf", BT_FN_INT_FILEPTR_CONST_STRING_VALIST_ARG, ATTR_FORMAT_SCANF_2_0)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_VPRINTF, "vprintf", BT_FN_INT_CONST_STRING_VALIST_ARG, ATTR_FORMAT_PRINTF_1_0)
|
||||
DEF_C99_BUILTIN (BUILT_IN_VSCANF, "vscanf", BT_FN_INT_CONST_STRING_VALIST_ARG, ATTR_FORMAT_SCANF_1_0)
|
||||
-DEF_C99_BUILTIN (BUILT_IN_VSNPRINTF, "vsnprintf", BT_FN_INT_STRING_SIZE_CONST_STRING_VALIST_ARG, ATTR_FORMAT_PRINTF_3_0)
|
||||
-DEF_LIB_BUILTIN (BUILT_IN_VSPRINTF, "vsprintf", BT_FN_INT_STRING_CONST_STRING_VALIST_ARG, ATTR_FORMAT_PRINTF_2_0)
|
||||
-DEF_C99_BUILTIN (BUILT_IN_VSSCANF, "vsscanf", BT_FN_INT_CONST_STRING_CONST_STRING_VALIST_ARG, ATTR_FORMAT_SCANF_2_0)
|
||||
+DEF_C99_BUILTIN (BUILT_IN_VSNPRINTF, "vsnprintf", BT_FN_INT_STRING_SIZE_CONST_STRING_VALIST_ARG, ATTR_FORMAT_PRINTF_NOTHROW_3_0)
|
||||
+DEF_LIB_BUILTIN (BUILT_IN_VSPRINTF, "vsprintf", BT_FN_INT_STRING_CONST_STRING_VALIST_ARG, ATTR_FORMAT_PRINTF_NOTHROW_2_0)
|
||||
+DEF_C99_BUILTIN (BUILT_IN_VSSCANF, "vsscanf", BT_FN_INT_CONST_STRING_CONST_STRING_VALIST_ARG, ATTR_FORMAT_SCANF_NOTHROW_2_0)
|
||||
|
||||
/* Category: ctype builtins. */
|
||||
DEF_LIB_BUILTIN (BUILT_IN_ISALNUM, "isalnum", BT_FN_INT_INT, ATTR_PURE_NOTHROW_LIST)
|
||||
@@ -693,8 +693,8 @@ DEF_GCC_BUILTIN (BUILT_IN_RETURN_
|
||||
DEF_GCC_BUILTIN (BUILT_IN_SAVEREGS, "saveregs", BT_FN_PTR_VAR, ATTR_NULL)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_SETJMP, "setjmp", BT_FN_INT_PTR, ATTR_NULL)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_STDARG_START, "stdarg_start", BT_FN_VOID_VALIST_REF_VAR, ATTR_NULL)
|
||||
-DEF_EXT_LIB_BUILTIN (BUILT_IN_STRFMON, "strfmon", BT_FN_SSIZE_STRING_SIZE_CONST_STRING_VAR, ATTR_FORMAT_STRFMON_3_4)
|
||||
-DEF_LIB_BUILTIN (BUILT_IN_STRFTIME, "strftime", BT_FN_SIZE_STRING_SIZE_CONST_STRING_CONST_PTR, ATTR_FORMAT_STRFTIME_3_0)
|
||||
+DEF_EXT_LIB_BUILTIN (BUILT_IN_STRFMON, "strfmon", BT_FN_SSIZE_STRING_SIZE_CONST_STRING_VAR, ATTR_FORMAT_STRFMON_NOTHROW_3_4)
|
||||
+DEF_LIB_BUILTIN (BUILT_IN_STRFTIME, "strftime", BT_FN_SIZE_STRING_SIZE_CONST_STRING_CONST_PTR, ATTR_FORMAT_STRFTIME_NOTHROW_3_0)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_TRAP, "trap", BT_FN_VOID, ATTR_NORETURN_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_UNWIND_INIT, "unwind_init", BT_FN_VOID, ATTR_NULL)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_UPDATE_SETJMP_BUF, "update_setjmp_buf", BT_FN_VOID_PTR_INT, ATTR_NULL)
|
||||
@@ -730,10 +730,10 @@ DEF_EXT_LIB_BUILTIN (BUILT_IN_STRCAT_
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_STRCPY_CHK, "__strcpy_chk", BT_FN_STRING_STRING_CONST_STRING_SIZE, ATTR_NOTHROW_NONNULL)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_STRNCAT_CHK, "__strncat_chk", BT_FN_STRING_STRING_CONST_STRING_SIZE_SIZE, ATTR_NOTHROW_NONNULL)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_STRNCPY_CHK, "__strncpy_chk", BT_FN_STRING_STRING_CONST_STRING_SIZE_SIZE, ATTR_NOTHROW_NONNULL)
|
||||
-DEF_EXT_LIB_BUILTIN (BUILT_IN_SNPRINTF_CHK, "__snprintf_chk", BT_FN_INT_STRING_SIZE_INT_SIZE_CONST_STRING_VAR, ATTR_FORMAT_PRINTF_5_6)
|
||||
-DEF_EXT_LIB_BUILTIN (BUILT_IN_SPRINTF_CHK, "__sprintf_chk", BT_FN_INT_STRING_INT_SIZE_CONST_STRING_VAR, ATTR_FORMAT_PRINTF_4_5)
|
||||
-DEF_EXT_LIB_BUILTIN (BUILT_IN_VSNPRINTF_CHK, "__vsnprintf_chk", BT_FN_INT_STRING_SIZE_INT_SIZE_CONST_STRING_VALIST_ARG, ATTR_FORMAT_PRINTF_5_0)
|
||||
-DEF_EXT_LIB_BUILTIN (BUILT_IN_VSPRINTF_CHK, "__vsprintf_chk", BT_FN_INT_STRING_INT_SIZE_CONST_STRING_VALIST_ARG, ATTR_FORMAT_PRINTF_4_0)
|
||||
+DEF_EXT_LIB_BUILTIN (BUILT_IN_SNPRINTF_CHK, "__snprintf_chk", BT_FN_INT_STRING_SIZE_INT_SIZE_CONST_STRING_VAR, ATTR_FORMAT_PRINTF_NOTHROW_5_6)
|
||||
+DEF_EXT_LIB_BUILTIN (BUILT_IN_SPRINTF_CHK, "__sprintf_chk", BT_FN_INT_STRING_INT_SIZE_CONST_STRING_VAR, ATTR_FORMAT_PRINTF_NOTHROW_4_5)
|
||||
+DEF_EXT_LIB_BUILTIN (BUILT_IN_VSNPRINTF_CHK, "__vsnprintf_chk", BT_FN_INT_STRING_SIZE_INT_SIZE_CONST_STRING_VALIST_ARG, ATTR_FORMAT_PRINTF_NOTHROW_5_0)
|
||||
+DEF_EXT_LIB_BUILTIN (BUILT_IN_VSPRINTF_CHK, "__vsprintf_chk", BT_FN_INT_STRING_INT_SIZE_CONST_STRING_VALIST_ARG, ATTR_FORMAT_PRINTF_NOTHROW_4_0)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_FPRINTF_CHK, "__fprintf_chk", BT_FN_INT_FILEPTR_INT_CONST_STRING_VAR, ATTR_FORMAT_PRINTF_3_4)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_PRINTF_CHK, "__printf_chk", BT_FN_INT_INT_CONST_STRING_VAR, ATTR_FORMAT_PRINTF_2_3)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_VFPRINTF_CHK, "__vfprintf_chk", BT_FN_INT_FILEPTR_INT_CONST_STRING_VALIST_ARG, ATTR_FORMAT_PRINTF_3_0)
|
@ -1,368 +0,0 @@
|
||||
2007-09-11 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* builtins.def (BUILT_IN_VA_ARG_PACK_LEN): New builtin.
|
||||
* builtins.c (expand_builtin) <case BUILT_IN_VA_ARG_PACK_LEN>: Issue
|
||||
error if __builtin_va_arg_pack_len () wasn't optimized out during
|
||||
inlining.
|
||||
* tree-inline.c (copy_bb): Replace __builtin_va_arg_pack_len ()
|
||||
with the number of inline's anonymous arguments.
|
||||
* doc/extend.texi: Document __builtin_va_arg_pack_len ().
|
||||
|
||||
* gcc.dg/va-arg-pack-len-1.c: New test.
|
||||
* g++.dg/va-arg-pack-len-1.C: New test.
|
||||
|
||||
--- gcc/builtins.def.jj 2007-09-06 10:19:24.000000000 +0200
|
||||
+++ gcc/builtins.def 2007-09-14 21:07:41.000000000 +0200
|
||||
@@ -666,6 +666,7 @@ DEF_GCC_BUILTIN (BUILT_IN_VA_COPY
|
||||
DEF_GCC_BUILTIN (BUILT_IN_VA_END, "va_end", BT_FN_VOID_VALIST_REF, ATTR_NULL)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_VA_START, "va_start", BT_FN_VOID_VALIST_REF_VAR, ATTR_NULL)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_VA_ARG_PACK, "va_arg_pack", BT_FN_INT, ATTR_PURE_NOTHROW_LIST)
|
||||
+DEF_GCC_BUILTIN (BUILT_IN_VA_ARG_PACK_LEN, "va_arg_pack_len", BT_FN_INT, ATTR_PURE_NOTHROW_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN__EXIT, "_exit", BT_FN_VOID_INT, ATTR_NORETURN_NOTHROW_LIST)
|
||||
DEF_C99_BUILTIN (BUILT_IN__EXIT2, "_Exit", BT_FN_VOID_INT, ATTR_NORETURN_NOTHROW_LIST)
|
||||
|
||||
--- gcc/builtins.c.jj 2007-09-06 11:04:56.000000000 +0200
|
||||
+++ gcc/builtins.c 2007-09-14 21:07:41.000000000 +0200
|
||||
@@ -5985,6 +5985,12 @@ expand_builtin (tree exp, rtx target, rt
|
||||
error ("invalid use of %<__builtin_va_arg_pack ()%>");
|
||||
return const0_rtx;
|
||||
|
||||
+ case BUILT_IN_VA_ARG_PACK_LEN:
|
||||
+ /* All valid uses of __builtin_va_arg_pack_len () are removed during
|
||||
+ inlining. */
|
||||
+ error ("invalid use of %<__builtin_va_arg_pack_len ()%>");
|
||||
+ return const0_rtx;
|
||||
+
|
||||
/* Return the address of the first anonymous stack arg. */
|
||||
case BUILT_IN_NEXT_ARG:
|
||||
if (fold_builtin_next_arg (arglist))
|
||||
--- gcc/tree-inline.c.jj 2007-09-06 12:35:57.000000000 +0200
|
||||
+++ gcc/tree-inline.c 2007-09-14 21:22:48.000000000 +0200
|
||||
@@ -741,6 +741,37 @@ copy_bb (copy_body_data *id, basic_block
|
||||
*a = copy_list (arglist);
|
||||
CALL_EXPR_VA_ARG_PACK (call) = 0;
|
||||
}
|
||||
+ else if (call
|
||||
+ && id->call_expr
|
||||
+ && (decl = get_callee_fndecl (call))
|
||||
+ && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
|
||||
+ && DECL_FUNCTION_CODE (decl)
|
||||
+ == BUILT_IN_VA_ARG_PACK_LEN)
|
||||
+ {
|
||||
+ /* __builtin_va_arg_pack_len () should be replaced by
|
||||
+ the number of anonymous arguments. */
|
||||
+ int nargs;
|
||||
+ tree count, *call_ptr, p, a;
|
||||
+
|
||||
+ a = TREE_OPERAND (id->call_expr, 1);
|
||||
+ for (p = DECL_ARGUMENTS (id->src_fn); p; p = TREE_CHAIN (p))
|
||||
+ a = TREE_CHAIN (a);
|
||||
+
|
||||
+ for (nargs = 0; a; a = TREE_CHAIN (a))
|
||||
+ nargs++;
|
||||
+
|
||||
+ count = build_int_cst (integer_type_node, nargs);
|
||||
+ call_ptr = &stmt;
|
||||
+ if (TREE_CODE (*call_ptr) == MODIFY_EXPR)
|
||||
+ call_ptr = &TREE_OPERAND (*call_ptr, 1);
|
||||
+ if (TREE_CODE (*call_ptr) == WITH_SIZE_EXPR)
|
||||
+ call_ptr = &TREE_OPERAND (*call_ptr, 0);
|
||||
+ gcc_assert (*call_ptr == call && call_ptr != &stmt);
|
||||
+ *call_ptr = count;
|
||||
+ update_stmt (stmt);
|
||||
+ call = NULL_TREE;
|
||||
+ }
|
||||
+
|
||||
/* We're duplicating a CALL_EXPR. Find any corresponding
|
||||
callgraph edges and update or duplicate them. */
|
||||
if (call && (decl = get_callee_fndecl (call)))
|
||||
--- gcc/doc/extend.texi.jj 2007-09-06 10:19:25.000000000 +0200
|
||||
+++ gcc/doc/extend.texi 2007-09-14 21:07:41.000000000 +0200
|
||||
@@ -578,6 +578,41 @@ myprintf (FILE *f, const char *format, .
|
||||
@end smallexample
|
||||
@end deftypefn
|
||||
|
||||
+@deftypefn {Built-in Function} __builtin_va_arg_pack_len ()
|
||||
+This built-in function returns the number of anonymous arguments of
|
||||
+an inline function. It can be used only in inline functions which
|
||||
+will be always inlined, never compiled as a separate function, such
|
||||
+as those using @code{__attribute__ ((__always_inline__))} or
|
||||
+@code{__attribute__ ((__gnu_inline__))} extern inline functions.
|
||||
+For example following will do link or runtime checking of open
|
||||
+arguments for optimized code:
|
||||
+@smallexample
|
||||
+#ifdef __OPTIMIZE__
|
||||
+extern inline __attribute__((__gnu_inline__)) int
|
||||
+myopen (const char *path, int oflag, ...)
|
||||
+@{
|
||||
+ if (__builtin_va_arg_pack_len () > 1)
|
||||
+ warn_open_too_many_arguments ();
|
||||
+
|
||||
+ if (__builtin_constant_p (oflag))
|
||||
+ @{
|
||||
+ if ((oflag & O_CREAT) != 0 && __builtin_va_arg_pack_len () < 1)
|
||||
+ @{
|
||||
+ warn_open_missing_mode ();
|
||||
+ return __open_2 (path, oflag);
|
||||
+ @}
|
||||
+ return open (path, oflag, __builtin_va_arg_pack ());
|
||||
+ @}
|
||||
+
|
||||
+ if (__builtin_va_arg_pack_len () < 1)
|
||||
+ return __open_2 (path, oflag);
|
||||
+
|
||||
+ return open (path, oflag, __builtin_va_arg_pack ());
|
||||
+@}
|
||||
+#endif
|
||||
+@end smallexample
|
||||
+@end deftypefn
|
||||
+
|
||||
@node Typeof
|
||||
@section Referring to a Type with @code{typeof}
|
||||
@findex typeof
|
||||
--- gcc/testsuite/gcc.dg/va-arg-pack-len-1.c.jj 2007-09-14 21:07:41.000000000 +0200
|
||||
+++ gcc/testsuite/gcc.dg/va-arg-pack-len-1.c 2007-09-14 21:07:41.000000000 +0200
|
||||
@@ -0,0 +1,120 @@
|
||||
+/* { dg-do run } */
|
||||
+/* { dg-options "-O2" } */
|
||||
+
|
||||
+#include <stdarg.h>
|
||||
+
|
||||
+extern int warn_open_missing_mode (void);
|
||||
+extern int warn_open_too_many_arguments (void);
|
||||
+extern void abort (void);
|
||||
+
|
||||
+char expected_char;
|
||||
+
|
||||
+__attribute__((noinline)) int
|
||||
+myopen2 (const char *path, int oflag)
|
||||
+{
|
||||
+ if (expected_char++ != path[0] || path[1] != '\0')
|
||||
+ abort ();
|
||||
+ switch (path[0])
|
||||
+ {
|
||||
+ case 'f':
|
||||
+ if (oflag != 0x2)
|
||||
+ abort ();
|
||||
+ break;
|
||||
+ case 'g':
|
||||
+ if (oflag != 0x43)
|
||||
+ abort ();
|
||||
+ /* In real __open_2 this would terminate the program:
|
||||
+ open with O_CREAT without third argument. */
|
||||
+ return -6;
|
||||
+ default:
|
||||
+ abort ();
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+__attribute__((noinline)) int
|
||||
+myopenva (const char *path, int oflag, ...)
|
||||
+{
|
||||
+ int mode = 0;
|
||||
+ va_list ap;
|
||||
+ if ((oflag & 0x40) != 0)
|
||||
+ {
|
||||
+ va_start (ap, oflag);
|
||||
+ mode = va_arg (ap, int);
|
||||
+ va_end (ap);
|
||||
+ }
|
||||
+ if (expected_char++ != path[0] || path[1] != '\0')
|
||||
+ abort ();
|
||||
+ switch (path[0])
|
||||
+ {
|
||||
+ case 'a':
|
||||
+ if (oflag != 0x43 || mode != 0644)
|
||||
+ abort ();
|
||||
+ break;
|
||||
+ case 'b':
|
||||
+ if (oflag != 0x3)
|
||||
+ abort ();
|
||||
+ break;
|
||||
+ case 'c':
|
||||
+ if (oflag != 0x2)
|
||||
+ abort ();
|
||||
+ break;
|
||||
+ case 'd':
|
||||
+ if (oflag != 0x43 || mode != 0600)
|
||||
+ abort ();
|
||||
+ break;
|
||||
+ case 'e':
|
||||
+ if (oflag != 0x3)
|
||||
+ abort ();
|
||||
+ break;
|
||||
+ default:
|
||||
+ abort ();
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+extern inline __attribute__((always_inline, gnu_inline)) int
|
||||
+myopen (const char *path, int oflag, ...)
|
||||
+{
|
||||
+ if (__builtin_va_arg_pack_len () > 1)
|
||||
+ warn_open_too_many_arguments ();
|
||||
+
|
||||
+ if (__builtin_constant_p (oflag))
|
||||
+ {
|
||||
+ if ((oflag & 0x40) != 0 && __builtin_va_arg_pack_len () < 1)
|
||||
+ {
|
||||
+ warn_open_missing_mode ();
|
||||
+ return myopen2 (path, oflag);
|
||||
+ }
|
||||
+ return myopenva (path, oflag, __builtin_va_arg_pack ());
|
||||
+ }
|
||||
+
|
||||
+ if (__builtin_va_arg_pack_len () < 1)
|
||||
+ return myopen2 (path, oflag);
|
||||
+
|
||||
+ return myopenva (path, oflag, __builtin_va_arg_pack ());
|
||||
+}
|
||||
+
|
||||
+volatile int l0;
|
||||
+
|
||||
+int
|
||||
+main (void)
|
||||
+{
|
||||
+ expected_char = 'a';
|
||||
+ if (myopen ("a", 0x43, 0644))
|
||||
+ abort ();
|
||||
+ if (myopen ("b", 0x3, 0755))
|
||||
+ abort ();
|
||||
+ if (myopen ("c", 0x2))
|
||||
+ abort ();
|
||||
+ if (myopen ("d", l0 + 0x43, 0600))
|
||||
+ abort ();
|
||||
+ if (myopen ("e", l0 + 0x3, 0700))
|
||||
+ abort ();
|
||||
+ if (myopen ("f", l0 + 0x2))
|
||||
+ abort ();
|
||||
+ /* Invalid use of myopen, but only detectable at runtime. */
|
||||
+ if (myopen ("g", l0 + 0x43) != -6)
|
||||
+ abort ();
|
||||
+ return 0;
|
||||
+}
|
||||
--- gcc/testsuite/g++.dg/ext/va-arg-pack-len-1.C.jj 2007-09-14 21:07:41.000000000 +0200
|
||||
+++ gcc/testsuite/g++.dg/ext/va-arg-pack-len-1.C 2007-09-14 21:07:41.000000000 +0200
|
||||
@@ -0,0 +1,120 @@
|
||||
+// { dg-do run }
|
||||
+// { dg-options "-O2" }
|
||||
+
|
||||
+#include <stdarg.h>
|
||||
+
|
||||
+extern "C" int warn_open_missing_mode (void);
|
||||
+extern "C" int warn_open_too_many_arguments (void);
|
||||
+extern "C" void abort (void);
|
||||
+
|
||||
+char expected_char;
|
||||
+
|
||||
+__attribute__((noinline)) int
|
||||
+myopen2 (const char *path, int oflag)
|
||||
+{
|
||||
+ if (expected_char++ != path[0] || path[1] != '\0')
|
||||
+ abort ();
|
||||
+ switch (path[0])
|
||||
+ {
|
||||
+ case 'f':
|
||||
+ if (oflag != 0x2)
|
||||
+ abort ();
|
||||
+ break;
|
||||
+ case 'g':
|
||||
+ if (oflag != 0x43)
|
||||
+ abort ();
|
||||
+ // In real __open_2 this would terminate the program:
|
||||
+ // open with O_CREAT without third argument.
|
||||
+ return -6;
|
||||
+ default:
|
||||
+ abort ();
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+__attribute__((noinline)) int
|
||||
+myopenva (const char *path, int oflag, ...)
|
||||
+{
|
||||
+ int mode = 0;
|
||||
+ va_list ap;
|
||||
+ if ((oflag & 0x40) != 0)
|
||||
+ {
|
||||
+ va_start (ap, oflag);
|
||||
+ mode = va_arg (ap, int);
|
||||
+ va_end (ap);
|
||||
+ }
|
||||
+ if (expected_char++ != path[0] || path[1] != '\0')
|
||||
+ abort ();
|
||||
+ switch (path[0])
|
||||
+ {
|
||||
+ case 'a':
|
||||
+ if (oflag != 0x43 || mode != 0644)
|
||||
+ abort ();
|
||||
+ break;
|
||||
+ case 'b':
|
||||
+ if (oflag != 0x3)
|
||||
+ abort ();
|
||||
+ break;
|
||||
+ case 'c':
|
||||
+ if (oflag != 0x2)
|
||||
+ abort ();
|
||||
+ break;
|
||||
+ case 'd':
|
||||
+ if (oflag != 0x43 || mode != 0600)
|
||||
+ abort ();
|
||||
+ break;
|
||||
+ case 'e':
|
||||
+ if (oflag != 0x3)
|
||||
+ abort ();
|
||||
+ break;
|
||||
+ default:
|
||||
+ abort ();
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+extern inline __attribute__((always_inline, gnu_inline)) int
|
||||
+myopen (const char *path, int oflag, ...)
|
||||
+{
|
||||
+ if (__builtin_va_arg_pack_len () > 1)
|
||||
+ warn_open_too_many_arguments ();
|
||||
+
|
||||
+ if (__builtin_constant_p (oflag))
|
||||
+ {
|
||||
+ if ((oflag & 0x40) != 0 && __builtin_va_arg_pack_len () < 1)
|
||||
+ {
|
||||
+ warn_open_missing_mode ();
|
||||
+ return myopen2 (path, oflag);
|
||||
+ }
|
||||
+ return myopenva (path, oflag, __builtin_va_arg_pack ());
|
||||
+ }
|
||||
+
|
||||
+ if (__builtin_va_arg_pack_len () < 1)
|
||||
+ return myopen2 (path, oflag);
|
||||
+
|
||||
+ return myopenva (path, oflag, __builtin_va_arg_pack ());
|
||||
+}
|
||||
+
|
||||
+volatile int l0;
|
||||
+
|
||||
+int
|
||||
+main (void)
|
||||
+{
|
||||
+ expected_char = 'a';
|
||||
+ if (myopen ("a", 0x43, 0644))
|
||||
+ abort ();
|
||||
+ if (myopen ("b", 0x3, 0755))
|
||||
+ abort ();
|
||||
+ if (myopen ("c", 0x2))
|
||||
+ abort ();
|
||||
+ if (myopen ("d", l0 + 0x43, 0600))
|
||||
+ abort ();
|
||||
+ if (myopen ("e", l0 + 0x3, 0700))
|
||||
+ abort ();
|
||||
+ if (myopen ("f", l0 + 0x2))
|
||||
+ abort ();
|
||||
+ // Invalid use of myopen, but only detectable at runtime.
|
||||
+ if (myopen ("g", l0 + 0x43) != -6)
|
||||
+ abort ();
|
||||
+ return 0;
|
||||
+}
|
@ -1,722 +0,0 @@
|
||||
2007-09-07 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* tree.c (cp_cannot_inline_tree_fn): Don't mark varargs_function_p
|
||||
as uninlinable.
|
||||
|
||||
* g++.dg/ext/va-arg-pack-1.C: New test.
|
||||
* g++.dg/ext/va-arg-pack-2.C: New test.
|
||||
|
||||
2007-09-05 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* builtins.def (BUILT_IN_VA_ARG_PACK): New built-in.
|
||||
* tree.h (CALL_EXPR_VA_ARG_PACK): Define.
|
||||
* tree-inline.h (copy_body_data): Add call_expr field.
|
||||
* tree-inline.c (expand_call_inline): Initialize call_expr.
|
||||
(copy_bb): Append anonymous inline fn arguments to arguments
|
||||
when inlining a CALL_EXPR_VA_ARG_PACK call.
|
||||
* builtins.c (expand_builtin): Issue an error if
|
||||
BUILT_IN_VA_ARG_PACK is seen during expand.
|
||||
(fold_builtin_1): Don't fold calls with
|
||||
__builtin_va_arg_pack () call as last argument.
|
||||
* gimplify.c (gimplify_call_expr): If last argument to a vararg
|
||||
function is __builtin_va_arg_pack (), decrease number of call
|
||||
arguments and instead set CALL_EXPR_VA_ARG_PACK on the CALL_EXPR.
|
||||
* fold-const.c (fold): Don't fold CALL_EXPRs with
|
||||
CALL_EXPR_VA_ARG_PACK bit set.
|
||||
* expr.c (expand_expr_real_1): Issue an error if
|
||||
CALL_EXPR_VA_ARG_PACK CALL_EXPR is seen during expand.
|
||||
* tree-pretty-print.c (dump_generic_node): Handle printing
|
||||
CALL_EXPR_VA_ARG_PACK bit on CALL_EXPRs.
|
||||
* doc/extend.texi (__builtin_va_arg_pack): Document.
|
||||
|
||||
* gcc.c-torture/execute/va-arg-pack-1.c: New test.
|
||||
* gcc.dg/va-arg-pack-1.c: New test.
|
||||
* gcc.dg/va-arg-pack-1a.c: New test.
|
||||
|
||||
--- gcc/builtins.def.jj 2007-09-06 10:19:09.000000000 +0200
|
||||
+++ gcc/builtins.def 2007-09-06 10:19:24.000000000 +0200
|
||||
@@ -665,6 +665,7 @@ DEF_GCC_BUILTIN (BUILT_IN_UPDATE_
|
||||
DEF_GCC_BUILTIN (BUILT_IN_VA_COPY, "va_copy", BT_FN_VOID_VALIST_REF_VALIST_ARG, ATTR_NULL)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_VA_END, "va_end", BT_FN_VOID_VALIST_REF, ATTR_NULL)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_VA_START, "va_start", BT_FN_VOID_VALIST_REF_VAR, ATTR_NULL)
|
||||
+DEF_GCC_BUILTIN (BUILT_IN_VA_ARG_PACK, "va_arg_pack", BT_FN_INT, ATTR_PURE_NOTHROW_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN__EXIT, "_exit", BT_FN_VOID_INT, ATTR_NORETURN_NOTHROW_LIST)
|
||||
DEF_C99_BUILTIN (BUILT_IN__EXIT2, "_Exit", BT_FN_VOID_INT, ATTR_NORETURN_NOTHROW_LIST)
|
||||
|
||||
--- gcc/tree.h.jj 2007-02-20 22:39:12.000000000 +0100
|
||||
+++ gcc/tree.h 2007-09-06 11:50:56.000000000 +0200
|
||||
@@ -411,6 +411,8 @@ struct tree_common GTY(())
|
||||
VAR_DECL or FUNCTION_DECL or IDENTIFIER_NODE
|
||||
ASM_VOLATILE_P in
|
||||
ASM_EXPR
|
||||
+ CALL_EXPR_VA_ARG_PACK in
|
||||
+ CALL_EXPR
|
||||
TYPE_CACHED_VALUES_P in
|
||||
..._TYPE
|
||||
SAVE_EXPR_RESOLVED_P in
|
||||
@@ -1066,6 +1068,11 @@ extern void omp_clause_range_check_faile
|
||||
#define SAVE_EXPR_RESOLVED_P(NODE) \
|
||||
(TREE_CHECK (NODE, SAVE_EXPR)->common.public_flag)
|
||||
|
||||
+/* Set on a CALL_EXPR if this stdarg call should be passed the argument
|
||||
+ pack. */
|
||||
+#define CALL_EXPR_VA_ARG_PACK(NODE) \
|
||||
+ (CALL_EXPR_CHECK(NODE)->common.public_flag)
|
||||
+
|
||||
/* In any expression, decl, or constant, nonzero means it has side effects or
|
||||
reevaluation of the whole expression could produce a different value.
|
||||
This is set if any subexpression is a function call, a side effect or a
|
||||
--- gcc/tree-inline.h.jj 2007-02-20 22:39:13.000000000 +0100
|
||||
+++ gcc/tree-inline.h 2007-09-06 10:19:24.000000000 +0200
|
||||
@@ -57,6 +57,10 @@ typedef struct copy_body_data
|
||||
/* Current BLOCK. */
|
||||
tree block;
|
||||
|
||||
+ /* CALL_EXPR if va arg parameter packs should be expanded or NULL
|
||||
+ is not. */
|
||||
+ tree call_expr;
|
||||
+
|
||||
/* Exception region the inlined call lie in. */
|
||||
int eh_region;
|
||||
/* Take region number in the function being copied, add this value and
|
||||
--- gcc/tree-inline.c.jj 2007-04-26 09:41:49.000000000 +0200
|
||||
+++ gcc/tree-inline.c 2007-09-06 12:35:57.000000000 +0200
|
||||
@@ -725,6 +725,22 @@ copy_bb (copy_body_data *id, basic_block
|
||||
|
||||
bsi_insert_after (©_bsi, stmt, BSI_NEW_STMT);
|
||||
call = get_call_expr_in (stmt);
|
||||
+ if (call && CALL_EXPR_VA_ARG_PACK (call) && id->call_expr)
|
||||
+ {
|
||||
+ tree arglist, *a, p;
|
||||
+ TREE_OPERAND (call, 1) = copy_list (TREE_OPERAND (call, 1));
|
||||
+
|
||||
+ for (a = &TREE_OPERAND (call, 1); *a; a = &TREE_CHAIN (*a))
|
||||
+ ;
|
||||
+
|
||||
+ p = DECL_ARGUMENTS (id->src_fn);
|
||||
+ for (arglist = TREE_OPERAND (id->call_expr, 1);
|
||||
+ p; p = TREE_CHAIN (p), arglist = TREE_CHAIN (arglist))
|
||||
+ ;
|
||||
+
|
||||
+ *a = copy_list (arglist);
|
||||
+ CALL_EXPR_VA_ARG_PACK (call) = 0;
|
||||
+ }
|
||||
/* We're duplicating a CALL_EXPR. Find any corresponding
|
||||
callgraph edges and update or duplicate them. */
|
||||
if (call && (decl = get_callee_fndecl (call)))
|
||||
@@ -2085,6 +2101,7 @@ expand_call_inline (basic_block bb, tree
|
||||
/* Record the function we are about to inline. */
|
||||
id->src_fn = fn;
|
||||
id->src_node = cg_edge->callee;
|
||||
+ id->call_expr = t;
|
||||
|
||||
initialize_inlined_parameters (id, args, TREE_OPERAND (t, 2), fn, bb);
|
||||
|
||||
--- gcc/builtins.c.jj 2007-08-31 09:47:46.000000000 +0200
|
||||
+++ gcc/builtins.c 2007-09-06 11:04:56.000000000 +0200
|
||||
@@ -5979,6 +5979,12 @@ expand_builtin (tree exp, rtx target, rt
|
||||
case BUILT_IN_ARGS_INFO:
|
||||
return expand_builtin_args_info (arglist);
|
||||
|
||||
+ case BUILT_IN_VA_ARG_PACK:
|
||||
+ /* All valid uses of __builtin_va_arg_pack () are removed during
|
||||
+ inlining. */
|
||||
+ error ("invalid use of %<__builtin_va_arg_pack ()%>");
|
||||
+ return const0_rtx;
|
||||
+
|
||||
/* Return the address of the first anonymous stack arg. */
|
||||
case BUILT_IN_NEXT_ARG:
|
||||
if (fold_builtin_next_arg (arglist))
|
||||
@@ -9017,7 +9023,27 @@ fold_builtin_1 (tree fndecl, tree arglis
|
||||
{
|
||||
tree type = TREE_TYPE (TREE_TYPE (fndecl));
|
||||
enum built_in_function fcode;
|
||||
+ tree a;
|
||||
+
|
||||
+ if (arglist)
|
||||
+ {
|
||||
+ for (a = arglist; TREE_CHAIN (a); a = TREE_CHAIN (a))
|
||||
+ ;
|
||||
|
||||
+ /* Before gimplification CALL_EXPR_VA_ARG_PACK is not set, but
|
||||
+ instead last argument is __builtin_va_arg_pack (). Defer folding
|
||||
+ even in that case, until arguments are finalized. */
|
||||
+ if (TREE_CODE (TREE_VALUE (a)) == CALL_EXPR)
|
||||
+ {
|
||||
+ tree fndecl2 = get_callee_fndecl (TREE_VALUE (a));
|
||||
+ if (fndecl2
|
||||
+ && TREE_CODE (fndecl2) == FUNCTION_DECL
|
||||
+ && DECL_BUILT_IN_CLASS (fndecl2) == BUILT_IN_NORMAL
|
||||
+ && DECL_FUNCTION_CODE (fndecl2) == BUILT_IN_VA_ARG_PACK)
|
||||
+ return NULL_TREE;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
|
||||
return targetm.fold_builtin (fndecl, arglist, ignore);
|
||||
|
||||
--- gcc/gimplify.c.jj 2007-08-31 09:47:46.000000000 +0200
|
||||
+++ gcc/gimplify.c 2007-09-06 11:42:01.000000000 +0200
|
||||
@@ -2018,6 +2018,55 @@ gimplify_call_expr (tree *expr_p, tree *
|
||||
ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, NULL,
|
||||
is_gimple_call_addr, fb_rvalue);
|
||||
|
||||
+ if (ret != GS_ERROR && TREE_OPERAND (*expr_p, 1))
|
||||
+ {
|
||||
+ int nargs;
|
||||
+
|
||||
+ for (nargs = 1, arglist = TREE_OPERAND (*expr_p, 1);
|
||||
+ TREE_CHAIN (arglist);
|
||||
+ arglist = TREE_CHAIN (arglist))
|
||||
+ nargs++;
|
||||
+
|
||||
+ if (TREE_CODE (TREE_VALUE (arglist)) == CALL_EXPR)
|
||||
+ {
|
||||
+ tree last_arg = TREE_VALUE (arglist);
|
||||
+ tree last_arg_fndecl = get_callee_fndecl (last_arg);
|
||||
+
|
||||
+ if (last_arg_fndecl
|
||||
+ && TREE_CODE (last_arg_fndecl) == FUNCTION_DECL
|
||||
+ && DECL_BUILT_IN_CLASS (last_arg_fndecl) == BUILT_IN_NORMAL
|
||||
+ && DECL_FUNCTION_CODE (last_arg_fndecl) == BUILT_IN_VA_ARG_PACK)
|
||||
+ {
|
||||
+ tree p = NULL_TREE, *aptr;
|
||||
+ int i;
|
||||
+
|
||||
+ if (decl && DECL_ARGUMENTS (decl))
|
||||
+ p = DECL_ARGUMENTS (decl);
|
||||
+ else if (decl)
|
||||
+ p = TYPE_ARG_TYPES (TREE_TYPE (decl));
|
||||
+ else if (POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (*expr_p, 0))))
|
||||
+ p = TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE
|
||||
+ (TREE_OPERAND (*expr_p, 0))));
|
||||
+ for (i = 0; p; p = TREE_CHAIN (p))
|
||||
+ i++;
|
||||
+
|
||||
+ if (i < nargs)
|
||||
+ {
|
||||
+ TREE_OPERAND (*expr_p, 1)
|
||||
+ = copy_list (TREE_OPERAND (*expr_p, 1));
|
||||
+
|
||||
+ for (aptr = &TREE_OPERAND (*expr_p, 1);
|
||||
+ TREE_CHAIN (*aptr);
|
||||
+ aptr = &TREE_CHAIN (*aptr))
|
||||
+ ;
|
||||
+
|
||||
+ *aptr = NULL_TREE;
|
||||
+ CALL_EXPR_VA_ARG_PACK (*expr_p) = 1;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
if (PUSH_ARGS_REVERSED)
|
||||
TREE_OPERAND (*expr_p, 1) = nreverse (TREE_OPERAND (*expr_p, 1));
|
||||
for (arglist = TREE_OPERAND (*expr_p, 1); arglist;
|
||||
@@ -2037,7 +2086,7 @@ gimplify_call_expr (tree *expr_p, tree *
|
||||
if (ret != GS_ERROR)
|
||||
{
|
||||
decl = get_callee_fndecl (*expr_p);
|
||||
- if (decl && DECL_BUILT_IN (decl))
|
||||
+ if (decl && DECL_BUILT_IN (decl) && !CALL_EXPR_VA_ARG_PACK (*expr_p))
|
||||
{
|
||||
tree arglist = TREE_OPERAND (*expr_p, 1);
|
||||
tree new = fold_builtin (decl, arglist, !want_value);
|
||||
--- gcc/fold-const.c.jj 2007-08-31 09:47:39.000000000 +0200
|
||||
+++ gcc/fold-const.c 2007-09-06 11:40:55.000000000 +0200
|
||||
@@ -10409,6 +10409,8 @@ fold (tree expr)
|
||||
op0 = TREE_OPERAND (t, 0);
|
||||
op1 = TREE_OPERAND (t, 1);
|
||||
op2 = TREE_OPERAND (t, 2);
|
||||
+ if (code == CALL_EXPR && CALL_EXPR_VA_ARG_PACK (t))
|
||||
+ return expr;
|
||||
tem = fold_ternary (code, type, op0, op1, op2);
|
||||
return tem ? tem : expr;
|
||||
default:
|
||||
--- gcc/expr.c.jj 2007-04-24 22:58:53.000000000 +0200
|
||||
+++ gcc/expr.c 2007-09-06 10:19:24.000000000 +0200
|
||||
@@ -7475,6 +7475,10 @@ expand_expr_real_1 (tree exp, rtx target
|
||||
return expand_expr (OBJ_TYPE_REF_EXPR (exp), target, tmode, modifier);
|
||||
|
||||
case CALL_EXPR:
|
||||
+ /* All valid uses of __builtin_va_arg_pack () are removed during
|
||||
+ inlining. */
|
||||
+ if (CALL_EXPR_VA_ARG_PACK (exp))
|
||||
+ error ("invalid use of %<__builtin_va_arg_pack ()%>");
|
||||
/* Check for a built-in function. */
|
||||
if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
|
||||
&& (TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
|
||||
--- gcc/doc/extend.texi.jj 2007-08-31 13:00:28.000000000 +0200
|
||||
+++ gcc/doc/extend.texi 2007-09-06 10:19:25.000000000 +0200
|
||||
@@ -552,6 +552,32 @@ the containing function. You should spe
|
||||
returned by @code{__builtin_apply}.
|
||||
@end deftypefn
|
||||
|
||||
+@deftypefn {Built-in Function} __builtin_va_arg_pack ()
|
||||
+This built-in function represents all anonymous arguments of an inline
|
||||
+function. It can be used only in inline functions which will be always
|
||||
+inlined, never compiled as a separate function, such as those using
|
||||
+@code{__attribute__ ((__always_inline__))} or
|
||||
+@code{__attribute__ ((__gnu_inline__))} extern inline functions.
|
||||
+It must be only passed as last argument to some other function
|
||||
+with variable arguments. This is useful for writing small wrapper
|
||||
+inlines for variable argument functions, when using preprocessor
|
||||
+macros is undesirable. For example:
|
||||
+@smallexample
|
||||
+extern int myprintf (FILE *f, const char *format, ...);
|
||||
+extern inline __attribute__ ((__gnu_inline__)) int
|
||||
+myprintf (FILE *f, const char *format, ...)
|
||||
+@{
|
||||
+ int r = fprintf (f, "myprintf: ");
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+ int s = fprintf (f, format, __builtin_va_arg_pack ());
|
||||
+ if (s < 0)
|
||||
+ return s;
|
||||
+ return r + s;
|
||||
+@}
|
||||
+@end smallexample
|
||||
+@end deftypefn
|
||||
+
|
||||
@node Typeof
|
||||
@section Referring to a Type with @code{typeof}
|
||||
@findex typeof
|
||||
--- gcc/tree-pretty-print.c.jj 2007-02-20 22:39:12.000000000 +0100
|
||||
+++ gcc/tree-pretty-print.c 2007-09-06 10:24:51.000000000 +0200
|
||||
@@ -1128,6 +1128,15 @@ dump_generic_node (pretty_printer *buffe
|
||||
op1 = TREE_OPERAND (node, 1);
|
||||
if (op1)
|
||||
dump_generic_node (buffer, op1, spc, flags, false);
|
||||
+ if (CALL_EXPR_VA_ARG_PACK (node))
|
||||
+ {
|
||||
+ if (op1)
|
||||
+ {
|
||||
+ pp_character (buffer, ',');
|
||||
+ pp_space (buffer);
|
||||
+ }
|
||||
+ pp_string (buffer, "__builtin_va_arg_pack ()");
|
||||
+ }
|
||||
pp_character (buffer, ')');
|
||||
|
||||
op1 = TREE_OPERAND (node, 2);
|
||||
--- gcc/cp/tree.c.jj 2007-03-12 08:28:01.000000000 +0100
|
||||
+++ gcc/cp/tree.c 2007-09-07 09:03:07.000000000 +0200
|
||||
@@ -2078,12 +2078,6 @@ cp_cannot_inline_tree_fn (tree* fnp)
|
||||
return 1;
|
||||
}
|
||||
|
||||
- if (varargs_function_p (fn))
|
||||
- {
|
||||
- DECL_UNINLINABLE (fn) = 1;
|
||||
- return 1;
|
||||
- }
|
||||
-
|
||||
if (! function_attribute_inlinable_p (fn))
|
||||
{
|
||||
DECL_UNINLINABLE (fn) = 1;
|
||||
--- gcc/testsuite/gcc.c-torture/execute/va-arg-pack-1.c.jj 2007-09-06 10:19:25.000000000 +0200
|
||||
+++ gcc/testsuite/gcc.c-torture/execute/va-arg-pack-1.c 2007-09-06 10:19:25.000000000 +0200
|
||||
@@ -0,0 +1,143 @@
|
||||
+/* __builtin_va_arg_pack () builtin tests. */
|
||||
+
|
||||
+#include <stdarg.h>
|
||||
+
|
||||
+extern void abort (void);
|
||||
+
|
||||
+int v1 = 8;
|
||||
+long int v2 = 3;
|
||||
+void *v3 = (void *) &v2;
|
||||
+struct A { char c[16]; } v4 = { "foo" };
|
||||
+long double v5 = 40;
|
||||
+char seen[20];
|
||||
+int cnt;
|
||||
+
|
||||
+__attribute__ ((noinline)) int
|
||||
+foo1 (int x, int y, ...)
|
||||
+{
|
||||
+ int i;
|
||||
+ long int l;
|
||||
+ void *v;
|
||||
+ struct A a;
|
||||
+ long double ld;
|
||||
+ va_list ap;
|
||||
+
|
||||
+ va_start (ap, y);
|
||||
+ if (x < 0 || x >= 20 || seen[x])
|
||||
+ abort ();
|
||||
+ seen[x] = ++cnt;
|
||||
+ if (y != 6)
|
||||
+ abort ();
|
||||
+ i = va_arg (ap, int);
|
||||
+ if (i != 5)
|
||||
+ abort ();
|
||||
+ switch (x)
|
||||
+ {
|
||||
+ case 0:
|
||||
+ i = va_arg (ap, int);
|
||||
+ if (i != 9 || v1 != 9)
|
||||
+ abort ();
|
||||
+ a = va_arg (ap, struct A);
|
||||
+ if (__builtin_memcmp (a.c, v4.c, sizeof (a.c)) != 0)
|
||||
+ abort ();
|
||||
+ v = (void *) va_arg (ap, struct A *);
|
||||
+ if (v != (void *) &v4)
|
||||
+ abort ();
|
||||
+ l = va_arg (ap, long int);
|
||||
+ if (l != 3 || v2 != 4)
|
||||
+ abort ();
|
||||
+ break;
|
||||
+ case 1:
|
||||
+ ld = va_arg (ap, long double);
|
||||
+ if (ld != 41 || v5 != ld)
|
||||
+ abort ();
|
||||
+ i = va_arg (ap, int);
|
||||
+ if (i != 8)
|
||||
+ abort ();
|
||||
+ v = va_arg (ap, void *);
|
||||
+ if (v != &v2)
|
||||
+ abort ();
|
||||
+ break;
|
||||
+ case 2:
|
||||
+ break;
|
||||
+ default:
|
||||
+ abort ();
|
||||
+ }
|
||||
+ va_end (ap);
|
||||
+ return x;
|
||||
+}
|
||||
+
|
||||
+__attribute__ ((noinline)) int
|
||||
+foo2 (int x, int y, ...)
|
||||
+{
|
||||
+ long long int ll;
|
||||
+ void *v;
|
||||
+ struct A a, b;
|
||||
+ long double ld;
|
||||
+ va_list ap;
|
||||
+
|
||||
+ va_start (ap, y);
|
||||
+ if (x < 0 || x >= 20 || seen[x])
|
||||
+ abort ();
|
||||
+ seen[x] = ++cnt | 64;
|
||||
+ if (y != 10)
|
||||
+ abort ();
|
||||
+ switch (x)
|
||||
+ {
|
||||
+ case 11:
|
||||
+ break;
|
||||
+ case 12:
|
||||
+ ld = va_arg (ap, long double);
|
||||
+ if (ld != 41 || v5 != 40)
|
||||
+ abort ();
|
||||
+ a = va_arg (ap, struct A);
|
||||
+ if (__builtin_memcmp (a.c, v4.c, sizeof (a.c)) != 0)
|
||||
+ abort ();
|
||||
+ b = va_arg (ap, struct A);
|
||||
+ if (__builtin_memcmp (b.c, v4.c, sizeof (b.c)) != 0)
|
||||
+ abort ();
|
||||
+ v = va_arg (ap, void *);
|
||||
+ if (v != &v2)
|
||||
+ abort ();
|
||||
+ ll = va_arg (ap, long long int);
|
||||
+ if (ll != 16LL)
|
||||
+ abort ();
|
||||
+ break;
|
||||
+ case 2:
|
||||
+ break;
|
||||
+ default:
|
||||
+ abort ();
|
||||
+ }
|
||||
+ va_end (ap);
|
||||
+ return x + 8;
|
||||
+}
|
||||
+
|
||||
+__attribute__ ((noinline)) int
|
||||
+foo3 (void)
|
||||
+{
|
||||
+ return 6;
|
||||
+}
|
||||
+
|
||||
+extern inline __attribute__ ((always_inline, gnu_inline)) int
|
||||
+bar (int x, ...)
|
||||
+{
|
||||
+ if (x < 10)
|
||||
+ return foo1 (x, foo3 (), 5, __builtin_va_arg_pack ());
|
||||
+ return foo2 (x, foo3 () + 4, __builtin_va_arg_pack ());
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+main (void)
|
||||
+{
|
||||
+ if (bar (0, ++v1, v4, &v4, v2++) != 0)
|
||||
+ abort ();
|
||||
+ if (bar (1, ++v5, 8, v3) != 1)
|
||||
+ abort ();
|
||||
+ if (bar (2) != 2)
|
||||
+ abort ();
|
||||
+ if (bar (v1 + 2) != 19)
|
||||
+ abort ();
|
||||
+ if (bar (v1 + 3, v5--, v4, v4, v3, 16LL) != 20)
|
||||
+ abort ();
|
||||
+ return 0;
|
||||
+}
|
||||
--- gcc/testsuite/gcc.dg/va-arg-pack-1.c.jj 2007-09-06 10:19:25.000000000 +0200
|
||||
+++ gcc/testsuite/gcc.dg/va-arg-pack-1.c 2007-09-06 12:52:00.000000000 +0200
|
||||
@@ -0,0 +1,46 @@
|
||||
+/* { dg-do compile } */
|
||||
+/* { dg-options "-O2" } */
|
||||
+
|
||||
+int bar (int, const char *, int, ...);
|
||||
+int baz (int, const char *, long int);
|
||||
+
|
||||
+extern inline __attribute__((always_inline)) int
|
||||
+f2 (int y, ...)
|
||||
+{
|
||||
+ return bar (y, "", __builtin_va_arg_pack ()); /* { dg-error "invalid use of" } */
|
||||
+}
|
||||
+
|
||||
+extern inline __attribute__((always_inline)) int
|
||||
+f3 (int y, ...)
|
||||
+{
|
||||
+ return bar (y, "", 5, __builtin_va_arg_pack ());
|
||||
+}
|
||||
+
|
||||
+extern inline __attribute__((always_inline)) int
|
||||
+f4 (int y, ...)
|
||||
+{
|
||||
+ return bar (y, "", 4, __builtin_va_arg_pack (), 6); /* { dg-error "invalid use of" } */
|
||||
+}
|
||||
+
|
||||
+extern inline __attribute__((always_inline)) int
|
||||
+f5 (int y, ...)
|
||||
+{
|
||||
+ return baz (y, "", __builtin_va_arg_pack ()); /* { dg-error "invalid use of" } */
|
||||
+}
|
||||
+
|
||||
+extern inline __attribute__((always_inline)) int
|
||||
+f6 (int y, ...)
|
||||
+{
|
||||
+ return __builtin_va_arg_pack (); /* { dg-error "invalid use of" } */
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+test (void)
|
||||
+{
|
||||
+ int a = f2 (5, "a", 6);
|
||||
+ a += f3 (6, "ab", 17LL);
|
||||
+ a += f4 (7, 1, 2, 3);
|
||||
+ a += f5 (8, 7L);
|
||||
+ a += f6 (9);
|
||||
+ return a;
|
||||
+}
|
||||
--- gcc/testsuite/gcc.dg/va-arg-pack-1a.c.jj 2007-09-06 12:51:51.000000000 +0200
|
||||
+++ gcc/testsuite/gcc.dg/va-arg-pack-1a.c 2007-09-06 12:52:09.000000000 +0200
|
||||
@@ -0,0 +1,11 @@
|
||||
+/* { dg-do compile } */
|
||||
+/* { dg-options "-O2" } */
|
||||
+
|
||||
+int bar (int, const char *, int, ...);
|
||||
+int baz (int, const char *, long int);
|
||||
+
|
||||
+int
|
||||
+f1 (int x, ...)
|
||||
+{
|
||||
+ return bar (5, "", 6, __builtin_va_arg_pack ()); /* { dg-error "invalid use of" } */
|
||||
+}
|
||||
--- gcc/testsuite/g++.dg/ext/va-arg-pack-1.C.jj 2007-09-07 08:52:55.000000000 +0200
|
||||
+++ gcc/testsuite/g++.dg/ext/va-arg-pack-1.C 2007-09-07 08:53:45.000000000 +0200
|
||||
@@ -0,0 +1,145 @@
|
||||
+// __builtin_va_arg_pack () builtin tests.
|
||||
+// { dg-do run }
|
||||
+// { dg-options "-O2" }
|
||||
+
|
||||
+#include <stdarg.h>
|
||||
+
|
||||
+extern "C" void abort (void);
|
||||
+
|
||||
+int v1 = 8;
|
||||
+long int v2 = 3;
|
||||
+void *v3 = (void *) &v2;
|
||||
+struct A { char c[16]; } v4 = { "foo" };
|
||||
+long double v5 = 40;
|
||||
+char seen[20];
|
||||
+int cnt;
|
||||
+
|
||||
+__attribute__ ((noinline)) int
|
||||
+foo1 (int x, int y, ...)
|
||||
+{
|
||||
+ int i;
|
||||
+ long int l;
|
||||
+ void *v;
|
||||
+ struct A a;
|
||||
+ long double ld;
|
||||
+ va_list ap;
|
||||
+
|
||||
+ va_start (ap, y);
|
||||
+ if (x < 0 || x >= 20 || seen[x])
|
||||
+ abort ();
|
||||
+ seen[x] = ++cnt;
|
||||
+ if (y != 6)
|
||||
+ abort ();
|
||||
+ i = va_arg (ap, int);
|
||||
+ if (i != 5)
|
||||
+ abort ();
|
||||
+ switch (x)
|
||||
+ {
|
||||
+ case 0:
|
||||
+ i = va_arg (ap, int);
|
||||
+ if (i != 9 || v1 != 9)
|
||||
+ abort ();
|
||||
+ a = va_arg (ap, struct A);
|
||||
+ if (__builtin_memcmp (a.c, v4.c, sizeof (a.c)) != 0)
|
||||
+ abort ();
|
||||
+ v = (void *) va_arg (ap, struct A *);
|
||||
+ if (v != (void *) &v4)
|
||||
+ abort ();
|
||||
+ l = va_arg (ap, long int);
|
||||
+ if (l != 3 || v2 != 4)
|
||||
+ abort ();
|
||||
+ break;
|
||||
+ case 1:
|
||||
+ ld = va_arg (ap, long double);
|
||||
+ if (ld != 41 || v5 != ld)
|
||||
+ abort ();
|
||||
+ i = va_arg (ap, int);
|
||||
+ if (i != 8)
|
||||
+ abort ();
|
||||
+ v = va_arg (ap, void *);
|
||||
+ if (v != &v2)
|
||||
+ abort ();
|
||||
+ break;
|
||||
+ case 2:
|
||||
+ break;
|
||||
+ default:
|
||||
+ abort ();
|
||||
+ }
|
||||
+ va_end (ap);
|
||||
+ return x;
|
||||
+}
|
||||
+
|
||||
+__attribute__ ((noinline)) int
|
||||
+foo2 (int x, int y, ...)
|
||||
+{
|
||||
+ long long int ll;
|
||||
+ void *v;
|
||||
+ struct A a, b;
|
||||
+ long double ld;
|
||||
+ va_list ap;
|
||||
+
|
||||
+ va_start (ap, y);
|
||||
+ if (x < 0 || x >= 20 || seen[x])
|
||||
+ abort ();
|
||||
+ seen[x] = ++cnt | 64;
|
||||
+ if (y != 10)
|
||||
+ abort ();
|
||||
+ switch (x)
|
||||
+ {
|
||||
+ case 11:
|
||||
+ break;
|
||||
+ case 12:
|
||||
+ ld = va_arg (ap, long double);
|
||||
+ if (ld != 41 || v5 != 40)
|
||||
+ abort ();
|
||||
+ a = va_arg (ap, struct A);
|
||||
+ if (__builtin_memcmp (a.c, v4.c, sizeof (a.c)) != 0)
|
||||
+ abort ();
|
||||
+ b = va_arg (ap, struct A);
|
||||
+ if (__builtin_memcmp (b.c, v4.c, sizeof (b.c)) != 0)
|
||||
+ abort ();
|
||||
+ v = va_arg (ap, void *);
|
||||
+ if (v != &v2)
|
||||
+ abort ();
|
||||
+ ll = va_arg (ap, long long int);
|
||||
+ if (ll != 16LL)
|
||||
+ abort ();
|
||||
+ break;
|
||||
+ case 2:
|
||||
+ break;
|
||||
+ default:
|
||||
+ abort ();
|
||||
+ }
|
||||
+ va_end (ap);
|
||||
+ return x + 8;
|
||||
+}
|
||||
+
|
||||
+__attribute__ ((noinline)) int
|
||||
+foo3 (void)
|
||||
+{
|
||||
+ return 6;
|
||||
+}
|
||||
+
|
||||
+extern inline __attribute__ ((always_inline, gnu_inline)) int
|
||||
+bar (int x, ...)
|
||||
+{
|
||||
+ if (x < 10)
|
||||
+ return foo1 (x, foo3 (), 5, __builtin_va_arg_pack ());
|
||||
+ return foo2 (x, foo3 () + 4, __builtin_va_arg_pack ());
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+main (void)
|
||||
+{
|
||||
+ if (bar (0, ++v1, v4, &v4, v2++) != 0)
|
||||
+ abort ();
|
||||
+ if (bar (1, ++v5, 8, v3) != 1)
|
||||
+ abort ();
|
||||
+ if (bar (2) != 2)
|
||||
+ abort ();
|
||||
+ if (bar (v1 + 2) != 19)
|
||||
+ abort ();
|
||||
+ if (bar (v1 + 3, v5--, v4, v4, v3, 16LL) != 20)
|
||||
+ abort ();
|
||||
+ return 0;
|
||||
+}
|
||||
--- gcc/testsuite/g++.dg/ext/va-arg-pack-2.C.jj 2007-09-07 08:53:23.000000000 +0200
|
||||
+++ gcc/testsuite/g++.dg/ext/va-arg-pack-2.C 2007-09-07 08:54:25.000000000 +0200
|
||||
@@ -0,0 +1,46 @@
|
||||
+// { dg-do compile }
|
||||
+// { dg-options "-O2" }
|
||||
+
|
||||
+int bar (int, const char *, int, ...);
|
||||
+int baz (int, const char *, long int);
|
||||
+
|
||||
+extern inline __attribute__((always_inline)) int
|
||||
+f2 (int y, ...)
|
||||
+{
|
||||
+ return bar (y, "", __builtin_va_arg_pack ()); /* { dg-error "invalid use of" } */
|
||||
+}
|
||||
+
|
||||
+extern inline __attribute__((always_inline)) int
|
||||
+f3 (int y, ...)
|
||||
+{
|
||||
+ return bar (y, "", 5, __builtin_va_arg_pack ());
|
||||
+}
|
||||
+
|
||||
+extern inline __attribute__((always_inline)) int
|
||||
+f4 (int y, ...)
|
||||
+{
|
||||
+ return bar (y, "", 4, __builtin_va_arg_pack (), 6); /* { dg-error "invalid use of" } */
|
||||
+}
|
||||
+
|
||||
+extern inline __attribute__((always_inline)) int
|
||||
+f5 (int y, ...)
|
||||
+{
|
||||
+ return baz (y, "", __builtin_va_arg_pack ()); /* { dg-error "invalid use of" } */
|
||||
+}
|
||||
+
|
||||
+extern inline __attribute__((always_inline)) int
|
||||
+f6 (int y, ...)
|
||||
+{
|
||||
+ return __builtin_va_arg_pack (); /* { dg-error "invalid use of" } */
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+test (void)
|
||||
+{
|
||||
+ int a = f2 (5, "a", 6);
|
||||
+ a += f3 (6, "ab", 17LL);
|
||||
+ a += f4 (7, 1, 2, 3);
|
||||
+ a += f5 (8, 7L);
|
||||
+ a += f6 (9);
|
||||
+ return a;
|
||||
+}
|
@ -1,608 +0,0 @@
|
||||
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"
|
295
gcc41-error-attrib.patch
Normal file
295
gcc41-error-attrib.patch
Normal file
@ -0,0 +1,295 @@
|
||||
2007-09-23 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* expr.c (expand_expr_real_1) <case CALL_EXPR>: Use get_callee_fndecl
|
||||
instead of checking CALL_EXPR_FN directly to test for builtins.
|
||||
If error or warning attributes are present, print
|
||||
error resp. warning.
|
||||
* c-common.c (handle_error_attribute): New function.
|
||||
(c_common_attribute_table): Add error and warning
|
||||
attributes.
|
||||
* doc/extend.texi: Document error and warning attributes.
|
||||
|
||||
* gcc.dg/va-arg-pack-len-1.c: Use error and warning
|
||||
attributes.
|
||||
* gcc.dg/va-arg-pack-len-2.c: New test.
|
||||
* g++.dg/ext/va-arg-pack-len-1.C: Use error and warning
|
||||
attributes.
|
||||
* g++.dg/ext/va-arg-pack-len-2.C: New test.
|
||||
|
||||
--- gcc/doc/extend.texi.jj 2007-09-25 15:04:15.000000000 +0200
|
||||
+++ gcc/doc/extend.texi 2007-09-25 15:32:22.000000000 +0200
|
||||
@@ -1589,8 +1589,8 @@ attributes are currently defined for fun
|
||||
@code{section}, @code{constructor}, @code{destructor}, @code{used},
|
||||
@code{unused}, @code{deprecated}, @code{weak}, @code{malloc},
|
||||
@code{alias}, @code{warn_unused_result}, @code{nonnull},
|
||||
-@code{gnu_inline}, @code{externally_visible} and @code{artificial}.
|
||||
-Several other
|
||||
+@code{gnu_inline}, @code{externally_visible}, @code{artificial},
|
||||
+@code{error} and @code{warning}. Several other
|
||||
attributes are defined for functions on particular target systems. Other
|
||||
attributes, including @code{section} are supported for variables declarations
|
||||
(@pxref{Variable Attributes}) and for types (@pxref{Type Attributes}).
|
||||
@@ -1688,6 +1688,30 @@ Whether the function itself is considere
|
||||
the current inlining parameters. The @code{flatten} attribute only works
|
||||
reliably in unit-at-a-time mode.
|
||||
|
||||
+@item error ("@var{message}")
|
||||
+@cindex @code{error} function attribute
|
||||
+If this attribute is used on a function declaration and a call to such a function
|
||||
+is not eliminated through dead code elimination or other optimizations, an error
|
||||
+which will include @var{message} will be diagnosed. This is useful
|
||||
+for compile time checking, especially together with @code{__builtin_constant_p}
|
||||
+and inline functions where checking the inline function arguments is not
|
||||
+possible through @code{extern char [(condition) ? 1 : -1];} tricks.
|
||||
+While it is possible to leave the function undefined and thus invoke
|
||||
+a link failure, when using this attribute the problem will be diagnosed
|
||||
+earlier and with exact location of the call even in presence of inline
|
||||
+functions or when not emitting debugging information.
|
||||
+
|
||||
+@item warning ("@var{message}")
|
||||
+@cindex @code{warning} function attribute
|
||||
+If this attribute is used on a function declaration and a call to such a function
|
||||
+is not eliminated through dead code elimination or other optimizations, a warning
|
||||
+which will include @var{message} will be diagnosed. This is useful
|
||||
+for compile time checking, especially together with @code{__builtin_constant_p}
|
||||
+and inline functions. While it is possible to define the function with
|
||||
+a message in @code{.gnu.warning*} section, when using this attribute the problem
|
||||
+will be diagnosed earlier and with exact location of the call even in presence
|
||||
+of inline functions or when not emitting debugging information.
|
||||
+
|
||||
@item cdecl
|
||||
@cindex functions that do pop the argument stack on the 386
|
||||
@opindex mrtd
|
||||
--- gcc/expr.c.jj 2007-09-25 14:58:40.000000000 +0200
|
||||
+++ gcc/expr.c 2007-09-25 15:19:15.000000000 +0200
|
||||
@@ -7513,19 +7513,31 @@ expand_expr_real_1 (tree exp, rtx target
|
||||
inlining. */
|
||||
if (CALL_EXPR_VA_ARG_PACK (exp))
|
||||
error ("invalid use of %<__builtin_va_arg_pack ()%>");
|
||||
- /* Check for a built-in function. */
|
||||
- if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
|
||||
- && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
|
||||
- == FUNCTION_DECL)
|
||||
- && DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
|
||||
- {
|
||||
- if (DECL_BUILT_IN_CLASS (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
|
||||
- == BUILT_IN_FRONTEND)
|
||||
- return lang_hooks.expand_expr (exp, original_target,
|
||||
- tmode, modifier,
|
||||
- alt_rtl);
|
||||
- else
|
||||
- return expand_builtin (exp, target, subtarget, tmode, ignore);
|
||||
+ {
|
||||
+ tree fndecl = get_callee_fndecl (exp), attr;
|
||||
+
|
||||
+ if (fndecl
|
||||
+ && (attr = lookup_attribute ("error",
|
||||
+ DECL_ATTRIBUTES (fndecl))) != NULL)
|
||||
+ error ("call to %qs declared with attribute error: %s",
|
||||
+ lang_hooks.decl_printable_name (fndecl, 1),
|
||||
+ TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr))));
|
||||
+ if (fndecl
|
||||
+ && (attr = lookup_attribute ("warning",
|
||||
+ DECL_ATTRIBUTES (fndecl))) != NULL)
|
||||
+ warning (0, "call to %qs declared with attribute warning: %s",
|
||||
+ lang_hooks.decl_printable_name (fndecl, 1),
|
||||
+ TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr))));
|
||||
+
|
||||
+ /* Check for a built-in function. */
|
||||
+ if (fndecl && DECL_BUILT_IN (fndecl))
|
||||
+ {
|
||||
+ if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_FRONTEND)
|
||||
+ return lang_hooks.expand_expr (exp, original_target,
|
||||
+ tmode, modifier, alt_rtl);
|
||||
+ else
|
||||
+ return expand_builtin (exp, target, subtarget, tmode, ignore);
|
||||
+ }
|
||||
}
|
||||
|
||||
return expand_call (exp, target, ignore);
|
||||
--- gcc/c-common.c.jj 2007-09-25 15:01:49.000000000 +0200
|
||||
+++ gcc/c-common.c 2007-09-25 15:24:34.000000000 +0200
|
||||
@@ -508,6 +508,7 @@ static tree handle_always_inline_attribu
|
||||
static tree handle_gnu_inline_attribute (tree *, tree, tree, int, bool *);
|
||||
static tree handle_artificial_attribute (tree *, tree, tree, int, bool *);
|
||||
static tree handle_flatten_attribute (tree *, tree, tree, int, bool *);
|
||||
+static tree handle_error_attribute (tree *, tree, tree, int, bool *);
|
||||
static tree handle_used_attribute (tree *, tree, tree, int, bool *);
|
||||
static tree handle_unused_attribute (tree *, tree, tree, int, bool *);
|
||||
static tree handle_externally_visible_attribute (tree *, tree, tree, int,
|
||||
@@ -641,6 +642,10 @@ const struct attribute_spec c_common_att
|
||||
handle_warn_unused_result_attribute },
|
||||
{ "sentinel", 0, 1, false, true, true,
|
||||
handle_sentinel_attribute },
|
||||
+ { "warning", 1, 1, true, false, false,
|
||||
+ handle_error_attribute },
|
||||
+ { "error", 1, 1, true, false, false,
|
||||
+ handle_error_attribute },
|
||||
{ NULL, 0, 0, false, false, false, NULL }
|
||||
};
|
||||
|
||||
@@ -4226,6 +4231,26 @@ handle_flatten_attribute (tree *node, tr
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
+/* Handle a "warning" or "error" attribute; arguments as in
|
||||
+ struct attribute_spec.handler. */
|
||||
+
|
||||
+static tree
|
||||
+handle_error_attribute (tree *node, tree name, tree args,
|
||||
+ int ARG_UNUSED (flags), bool *no_add_attrs)
|
||||
+{
|
||||
+ if (TREE_CODE (*node) == FUNCTION_DECL
|
||||
+ || TREE_CODE (TREE_VALUE (args)) == STRING_CST)
|
||||
+ /* Do nothing else, just set the attribute. We'll get at
|
||||
+ it later with lookup_attribute. */
|
||||
+ ;
|
||||
+ else
|
||||
+ {
|
||||
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
|
||||
+ *no_add_attrs = true;
|
||||
+ }
|
||||
+
|
||||
+ return NULL_TREE;
|
||||
+}
|
||||
|
||||
/* Handle a "used" attribute; arguments as in
|
||||
struct attribute_spec.handler. */
|
||||
--- gcc/testsuite/gcc.dg/va-arg-pack-len-1.c.jj 2007-09-25 12:23:05.000000000 +0200
|
||||
+++ gcc/testsuite/gcc.dg/va-arg-pack-len-1.c 2007-09-25 15:16:03.000000000 +0200
|
||||
@@ -3,8 +3,10 @@
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
-extern int warn_open_missing_mode (void);
|
||||
-extern int warn_open_too_many_arguments (void);
|
||||
+extern int error_open_missing_mode (void)
|
||||
+ __attribute__((__error__ ("open with O_CREAT needs 3 arguments, only 2 were given")));
|
||||
+extern int warn_open_too_many_arguments (void)
|
||||
+ __attribute__((__warning__ ("open called with more than 3 arguments")));
|
||||
extern void abort (void);
|
||||
|
||||
char expected_char;
|
||||
@@ -83,7 +85,7 @@ myopen (const char *path, int oflag, ...
|
||||
{
|
||||
if ((oflag & 0x40) != 0 && __builtin_va_arg_pack_len () < 1)
|
||||
{
|
||||
- warn_open_missing_mode ();
|
||||
+ error_open_missing_mode ();
|
||||
return myopen2 (path, oflag);
|
||||
}
|
||||
return myopenva (path, oflag, __builtin_va_arg_pack ());
|
||||
--- gcc/testsuite/gcc.dg/va-arg-pack-len-2.c.jj 2007-09-25 15:16:03.000000000 +0200
|
||||
+++ gcc/testsuite/gcc.dg/va-arg-pack-len-2.c 2007-09-25 15:16:03.000000000 +0200
|
||||
@@ -0,0 +1,42 @@
|
||||
+/* { dg-do compile } */
|
||||
+/* { dg-options "-O2" } */
|
||||
+
|
||||
+#include <stdarg.h>
|
||||
+
|
||||
+extern int error_open_missing_mode (void)
|
||||
+ __attribute__((__error__ ("open with O_CREAT needs 3 arguments, only 2 were given")));
|
||||
+extern int warn_open_too_many_arguments (void)
|
||||
+ __attribute__((__warning__ ("open called with more than 3 arguments")));
|
||||
+
|
||||
+extern int myopen2 (const char *path, int oflag);
|
||||
+extern int myopenva (const char *path, int oflag, ...);
|
||||
+
|
||||
+extern inline __attribute__((always_inline, gnu_inline)) int
|
||||
+myopen (const char *path, int oflag, ...)
|
||||
+{
|
||||
+ if (__builtin_va_arg_pack_len () > 1)
|
||||
+ warn_open_too_many_arguments (); /* { dg-warning "called with more than 3" } */
|
||||
+
|
||||
+ if (__builtin_constant_p (oflag))
|
||||
+ {
|
||||
+ if ((oflag & 0x40) != 0 && __builtin_va_arg_pack_len () < 1)
|
||||
+ {
|
||||
+ error_open_missing_mode (); /* { dg-error "needs 3 arguments, only 2 were given" } */
|
||||
+ return myopen2 (path, oflag);
|
||||
+ }
|
||||
+ return myopenva (path, oflag, __builtin_va_arg_pack ());
|
||||
+ }
|
||||
+
|
||||
+ if (__builtin_va_arg_pack_len () < 1)
|
||||
+ return myopen2 (path, oflag);
|
||||
+
|
||||
+ return myopenva (path, oflag, __builtin_va_arg_pack ());
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+main (void)
|
||||
+{
|
||||
+ myopen ("h", 0x43);
|
||||
+ myopen ("i", 0x43, 0644, 0655);
|
||||
+ return 0;
|
||||
+}
|
||||
--- gcc/testsuite/g++.dg/ext/va-arg-pack-len-1.C.jj 2007-09-25 12:23:05.000000000 +0200
|
||||
+++ gcc/testsuite/g++.dg/ext/va-arg-pack-len-1.C 2007-09-25 15:16:03.000000000 +0200
|
||||
@@ -3,8 +3,10 @@
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
-extern "C" int warn_open_missing_mode (void);
|
||||
-extern "C" int warn_open_too_many_arguments (void);
|
||||
+extern "C" int error_open_missing_mode (void)
|
||||
+ __attribute__((__error__ ("open with O_CREAT needs 3 arguments, only 2 were given")));
|
||||
+extern "C" int warn_open_too_many_arguments (void)
|
||||
+ __attribute__((__warning__ ("open called with more than 3 arguments")));
|
||||
extern "C" void abort (void);
|
||||
|
||||
char expected_char;
|
||||
@@ -83,7 +85,7 @@ myopen (const char *path, int oflag, ...
|
||||
{
|
||||
if ((oflag & 0x40) != 0 && __builtin_va_arg_pack_len () < 1)
|
||||
{
|
||||
- warn_open_missing_mode ();
|
||||
+ error_open_missing_mode ();
|
||||
return myopen2 (path, oflag);
|
||||
}
|
||||
return myopenva (path, oflag, __builtin_va_arg_pack ());
|
||||
--- gcc/testsuite/g++.dg/ext/va-arg-pack-len-2.C.jj 2007-09-25 15:16:03.000000000 +0200
|
||||
+++ gcc/testsuite/g++.dg/ext/va-arg-pack-len-2.C 2007-09-25 15:16:03.000000000 +0200
|
||||
@@ -0,0 +1,42 @@
|
||||
+// { dg-do compile }
|
||||
+// { dg-options "-O2" }
|
||||
+
|
||||
+#include <stdarg.h>
|
||||
+
|
||||
+extern int error_open_missing_mode (void)
|
||||
+ __attribute__((__error__ ("open with O_CREAT needs 3 arguments, only 2 were given")));
|
||||
+extern int warn_open_too_many_arguments (void)
|
||||
+ __attribute__((__warning__ ("open called with more than 3 arguments")));
|
||||
+
|
||||
+extern int myopen2 (const char *path, int oflag);
|
||||
+extern int myopenva (const char *path, int oflag, ...);
|
||||
+
|
||||
+extern inline __attribute__((always_inline, gnu_inline)) int
|
||||
+myopen (const char *path, int oflag, ...)
|
||||
+{
|
||||
+ if (__builtin_va_arg_pack_len () > 1)
|
||||
+ warn_open_too_many_arguments (); // { dg-warning "called with more than 3" }
|
||||
+
|
||||
+ if (__builtin_constant_p (oflag))
|
||||
+ {
|
||||
+ if ((oflag & 0x40) != 0 && __builtin_va_arg_pack_len () < 1)
|
||||
+ {
|
||||
+ error_open_missing_mode (); // { dg-error "needs 3 arguments, only 2 were given" }
|
||||
+ return myopen2 (path, oflag);
|
||||
+ }
|
||||
+ return myopenva (path, oflag, __builtin_va_arg_pack ());
|
||||
+ }
|
||||
+
|
||||
+ if (__builtin_va_arg_pack_len () < 1)
|
||||
+ return myopen2 (path, oflag);
|
||||
+
|
||||
+ return myopenva (path, oflag, __builtin_va_arg_pack ());
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+main (void)
|
||||
+{
|
||||
+ myopen ("h", 0x43);
|
||||
+ myopen ("i", 0x43, 0644, 0655);
|
||||
+ return 0;
|
||||
+}
|
242
gcc41-jdwp.patch
Normal file
242
gcc41-jdwp.patch
Normal file
@ -0,0 +1,242 @@
|
||||
2007-09-24 Keith Seitz <keiths@redhat.com>
|
||||
|
||||
* include/jvm.h (struct natThread): Add new field 'frame'.
|
||||
* include/java-interp.h (_Jv_Frame): Use _Jv_ThreadStackPeek,
|
||||
_Jv_ThreadStackPop, and _Jv_ThreadStackPush instead of
|
||||
java.lang.Thread.frame.
|
||||
(~_Jv_Frame): Use _Jv_ThreadStackPop.
|
||||
* java/lang/natThread.cc (_Jv_ThreadStackPeek): New function.
|
||||
(_Jv_ThreadStackPush): New function.
|
||||
(_Jv_ThreadStackPop): New function.
|
||||
* java/lang/Thread.java (frame): Remove field to restore
|
||||
C++ ABI compatibility.
|
||||
* gnu/classpath/jdwp/natVMVirtualMachine.cc (getFrames): Use
|
||||
_Jv_ThreadStackPeek.
|
||||
(getFrame): Likewise.
|
||||
* gnu/classpath/jdwp/natVMFrame.cc (getFrameDepth): Likewise.
|
||||
* jvmti.cc (getLocalFrame): Likewise.
|
||||
(_Jv_JVMTI_GetFrameCount): Likewise.
|
||||
(_Jv_JVMTI_GetThreadState): Likewise.
|
||||
(_Jv_JVMTI_GetStackTrace): Likewise.
|
||||
* interpret.cc (_Jv_ReportJVMTIExceptionThrow): Likewise.
|
||||
* headers.txt (java/lang/Thread.h): Prepend declarations
|
||||
for _Jv_ThreadStackPeek, _Jv_ThreadStackPush, and _Jv_ThreadStackPop.
|
||||
Add as friend functions.
|
||||
* jni.cc (_Jv_JNIMethod::call): Push a frame onto the stack when
|
||||
calling a JNI method.
|
||||
|
||||
--- libjava/interpret.cc (revision 128603)
|
||||
+++ libjava/interpret.cc (working copy)
|
||||
@@ -1709,7 +1709,7 @@
|
||||
_Jv_ReportJVMTIExceptionThrow (jthrowable ex)
|
||||
{
|
||||
jthread thread = ::java::lang::Thread::currentThread ();
|
||||
- _Jv_Frame *frame = reinterpret_cast<_Jv_Frame *> (thread->frame);
|
||||
+ _Jv_Frame *frame = _Jv_ThreadStackPeek (thread);
|
||||
jmethodID throw_meth = frame->self->get_method ();
|
||||
jlocation throw_loc = -1;
|
||||
if (frame->frame_type == frame_interpreter)
|
||||
--- libjava/include/java-interp.h (revision 128603)
|
||||
+++ libjava/include/java-interp.h (working copy)
|
||||
@@ -391,14 +391,14 @@
|
||||
{
|
||||
self = s;
|
||||
frame_type = type;
|
||||
- next = (_Jv_Frame *) thr->frame;
|
||||
- thr->frame = (gnu::gcj::RawData *) this;
|
||||
+ next = _Jv_ThreadStackPeek (thr);
|
||||
+ _Jv_ThreadStackPush (thr, this);
|
||||
thread = thr;
|
||||
}
|
||||
|
||||
~_Jv_Frame ()
|
||||
{
|
||||
- thread->frame = (gnu::gcj::RawData *) next;
|
||||
+ _Jv_ThreadStackPop (thread);
|
||||
}
|
||||
|
||||
int depth ()
|
||||
--- libjava/include/jvm.h (revision 128603)
|
||||
+++ libjava/include/jvm.h (working copy)
|
||||
@@ -34,6 +34,8 @@
|
||||
|
||||
#include <sysdep/locks.h>
|
||||
|
||||
+class _Jv_Frame;
|
||||
+
|
||||
/* Macro for possible unused arguments. */
|
||||
#define MAYBE_UNUSED __attribute__((__unused__))
|
||||
|
||||
@@ -767,6 +769,12 @@
|
||||
|
||||
// Each thread has its own JNI object.
|
||||
_Jv_JNIEnv *jni_env;
|
||||
+
|
||||
+ // Describes the topmost frame in the thread's composite
|
||||
+ // (interp + JNI) stack. Added here to maintain C++ ABI
|
||||
+ // compatibility with previous versions. Newer versions
|
||||
+ // of gcj put this in java/lang/Thread.java.
|
||||
+ _Jv_Frame *frame;
|
||||
};
|
||||
|
||||
#endif /* __JAVA_JVM_H__ */
|
||||
--- libjava/jni.cc (revision 128603)
|
||||
+++ libjava/jni.cc (working copy)
|
||||
@@ -2343,6 +2343,10 @@
|
||||
// Copy over passed-in arguments.
|
||||
memcpy (&real_args[offset], args, _this->args_raw_size);
|
||||
|
||||
+ // Add a frame to the composite (interpreted + JNI) call stack
|
||||
+ java::lang::Thread *thread = java::lang::Thread::currentThread ();
|
||||
+ _Jv_NativeFrame nat_frame (_this, thread);
|
||||
+
|
||||
// The actual call to the JNI function.
|
||||
#if FFI_NATIVE_RAW_API
|
||||
ffi_raw_call (&_this->jni_cif, (void (*)()) _this->function,
|
||||
--- libjava/jvmti.cc (revision 128603)
|
||||
+++ libjava/jvmti.cc (working copy)
|
||||
@@ -228,7 +228,7 @@
|
||||
THREAD_CHECK_VALID (thread);
|
||||
THREAD_CHECK_IS_ALIVE (thread);
|
||||
|
||||
- _Jv_Frame *frame = reinterpret_cast<_Jv_Frame *> (thread->frame);
|
||||
+ _Jv_Frame *frame = _Jv_ThreadStackPeek (thread);
|
||||
|
||||
for (int i = 0; i < depth; i++)
|
||||
{
|
||||
@@ -516,7 +516,7 @@
|
||||
THREAD_CHECK_VALID (thread);
|
||||
THREAD_CHECK_IS_ALIVE (thread);
|
||||
|
||||
- _Jv_Frame *frame = reinterpret_cast<_Jv_Frame *> (thread->frame);
|
||||
+ _Jv_Frame *frame = _Jv_ThreadStackPeek (thread);
|
||||
(*frame_count) = frame->depth ();
|
||||
return JVMTI_ERROR_NONE;
|
||||
}
|
||||
@@ -543,7 +543,7 @@
|
||||
if (thread->isInterrupted ())
|
||||
state |= JVMTI_THREAD_STATE_INTERRUPTED;
|
||||
|
||||
- _Jv_Frame *frame = reinterpret_cast<_Jv_Frame *> (thread->frame);
|
||||
+ _Jv_Frame *frame = _Jv_ThreadStackPeek (thread);
|
||||
if (frame != NULL && frame->frame_type == frame_native)
|
||||
state |= JVMTI_THREAD_STATE_IN_NATIVE;
|
||||
|
||||
@@ -1273,7 +1273,7 @@
|
||||
ILLEGAL_ARGUMENT (start_depth >= (*frame_count));
|
||||
ILLEGAL_ARGUMENT (start_depth < (-(*frame_count)));
|
||||
|
||||
- _Jv_Frame *frame = reinterpret_cast<_Jv_Frame *> (thread->frame);
|
||||
+ _Jv_Frame *frame = _Jv_ThreadStackPeek (thread);
|
||||
|
||||
// If start_depth is negative use this to determine at what depth to start
|
||||
// the trace by adding it to the length of the call stack. This allows the
|
||||
--- libjava/headers.txt (revision 128603)
|
||||
+++ libjava/headers.txt (working copy)
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
class java/lang/Thread
|
||||
prepend class _Jv_JNIEnv;
|
||||
+prepend class _Jv_Frame;
|
||||
prepend #define _JV_NOT_OWNER 1
|
||||
prepend #define _JV_INTERRUPTED 2
|
||||
prepend _Jv_JNIEnv * _Jv_GetCurrentJNIEnv ();
|
||||
@@ -17,6 +18,9 @@
|
||||
prepend jint _Jv_DetachCurrentThread ();
|
||||
prepend struct _Jv_Thread_t;
|
||||
prepend _Jv_Thread_t* _Jv_ThreadGetData (java::lang::Thread* thread);
|
||||
+prepend _Jv_Frame *_Jv_ThreadStackPeek (java::lang::Thread *thread);
|
||||
+prepend void _Jv_ThreadStackPush (java::lang::Thread *thread, _Jv_Frame *frame);
|
||||
+prepend void _Jv_ThreadStackPop (java::lang::Thread *thread);
|
||||
friend _Jv_JNIEnv * ::_Jv_GetCurrentJNIEnv ();
|
||||
friend void ::_Jv_SetCurrentJNIEnv (_Jv_JNIEnv *env);
|
||||
friend void ::_Jv_ThreadRun (java::lang::Thread* thread);
|
||||
@@ -24,6 +28,9 @@
|
||||
friend java::lang::Thread* ::_Jv_AttachCurrentThread (jstring name, java::lang::ThreadGroup* group);
|
||||
friend java::lang::Thread* ::_Jv_AttachCurrentThreadAsDaemon (jstring name, java::lang::ThreadGroup* group);
|
||||
friend jint (::_Jv_DetachCurrentThread) ();
|
||||
+friend _Jv_Frame *::_Jv_ThreadStackPeek (java::lang::Thread *thread);
|
||||
+friend void ::_Jv_ThreadStackPush (java::lang::Thread *thread, _Jv_Frame *frame);
|
||||
+friend void ::_Jv_ThreadStackPop (java::lang::Thread *thread);
|
||||
|
||||
class java/lang/String
|
||||
prepend jchar* _Jv_GetStringChars (jstring str);
|
||||
--- libjava/gnu/classpath/jdwp/natVMFrame.cc (revision 128603)
|
||||
+++ libjava/gnu/classpath/jdwp/natVMFrame.cc (working copy)
|
||||
@@ -181,7 +181,7 @@
|
||||
getFrameDepth (_Jv_Frame *frame)
|
||||
{
|
||||
jint depth = 0;
|
||||
- _Jv_Frame *top_frame = (_Jv_Frame *) frame->thread->frame;
|
||||
+ _Jv_Frame *top_frame = _Jv_ThreadStackPeek (frame->thread);
|
||||
jint num_frames = VMVirtualMachine::getFrameCount (frame->thread);
|
||||
|
||||
while (frame != top_frame)
|
||||
--- libjava/gnu/classpath/jdwp/natVMVirtualMachine.cc (revision 128603)
|
||||
+++ libjava/gnu/classpath/jdwp/natVMVirtualMachine.cc (working copy)
|
||||
@@ -553,7 +553,7 @@
|
||||
|
||||
frame_list = new ::java::util::ArrayList (num_frames);
|
||||
|
||||
- _Jv_Frame *vm_frame = reinterpret_cast<_Jv_Frame *> (thread->frame);
|
||||
+ _Jv_Frame *vm_frame = _Jv_ThreadStackPeek (thread);
|
||||
|
||||
// Take start frames off the top of the stack
|
||||
while (vm_frame != NULL && start > 0)
|
||||
@@ -584,7 +584,7 @@
|
||||
{
|
||||
using namespace gnu::classpath::jdwp::exception;
|
||||
|
||||
- _Jv_Frame *vm_frame = (_Jv_Frame *) thread->frame;
|
||||
+ _Jv_Frame *vm_frame = _Jv_ThreadStackPeek (thread);
|
||||
jint depth = 0;
|
||||
_Jv_Frame *frame = reinterpret_cast<_Jv_Frame *> (frameID);
|
||||
|
||||
--- libjava/java/lang/Thread.java (revision 128603)
|
||||
+++ libjava/java/lang/Thread.java (working copy)
|
||||
@@ -186,9 +186,6 @@
|
||||
// This describes the top-most interpreter frame for this thread.
|
||||
RawData interp_frame;
|
||||
|
||||
- // This describes the top most frame in the composite (interp + JNI) stack
|
||||
- RawData frame;
|
||||
-
|
||||
// Current state.
|
||||
volatile int state;
|
||||
|
||||
--- libjava/java/lang/natThread.cc (revision 128603)
|
||||
+++ libjava/java/lang/natThread.cc (working copy)
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <gcj/cni.h>
|
||||
#include <jvm.h>
|
||||
#include <java-threads.h>
|
||||
+#include <java-interp.h>
|
||||
|
||||
#include <gnu/gcj/RawDataManaged.h>
|
||||
#include <java/lang/Thread.h>
|
||||
@@ -525,3 +526,25 @@
|
||||
|
||||
return 0;
|
||||
}
|
||||
+
|
||||
+_Jv_Frame *
|
||||
+_Jv_ThreadStackPeek (java::lang::Thread *thread)
|
||||
+{
|
||||
+ struct natThread *nt = (natThread *) thread->data;
|
||||
+ return nt->frame;
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+_Jv_ThreadStackPush (java::lang::Thread *thread, _Jv_Frame *frame)
|
||||
+{
|
||||
+ struct natThread *nt = (natThread *) thread->data;
|
||||
+ nt->frame = frame;
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+_Jv_ThreadStackPop (java::lang::Thread *thread)
|
||||
+{
|
||||
+ struct natThread *nt = (natThread *) thread->data;
|
||||
+ _Jv_Frame *next = nt->frame->next;
|
||||
+ nt->frame = next;
|
||||
+}
|
@ -1,54 +0,0 @@
|
||||
2007-09-22 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* configure.ac (MAKEINFO): Handle makeinfo version 4.10 and above.
|
||||
* configure: Regenerated.
|
||||
|
||||
2007-09-15 Alan Modra <amodra@bigpond.net.au>
|
||||
|
||||
* configure.in: Correct makeinfo version check.
|
||||
* configure: Regenerate.
|
||||
|
||||
--- configure.in.jj 2007-02-20 16:41:55.000000000 -0500
|
||||
+++ configure.in 2007-09-22 09:36:04.000000000 -0400
|
||||
@@ -2159,7 +2159,7 @@ changequote(,)
|
||||
# For an installed makeinfo, we require it to be from texinfo 4.2 or
|
||||
# higher, else we use the "missing" dummy.
|
||||
if ${MAKEINFO} --version \
|
||||
- | egrep 'texinfo[^0-9]*([1-3][0-9]|4\.[2-9]|[5-9])' >/dev/null 2>&1; then
|
||||
+ | egrep 'texinfo[^0-9]*(4\.([2-9]|[1-9][0-9])|[5-9]|[1-9][0-9])' >/dev/null 2>&1; then
|
||||
:
|
||||
else
|
||||
MAKEINFO="$MISSING makeinfo"
|
||||
--- configure.jj 2007-02-20 16:41:55.000000000 -0500
|
||||
+++ configure 2007-09-22 09:36:25.000000000 -0400
|
||||
@@ -3574,7 +3574,7 @@ case " $build_configdirs " in
|
||||
# For an installed makeinfo, we require it to be from texinfo 4.2 or
|
||||
# higher, else we use the "missing" dummy.
|
||||
if ${MAKEINFO} --version \
|
||||
- | egrep 'texinfo[^0-9]*([1-3][0-9]|4\.[2-9]|[5-9])' >/dev/null 2>&1; then
|
||||
+ | egrep 'texinfo[^0-9]*(4\.([2-9]|[1-9][0-9])|[5-9]|[1-9][0-9])' >/dev/null 2>&1; then
|
||||
:
|
||||
else
|
||||
MAKEINFO="$MISSING makeinfo"
|
||||
--- gcc/configure.ac.jj 2007-02-20 16:39:12.000000000 -0500
|
||||
+++ gcc/configure.ac 2007-09-22 08:38:07.000000000 -0400
|
||||
@@ -833,7 +833,7 @@ MISSING="${CONFIG_SHELL-/bin/sh} $srcdir
|
||||
# that we can use it.
|
||||
gcc_AC_CHECK_PROG_VER(MAKEINFO, makeinfo, --version,
|
||||
[GNU texinfo.* \([0-9][0-9.]*\)],
|
||||
- [4.[2-9]*])
|
||||
+ [4.[2-9]*|4.[1-9][0-9]*|[5-9]*|[1-9][0-9]*])
|
||||
if test $gcc_cv_prog_makeinfo_modern = no; then
|
||||
MAKEINFO="$MISSING makeinfo"
|
||||
AC_MSG_WARN([
|
||||
--- gcc/configure.jj 2007-02-20 16:39:12.000000000 -0500
|
||||
+++ gcc/configure 2007-09-22 08:38:30.000000000 -0400
|
||||
@@ -7496,7 +7496,7 @@ else
|
||||
echo "configure:7496: version of makeinfo is $ac_prog_version" >&5
|
||||
case $ac_prog_version in
|
||||
'') gcc_cv_prog_makeinfo_modern=no;;
|
||||
- 4.[2-9]*)
|
||||
+ 4.[2-9]*|4.[1-9][0-9]*|[5-9]*|[1-9][0-9]*)
|
||||
gcc_cv_prog_makeinfo_modern=yes;;
|
||||
*) gcc_cv_prog_makeinfo_modern=no;;
|
||||
esac
|
@ -1,82 +0,0 @@
|
||||
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"
|
@ -1,34 +0,0 @@
|
||||
2007-08-20 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* config/rs6000/tramp.asm: Include config.h.
|
||||
Check __PIC__ or __pic__ macro instead of SHARED.
|
||||
|
||||
--- gcc/config/rs6000/tramp.asm.jj 2006-10-05 00:28:33.000000000 +0200
|
||||
+++ gcc/config/rs6000/tramp.asm 2007-08-20 23:20:52.000000000 +0200
|
||||
@@ -1,6 +1,6 @@
|
||||
/* Special support for trampolines
|
||||
*
|
||||
- * Copyright (C) 1996, 1997, 2000 Free Software Foundation, Inc.
|
||||
+ * Copyright (C) 1996, 1997, 2000, 2007 Free Software Foundation, Inc.
|
||||
* Written By Michael Meissner
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify it
|
||||
@@ -37,7 +37,8 @@
|
||||
|
||||
.file "tramp.asm"
|
||||
.section ".text"
|
||||
- #include "ppc-asm.h"
|
||||
+#include "ppc-asm.h"
|
||||
+#include "config.h"
|
||||
|
||||
#ifndef __powerpc64__
|
||||
.type trampoline_initial,@object
|
||||
@@ -105,7 +106,7 @@ FUNC_START(__trampoline_setup)
|
||||
blr
|
||||
|
||||
.Labort:
|
||||
-#if defined SHARED && defined HAVE_AS_REL16
|
||||
+#if (defined __PIC__ || defined __pic__) && defined HAVE_AS_REL16
|
||||
bcl 20,31,1f
|
||||
1: mflr r30
|
||||
addis r30,r30,_GLOBAL_OFFSET_TABLE_-1b@ha
|
59
gcc41-pr20880.patch
Normal file
59
gcc41-pr20880.patch
Normal file
@ -0,0 +1,59 @@
|
||||
2006-11-24 Paul Thomas <pault@gcc.gnu.org>
|
||||
|
||||
PR fortran/20880
|
||||
* parse.c (parse_interface): Error if procedure name is that of
|
||||
encompassing scope.
|
||||
|
||||
* gfortran.dg/interface_3a.f90: New test.
|
||||
|
||||
--- gcc/fortran/parse.c (revision 119172)
|
||||
+++ gcc/fortran/parse.c (revision 119173)
|
||||
@@ -1694,6 +1694,7 @@ parse_interface (void)
|
||||
gfc_interface_info save;
|
||||
gfc_state_data s1, s2;
|
||||
gfc_statement st;
|
||||
+ locus proc_locus;
|
||||
|
||||
accept_statement (ST_INTERFACE);
|
||||
|
||||
@@ -1781,6 +1782,7 @@ loop:
|
||||
accept_statement (st);
|
||||
prog_unit = gfc_new_block;
|
||||
prog_unit->formal_ns = gfc_current_ns;
|
||||
+ proc_locus = gfc_current_locus;
|
||||
|
||||
decl:
|
||||
/* Read data declaration statements. */
|
||||
@@ -1796,8 +1798,15 @@ decl:
|
||||
|
||||
current_interface = save;
|
||||
gfc_add_interface (prog_unit);
|
||||
-
|
||||
pop_state ();
|
||||
+
|
||||
+ if (current_interface.ns
|
||||
+ && current_interface.ns->proc_name
|
||||
+ && strcmp (current_interface.ns->proc_name->name,
|
||||
+ prog_unit->name) == 0)
|
||||
+ gfc_error ("INTERFACE procedure '%s' at %L has the same name as the "
|
||||
+ "enclosing procedure", prog_unit->name, &proc_locus);
|
||||
+
|
||||
goto loop;
|
||||
|
||||
done:
|
||||
--- gcc/testsuite/gfortran.dg/interface_3a.f90
|
||||
+++ gcc/testsuite/gfortran.dg/interface_3a.f90
|
||||
@@ -0,0 +1,13 @@
|
||||
+! { dg-do compile }
|
||||
+! Contributed by Joost VandeVondele <jv244@cam.ac.uk>
|
||||
+!
|
||||
+! This was found whilst investigating => segfault
|
||||
+subroutine thy_sub (a)
|
||||
+ interface
|
||||
+ subroutine thy_sub (a) ! { dg-error "enclosing procedure" }
|
||||
+ real a
|
||||
+ end subroutine
|
||||
+ end interface
|
||||
+ real a
|
||||
+ print *, a
|
||||
+end subroutine
|
@ -1,63 +0,0 @@
|
||||
2007-08-14 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR fortran/22244
|
||||
* Make-lang.in (fortran/trans-types.o): Depend on $(FLAGS_H).
|
||||
* trans-types.c: Include flags.h.
|
||||
(gfc_get_nodesc_array_type): Add TYPE_DECL TYPE_NAME with
|
||||
correct bounds and dimensions for packed arrays.
|
||||
|
||||
--- gcc/fortran/Make-lang.in (revision 127395)
|
||||
+++ gcc/fortran/Make-lang.in (working copy)
|
||||
@@ -292,7 +292,7 @@ fortran/trans-decl.o: $(GFORTRAN_TRANS_D
|
||||
cgraph.h $(TARGET_H) function.h $(FLAGS_H) $(RTL_H) tree-gimple.h \
|
||||
tree-dump.h
|
||||
fortran/trans-types.o: $(GFORTRAN_TRANS_DEPS) gt-fortran-trans-types.h \
|
||||
- real.h toplev.h $(TARGET_H)
|
||||
+ real.h toplev.h $(TARGET_H) $(FLAGS_H)
|
||||
fortran/trans-const.o: $(GFORTRAN_TRANS_DEPS)
|
||||
fortran/trans-expr.o: $(GFORTRAN_TRANS_DEPS) fortran/dependency.h
|
||||
fortran/trans-stmt.o: $(GFORTRAN_TRANS_DEPS) fortran/dependency.h
|
||||
--- gcc/fortran/trans-types.c (revision 127395)
|
||||
+++ gcc/fortran/trans-types.c (working copy)
|
||||
@@ -35,6 +35,7 @@ Software Foundation, 51 Franklin Street,
|
||||
#include "trans-types.h"
|
||||
#include "trans-const.h"
|
||||
#include "real.h"
|
||||
+#include "flags.h"
|
||||
|
||||
|
||||
#if (GFC_MAX_DIMENSIONS < 10)
|
||||
@@ -1005,7 +1006,7 @@ gfc_get_nodesc_array_type (tree etype, g
|
||||
{
|
||||
/* Fill in the stride and bound components of the type. */
|
||||
if (known_stride)
|
||||
- tmp = gfc_conv_mpz_to_tree (stride, gfc_index_integer_kind);
|
||||
+ tmp = gfc_conv_mpz_to_tree (stride, gfc_index_integer_kind);
|
||||
else
|
||||
tmp = NULL_TREE;
|
||||
GFC_TYPE_ARRAY_STRIDE (type, n) = tmp;
|
||||
@@ -1103,6 +1104,24 @@ gfc_get_nodesc_array_type (tree etype, g
|
||||
mpz_clear (stride);
|
||||
mpz_clear (delta);
|
||||
|
||||
+ /* In debug info represent packed arrays as multi-dimensional
|
||||
+ if they have rank > 1 and with proper bounds, instead of flat
|
||||
+ arrays. */
|
||||
+ if (known_stride && write_symbols != NO_DEBUG)
|
||||
+ {
|
||||
+ tree gtype = etype, rtype, type_decl;
|
||||
+
|
||||
+ for (n = as->rank - 1; n >= 0; n--)
|
||||
+ {
|
||||
+ rtype = build_range_type (gfc_array_index_type,
|
||||
+ GFC_TYPE_ARRAY_LBOUND (type, n),
|
||||
+ GFC_TYPE_ARRAY_UBOUND (type, n));
|
||||
+ gtype = build_array_type (gtype, rtype);
|
||||
+ }
|
||||
+ TYPE_NAME (type) = type_decl = build_decl (TYPE_DECL, NULL, gtype);
|
||||
+ DECL_ORIGINAL_TYPE (type_decl) = gtype;
|
||||
+ }
|
||||
+
|
||||
if (packed < 3 || !known_stride)
|
||||
{
|
||||
/* For dummy arrays and automatic (heap allocated) arrays we
|
@ -1,84 +0,0 @@
|
||||
2006-10-27 Jerry DeLisle <jvdelisle@gcc.gnu.org>
|
||||
|
||||
PR fortran/27954
|
||||
* decl.c (gfc_free_data_all): New function to free all data structures
|
||||
after errors in DATA statements and declarations.
|
||||
(top_var_list): Use new function.(top_val_list): Use new function.
|
||||
(gfc_match_data_decl): Use new function.
|
||||
|
||||
PR libgfortran/27954
|
||||
* gfortran.dg/error_recovery_2.f90: New test.
|
||||
|
||||
--- gcc/fortran/decl.c (revision 118083)
|
||||
+++ gcc/fortran/decl.c (revision 118086)
|
||||
@@ -128,6 +128,21 @@ gfc_free_data (gfc_data * p)
|
||||
}
|
||||
|
||||
|
||||
+/* Free all data in a namespace. */
|
||||
+static void
|
||||
+gfc_free_data_all (gfc_namespace * ns)
|
||||
+{
|
||||
+ gfc_data *d;
|
||||
+
|
||||
+ for (;ns->data;)
|
||||
+ {
|
||||
+ d = ns->data->next;
|
||||
+ gfc_free (ns->data);
|
||||
+ ns->data = d;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+
|
||||
static match var_element (gfc_data_variable *);
|
||||
|
||||
/* Match a list of variables terminated by an iterator and a right
|
||||
@@ -262,6 +277,7 @@ top_var_list (gfc_data * d)
|
||||
|
||||
syntax:
|
||||
gfc_syntax_error (ST_DATA);
|
||||
+ gfc_free_data_all (gfc_current_ns);
|
||||
return MATCH_ERROR;
|
||||
}
|
||||
|
||||
@@ -374,6 +390,7 @@ top_val_list (gfc_data * data)
|
||||
|
||||
syntax:
|
||||
gfc_syntax_error (ST_DATA);
|
||||
+ gfc_free_data_all (gfc_current_ns);
|
||||
return MATCH_ERROR;
|
||||
}
|
||||
|
||||
@@ -2368,6 +2385,8 @@ ok:
|
||||
gfc_error ("Syntax error in data declaration at %C");
|
||||
m = MATCH_ERROR;
|
||||
|
||||
+ gfc_free_data_all (gfc_current_ns);
|
||||
+
|
||||
cleanup:
|
||||
gfc_free_array_spec (current_as);
|
||||
current_as = NULL;
|
||||
--- gcc/testsuite/gfortran.dg/error_recovery_2.f90 (revision 0)
|
||||
+++ gcc/testsuite/gfortran.dg/error_recovery_2.f90 (revision 118086)
|
||||
@@ -0,0 +1,21 @@
|
||||
+! { dg-do compile }
|
||||
+! PR27954 Internal compiler error on bad statements
|
||||
+! Derived from test case submitted in PR.
|
||||
+subroutine bad1
|
||||
+ character*20 :: y, x 00 ! { dg-error "Syntax error" }
|
||||
+ data y /'abcdef'/, x /'jbnhjk'/ pp ! { dg-error "Syntax error" }
|
||||
+end subroutine bad1
|
||||
+
|
||||
+subroutine bad2
|
||||
+ character*20 :: y, x 00 ! { dg-error "Syntax error" }
|
||||
+ data y /'abcdef'/, x /'jbnhjk'/ pp ! { dg-error "Syntax error" }
|
||||
+ print *, "basket case."
|
||||
+end subroutine bad2
|
||||
+
|
||||
+subroutine bad3
|
||||
+ implicit none
|
||||
+ character*20 :: y, x 00 ! { dg-error "Syntax error" }
|
||||
+ data y /'abcdef'/, x /'jbnhjk'/ pp ! { dg-error "Syntax error" }
|
||||
+ print *, "basket case that segfaults without patch."
|
||||
+end subroutine bad3
|
||||
+
|
@ -1,44 +1,210 @@
|
||||
2006-08-17 Jakub Jelinek <jakub@redhat.com>
|
||||
2007-09-23 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR middle-end/28755
|
||||
* expr.c (expand_expr_real_1) <case ARRAY_REF>: Make sure
|
||||
the const array field optimization doesn't create an extra constant
|
||||
MEM.
|
||||
* expr.c (expand_constructor): New function.
|
||||
(expand_expr_real_1) <case CONSTRUCTOR>: Call it.
|
||||
(expand_expr_real_1) <case ARRAY_REF>: Call it if VALUE is
|
||||
CONSTRUCTOR.
|
||||
|
||||
* gcc.dg/pr28755.c: New test.
|
||||
|
||||
--- gcc/expr.c.jj 2006-08-09 17:54:03.000000000 +0200
|
||||
+++ gcc/expr.c 2006-08-17 13:00:33.000000000 +0200
|
||||
@@ -7105,13 +7105,25 @@ expand_expr_real_1 (tree exp, rtx target
|
||||
--- gcc/expr.c (revision 128684)
|
||||
+++ gcc/expr.c (revision 128685)
|
||||
@@ -6435,6 +6435,89 @@ expand_expr_addr_expr (tree exp, rtx tar
|
||||
return result;
|
||||
}
|
||||
|
||||
+/* Generate code for computing CONSTRUCTOR EXP.
|
||||
+ An rtx for the computed value is returned. If AVOID_TEMP_MEM
|
||||
+ is TRUE, instead of creating a temporary variable in memory
|
||||
+ NULL is returned and the caller needs to handle it differently. */
|
||||
+
|
||||
+static rtx
|
||||
+expand_constructor (tree exp, rtx target, enum expand_modifier modifier,
|
||||
+ bool avoid_temp_mem)
|
||||
+{
|
||||
+ tree type = TREE_TYPE (exp);
|
||||
+ enum machine_mode mode = TYPE_MODE (type);
|
||||
+
|
||||
+ /* Try to avoid creating a temporary at all. This is possible
|
||||
+ if all of the initializer is zero.
|
||||
+ FIXME: try to handle all [0..255] initializers we can handle
|
||||
+ with memset. */
|
||||
+ if (TREE_STATIC (exp)
|
||||
+ && !TREE_ADDRESSABLE (exp)
|
||||
+ && target != 0 && mode == BLKmode
|
||||
+ && all_zeros_p (exp))
|
||||
+ {
|
||||
+ clear_storage (target, expr_size (exp), BLOCK_OP_NORMAL);
|
||||
+ return target;
|
||||
+ }
|
||||
+
|
||||
+ /* All elts simple constants => refer to a constant in memory. But
|
||||
+ if this is a non-BLKmode mode, let it store a field at a time
|
||||
+ since that should make a CONST_INT or CONST_DOUBLE when we
|
||||
+ fold. Likewise, if we have a target we can use, it is best to
|
||||
+ store directly into the target unless the type is large enough
|
||||
+ that memcpy will be used. If we are making an initializer and
|
||||
+ all operands are constant, put it in memory as well.
|
||||
+
|
||||
+ FIXME: Avoid trying to fill vector constructors piece-meal.
|
||||
+ Output them with output_constant_def below unless we're sure
|
||||
+ they're zeros. This should go away when vector initializers
|
||||
+ are treated like VECTOR_CST instead of arrays. */
|
||||
+ if ((TREE_STATIC (exp)
|
||||
+ && ((mode == BLKmode
|
||||
+ && ! (target != 0 && safe_from_p (target, exp, 1)))
|
||||
+ || TREE_ADDRESSABLE (exp)
|
||||
+ || (host_integerp (TYPE_SIZE_UNIT (type), 1)
|
||||
+ && (! MOVE_BY_PIECES_P
|
||||
+ (tree_low_cst (TYPE_SIZE_UNIT (type), 1),
|
||||
+ TYPE_ALIGN (type)))
|
||||
+ && ! mostly_zeros_p (exp))))
|
||||
+ || ((modifier == EXPAND_INITIALIZER || modifier == EXPAND_CONST_ADDRESS)
|
||||
+ && TREE_CONSTANT (exp)))
|
||||
+ {
|
||||
+ rtx constructor;
|
||||
+
|
||||
+ if (avoid_temp_mem)
|
||||
+ return NULL_RTX;
|
||||
+
|
||||
+ constructor = output_constant_def (exp, 1);
|
||||
+
|
||||
+ if (modifier != EXPAND_CONST_ADDRESS
|
||||
+ && modifier != EXPAND_INITIALIZER
|
||||
+ && modifier != EXPAND_SUM)
|
||||
+ constructor = validize_mem (constructor);
|
||||
+
|
||||
+ return constructor;
|
||||
+ }
|
||||
+
|
||||
+ /* Handle calls that pass values in multiple non-contiguous
|
||||
+ locations. The Irix 6 ABI has examples of this. */
|
||||
+ if (target == 0 || ! safe_from_p (target, exp, 1)
|
||||
+ || GET_CODE (target) == PARALLEL || modifier == EXPAND_STACK_PARM)
|
||||
+ {
|
||||
+ if (avoid_temp_mem)
|
||||
+ return NULL_RTX;
|
||||
+
|
||||
+ target
|
||||
+ = assign_temp (build_qualified_type (type, (TYPE_QUALS (type)
|
||||
+ | (TREE_READONLY (exp)
|
||||
+ * TYPE_QUAL_CONST))),
|
||||
+ 0, TREE_ADDRESSABLE (exp), 1);
|
||||
+ }
|
||||
+
|
||||
+ store_constructor (exp, target, 0, int_expr_size (exp));
|
||||
+ return target;
|
||||
+}
|
||||
+
|
||||
|
||||
/* expand_expr: generate code for computing expression EXP.
|
||||
An rtx for the computed value is returned. The value is never null.
|
||||
@@ -6899,71 +6982,7 @@ expand_expr_real_1 (tree exp, rtx target
|
||||
return const0_rtx;
|
||||
}
|
||||
|
||||
- /* Try to avoid creating a temporary at all. This is possible
|
||||
- if all of the initializer is zero.
|
||||
- FIXME: try to handle all [0..255] initializers we can handle
|
||||
- with memset. */
|
||||
- else if (TREE_STATIC (exp)
|
||||
- && !TREE_ADDRESSABLE (exp)
|
||||
- && target != 0 && mode == BLKmode
|
||||
- && all_zeros_p (exp))
|
||||
- {
|
||||
- clear_storage (target, expr_size (exp), BLOCK_OP_NORMAL);
|
||||
- return target;
|
||||
- }
|
||||
-
|
||||
- /* All elts simple constants => refer to a constant in memory. But
|
||||
- if this is a non-BLKmode mode, let it store a field at a time
|
||||
- since that should make a CONST_INT or CONST_DOUBLE when we
|
||||
- fold. Likewise, if we have a target we can use, it is best to
|
||||
- store directly into the target unless the type is large enough
|
||||
- that memcpy will be used. If we are making an initializer and
|
||||
- all operands are constant, put it in memory as well.
|
||||
-
|
||||
- FIXME: Avoid trying to fill vector constructors piece-meal.
|
||||
- Output them with output_constant_def below unless we're sure
|
||||
- they're zeros. This should go away when vector initializers
|
||||
- are treated like VECTOR_CST instead of arrays.
|
||||
- */
|
||||
- else if ((TREE_STATIC (exp)
|
||||
- && ((mode == BLKmode
|
||||
- && ! (target != 0 && safe_from_p (target, exp, 1)))
|
||||
- || TREE_ADDRESSABLE (exp)
|
||||
- || (host_integerp (TYPE_SIZE_UNIT (type), 1)
|
||||
- && (! MOVE_BY_PIECES_P
|
||||
- (tree_low_cst (TYPE_SIZE_UNIT (type), 1),
|
||||
- TYPE_ALIGN (type)))
|
||||
- && ! mostly_zeros_p (exp))))
|
||||
- || ((modifier == EXPAND_INITIALIZER
|
||||
- || modifier == EXPAND_CONST_ADDRESS)
|
||||
- && TREE_CONSTANT (exp)))
|
||||
- {
|
||||
- rtx constructor = output_constant_def (exp, 1);
|
||||
-
|
||||
- if (modifier != EXPAND_CONST_ADDRESS
|
||||
- && modifier != EXPAND_INITIALIZER
|
||||
- && modifier != EXPAND_SUM)
|
||||
- constructor = validize_mem (constructor);
|
||||
-
|
||||
- return constructor;
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- /* Handle calls that pass values in multiple non-contiguous
|
||||
- locations. The Irix 6 ABI has examples of this. */
|
||||
- if (target == 0 || ! safe_from_p (target, exp, 1)
|
||||
- || GET_CODE (target) == PARALLEL
|
||||
- || modifier == EXPAND_STACK_PARM)
|
||||
- target
|
||||
- = assign_temp (build_qualified_type (type,
|
||||
- (TYPE_QUALS (type)
|
||||
- | (TREE_READONLY (exp)
|
||||
- * TYPE_QUAL_CONST))),
|
||||
- 0, TREE_ADDRESSABLE (exp), 1);
|
||||
-
|
||||
- store_constructor (exp, target, 0, int_expr_size (exp));
|
||||
- return target;
|
||||
- }
|
||||
+ return expand_constructor (exp, target, modifier, false);
|
||||
|
||||
case MISALIGNED_INDIRECT_REF:
|
||||
case ALIGN_INDIRECT_REF:
|
||||
@@ -7105,10 +7124,25 @@ expand_expr_real_1 (tree exp, rtx target
|
||||
field, value)
|
||||
if (tree_int_cst_equal (field, index))
|
||||
{
|
||||
- if (!TREE_SIDE_EFFECTS (value))
|
||||
- return expand_expr (fold (value), target, tmode,
|
||||
- modifier);
|
||||
- break;
|
||||
+ if (TREE_SIDE_EFFECTS (value))
|
||||
+ break;
|
||||
+
|
||||
+ if (TREE_CODE (value) != CONSTRUCTOR)
|
||||
return expand_expr (fold (value), target, tmode,
|
||||
modifier);
|
||||
+ if (TREE_CODE (value) == CONSTRUCTOR)
|
||||
+ {
|
||||
+ /* If VALUE is a CONSTRUCTOR, this
|
||||
+ optimization is only useful if
|
||||
+ this doesn't store the CONSTRUCTOR
|
||||
+ into memory. If it does, it is more
|
||||
+ efficient to just load the data from
|
||||
+ the array directly. */
|
||||
+ rtx ret = expand_constructor (value, target,
|
||||
+ modifier, true);
|
||||
+ if (ret == NULL_RTX)
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ /* For CONSTRUCTOR this optimization is not always
|
||||
+ a win - if expand_expr creates a temporary
|
||||
+ constant, we just waste unnecessarily rodata
|
||||
+ space. */
|
||||
+ temp = expand_expr (value, target, tmode, modifier);
|
||||
+ if (temp == target
|
||||
+ || (temp && GET_CODE (temp) != MEM))
|
||||
+ return temp;
|
||||
break;
|
||||
+ return expand_expr (fold (value), target, tmode,
|
||||
+ modifier);
|
||||
}
|
||||
}
|
||||
- else if(TREE_CODE (init) == STRING_CST)
|
||||
+ else if (TREE_CODE (init) == STRING_CST)
|
||||
{
|
||||
tree index1 = index;
|
||||
tree low_bound = array_ref_low_bound (exp);
|
||||
--- gcc/testsuite/gcc.dg/pr28755.c.jj 2006-08-17 12:59:57.000000000 +0200
|
||||
+++ gcc/testsuite/gcc.dg/pr28755.c 2006-08-17 12:59:57.000000000 +0200
|
||||
else if(TREE_CODE (init) == STRING_CST)
|
||||
--- gcc/testsuite/gcc.dg/pr28755.c (revision 0)
|
||||
+++ gcc/testsuite/gcc.dg/pr28755.c (revision 128685)
|
||||
@@ -0,0 +1,22 @@
|
||||
+/* PR middle-end/28755 */
|
||||
+/* { dg-do compile } */
|
||||
|
@ -1,63 +0,0 @@
|
||||
2007-07-21 Jerry DeLisle <jvdelisle@gcc.gnu.org>
|
||||
|
||||
PR libgfortran/32678
|
||||
* io/transfer.c (formatted_transfer_scalar): Fix off by one error in
|
||||
calculation of pos and skips. Don't allow pending_spaces to go
|
||||
negative.
|
||||
|
||||
PR fortran/32678
|
||||
* gfortran.dg/fmt_t_5.f90: New test.
|
||||
|
||||
--- libgfortran/io/transfer.c (revision 126821)
|
||||
+++ libgfortran/io/transfer.c (revision 126823)
|
||||
@@ -893,9 +893,9 @@ formatted_transfer_scalar (st_parameter_
|
||||
case FMT_TR:
|
||||
consume_data_flag = 0 ;
|
||||
|
||||
- pos = bytes_used + f->u.n + dtp->u.p.skips;
|
||||
- dtp->u.p.skips = f->u.n + dtp->u.p.skips;
|
||||
- dtp->u.p.pending_spaces = pos - dtp->u.p.max_pos;
|
||||
+ dtp->u.p.skips += f->u.n;
|
||||
+ pos = bytes_used + dtp->u.p.skips - 1;
|
||||
+ dtp->u.p.pending_spaces = pos - dtp->u.p.max_pos + 1;
|
||||
|
||||
/* Writes occur just before the switch on f->format, above, so
|
||||
that trailing blanks are suppressed, unless we are doing a
|
||||
@@ -922,8 +922,6 @@ formatted_transfer_scalar (st_parameter_
|
||||
if (bytes_used == 0)
|
||||
{
|
||||
dtp->u.p.pending_spaces -= f->u.n;
|
||||
- dtp->u.p.pending_spaces = dtp->u.p.pending_spaces < 0 ? 0
|
||||
- : dtp->u.p.pending_spaces;
|
||||
dtp->u.p.skips -= f->u.n;
|
||||
dtp->u.p.skips = dtp->u.p.skips < 0 ? 0 : dtp->u.p.skips;
|
||||
}
|
||||
@@ -945,6 +943,8 @@ formatted_transfer_scalar (st_parameter_
|
||||
dtp->u.p.skips = dtp->u.p.skips + pos - bytes_used;
|
||||
dtp->u.p.pending_spaces = dtp->u.p.pending_spaces
|
||||
+ pos - dtp->u.p.max_pos;
|
||||
+ dtp->u.p.pending_spaces = dtp->u.p.pending_spaces < 0
|
||||
+ ? 0 : dtp->u.p.pending_spaces;
|
||||
|
||||
if (dtp->u.p.skips == 0)
|
||||
break;
|
||||
--- gcc/testsuite/gfortran.dg/fmt_t_5.f90 (revision 126821)
|
||||
+++ gcc/testsuite/gfortran.dg/fmt_t_5.f90 (revision 126823)
|
||||
@@ -0,0 +1,17 @@
|
||||
+! { dg-do run }
|
||||
+! PR32678 GFortan works incorrectly when writing with FORMAT Tx
|
||||
+! Before patch, NULLs were inserted in output.
|
||||
+! Test case from reporter enhanced to detect this problem.
|
||||
+ character(25) :: output
|
||||
+ character(1) :: c
|
||||
+ output = ""
|
||||
+ open (unit=10, file="pr32678testfile", status="replace")
|
||||
+ write (10,10) '12','a','b'
|
||||
+ close (10, status="keep")
|
||||
+ open (unit=10, file="pr32678testfile")
|
||||
+ read(10,20) output(1:21)
|
||||
+ if (output(1:21).ne."ab x") call abort
|
||||
+ close (10, status="delete")
|
||||
+ 10 format (a2,t1,a1,t2,a1,t20,' x')
|
||||
+ 20 format (a21)
|
||||
+ end
|
46
gcc41-pr32694.patch
Normal file
46
gcc41-pr32694.patch
Normal file
@ -0,0 +1,46 @@
|
||||
2007-09-25 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR tree-optimization/32694
|
||||
2006-11-08 Roger Sayle <roger@eyesopen.com>
|
||||
* tree-ssa-propagate.c (set_rhs): Verify tcc_comparison the same way
|
||||
as tcc_binary.
|
||||
|
||||
* gcc.c-torture/compile/20070925-1.c: New test.
|
||||
|
||||
--- gcc/tree-ssa-propagate.c.jj 2007-09-23 19:43:36.000000000 +0200
|
||||
+++ gcc/tree-ssa-propagate.c 2007-09-25 09:30:50.000000000 +0200
|
||||
@@ -570,7 +570,8 @@ set_rhs (tree *stmt_p, tree expr)
|
||||
ssa_op_iter iter;
|
||||
|
||||
/* Verify the constant folded result is valid gimple. */
|
||||
- if (TREE_CODE_CLASS (code) == tcc_binary)
|
||||
+ if (TREE_CODE_CLASS (code) == tcc_binary
|
||||
+ || TREE_CODE_CLASS (code) == tcc_comparison)
|
||||
{
|
||||
if (!is_gimple_val (TREE_OPERAND (expr, 0))
|
||||
|| !is_gimple_val (TREE_OPERAND (expr, 1)))
|
||||
--- gcc/testsuite/gcc.c-torture/compile/20070925-1.c.jj 2007-09-25 09:28:37.000000000 +0200
|
||||
+++ gcc/testsuite/gcc.c-torture/compile/20070925-1.c 2007-09-25 09:29:41.000000000 +0200
|
||||
@@ -0,0 +1,22 @@
|
||||
+/* PR tree-optimization/32694 */
|
||||
+
|
||||
+typedef signed long long int WordS64;
|
||||
+typedef unsigned long long int Word64;
|
||||
+
|
||||
+int
|
||||
+foo (Word64 * p)
|
||||
+{
|
||||
+ while (1)
|
||||
+ {
|
||||
+ WordS64 c = 0x1llu;
|
||||
+ WordS64 x = *p;
|
||||
+ if (c >= 0)
|
||||
+ {
|
||||
+ if (x > (WordS64) 0x7FFFFFFFFFFFFFFFll - c)
|
||||
+ return 6;
|
||||
+ }
|
||||
+ else if (x < (WordS64) 0x8000000000000000ll - c)
|
||||
+ return 7;
|
||||
+ p++;
|
||||
+ }
|
||||
+}
|
@ -1,138 +0,0 @@
|
||||
2007-08-20 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR middle-end/32912
|
||||
* fold-const.c (fold_binary): Only optimize X | ~X and X ^ ~X for
|
||||
integral types.
|
||||
|
||||
* gcc.dg/pr32912-1.c: New test.
|
||||
* gcc.dg/pr32912-2.c: New test.
|
||||
|
||||
--- gcc/fold-const.c.jj 2007-08-13 15:11:18.000000000 +0200
|
||||
+++ gcc/fold-const.c 2007-08-20 15:49:05.000000000 +0200
|
||||
@@ -8079,6 +8079,7 @@ fold_binary (enum tree_code code, tree t
|
||||
|
||||
/* ~X | X is -1. */
|
||||
if (TREE_CODE (arg0) == BIT_NOT_EXPR
|
||||
+ && INTEGRAL_TYPE_P (TREE_TYPE (arg1))
|
||||
&& operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
|
||||
{
|
||||
t1 = build_int_cst (type, -1);
|
||||
@@ -8088,6 +8089,7 @@ fold_binary (enum tree_code code, tree t
|
||||
|
||||
/* X | ~X is -1. */
|
||||
if (TREE_CODE (arg1) == BIT_NOT_EXPR
|
||||
+ && INTEGRAL_TYPE_P (TREE_TYPE (arg0))
|
||||
&& operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
|
||||
{
|
||||
t1 = build_int_cst (type, -1);
|
||||
@@ -8175,6 +8177,7 @@ fold_binary (enum tree_code code, tree t
|
||||
|
||||
/* ~X ^ X is -1. */
|
||||
if (TREE_CODE (arg0) == BIT_NOT_EXPR
|
||||
+ && INTEGRAL_TYPE_P (TREE_TYPE (arg1))
|
||||
&& operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
|
||||
{
|
||||
t1 = build_int_cst (type, -1);
|
||||
@@ -8184,6 +8187,7 @@ fold_binary (enum tree_code code, tree t
|
||||
|
||||
/* X ^ ~X is -1. */
|
||||
if (TREE_CODE (arg1) == BIT_NOT_EXPR
|
||||
+ && INTEGRAL_TYPE_P (TREE_TYPE (arg0))
|
||||
&& operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
|
||||
{
|
||||
t1 = build_int_cst (type, -1);
|
||||
--- gcc/testsuite/gcc.dg/pr32912-1.c.jj 2007-08-20 14:43:05.000000000 +0200
|
||||
+++ gcc/testsuite/gcc.dg/pr32912-1.c 2007-08-20 14:43:23.000000000 +0200
|
||||
@@ -0,0 +1,44 @@
|
||||
+/* PR middle-end/32912 */
|
||||
+/* { dg-do run } */
|
||||
+/* { dg-options "-O2 -w" } */
|
||||
+
|
||||
+extern void abort (void);
|
||||
+
|
||||
+typedef int __m128i __attribute__ ((__vector_size__ (16)));
|
||||
+
|
||||
+__m128i a, b, c, d, e, f;
|
||||
+
|
||||
+void
|
||||
+foo (__m128i x)
|
||||
+{
|
||||
+ a = x ^ ~x;
|
||||
+ b = ~x ^ x;
|
||||
+ c = x | ~x;
|
||||
+ d = ~x | x;
|
||||
+ e = x & ~x;
|
||||
+ f = ~x & x;
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+main (void)
|
||||
+{
|
||||
+ union { __m128i v; int i[sizeof (__m128i) / sizeof (int)]; } u;
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < sizeof (u.i) / sizeof (u.i[0]); i++)
|
||||
+ u.i[i] = i * 49 - 36;
|
||||
+ foo (u.v);
|
||||
+#define check(x, val) \
|
||||
+ u.v = (x); \
|
||||
+ for (i = 0; i < sizeof (u.i) / sizeof (u.i[0]); i++) \
|
||||
+ if (u.i[i] != (val)) \
|
||||
+ abort ()
|
||||
+
|
||||
+ check (a, ~0);
|
||||
+ check (b, ~0);
|
||||
+ check (c, ~0);
|
||||
+ check (d, ~0);
|
||||
+ check (e, 0);
|
||||
+ check (f, 0);
|
||||
+ return 0;
|
||||
+}
|
||||
--- gcc/testsuite/gcc.dg/pr32912-2.c.jj 2007-08-20 15:58:47.000000000 +0200
|
||||
+++ 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 -w" } */
|
||||
+
|
||||
+extern void abort (void);
|
||||
+
|
||||
+typedef int __m128i __attribute__ ((__vector_size__ (16)));
|
||||
+
|
||||
+__m128i a, b, c, d, e, f;
|
||||
+
|
||||
+__m128i
|
||||
+foo (void)
|
||||
+{
|
||||
+ __m128i x = { 0x11111111, 0x22222222, 0x44444444 };
|
||||
+ return x;
|
||||
+}
|
||||
+
|
||||
+__m128i
|
||||
+bar (void)
|
||||
+{
|
||||
+ __m128i x = { 0x11111111, 0x22222222, 0x44444444 };
|
||||
+ return ~x;
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+main (void)
|
||||
+{
|
||||
+ union { __m128i v; int i[sizeof (__m128i) / sizeof (int)]; } u, v;
|
||||
+ int i;
|
||||
+
|
||||
+ u.v = foo ();
|
||||
+ v.v = bar ();
|
||||
+ for (i = 0; i < sizeof (u.i) / sizeof (u.i[0]); i++)
|
||||
+ {
|
||||
+ if (u.i[i] != ~v.i[i])
|
||||
+ abort ();
|
||||
+ if (i < 3)
|
||||
+ {
|
||||
+ if (u.i[i] != (0x11111111 << i))
|
||||
+ abort ();
|
||||
+ }
|
||||
+ else if (u.i[i])
|
||||
+ abort ();
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
@ -1,61 +0,0 @@
|
||||
2007-09-15 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR middle-end/33423
|
||||
* builtins.c (expand_builtin_memory_chk): Handle COMPOUND_EXPRs
|
||||
returned by build_call_expr.
|
||||
|
||||
* gcc.c-torture/compile/20070915-1.c: New test.
|
||||
|
||||
--- gcc/builtins.c.jj 2007-09-14 21:07:41.000000000 +0200
|
||||
+++ gcc/builtins.c 2007-09-16 22:31:40.000000000 +0200
|
||||
@@ -10383,6 +10383,13 @@ expand_builtin_memory_chk (tree exp, rtx
|
||||
return 0;
|
||||
|
||||
fn = build_function_call_expr (fn, arglist);
|
||||
+ STRIP_TYPE_NOPS (fn);
|
||||
+ while (TREE_CODE (fn) == COMPOUND_EXPR)
|
||||
+ {
|
||||
+ expand_expr (TREE_OPERAND (fn, 0), const0_rtx, VOIDmode,
|
||||
+ EXPAND_NORMAL);
|
||||
+ fn = TREE_OPERAND (fn, 1);
|
||||
+ }
|
||||
if (TREE_CODE (fn) == CALL_EXPR)
|
||||
CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
|
||||
return expand_expr (fn, target, mode, EXPAND_NORMAL);
|
||||
@@ -10432,6 +10439,13 @@ expand_builtin_memory_chk (tree exp, rtx
|
||||
if (!fn)
|
||||
return 0;
|
||||
fn = build_function_call_expr (fn, arglist);
|
||||
+ STRIP_TYPE_NOPS (fn);
|
||||
+ while (TREE_CODE (fn) == COMPOUND_EXPR)
|
||||
+ {
|
||||
+ expand_expr (TREE_OPERAND (fn, 0), const0_rtx, VOIDmode,
|
||||
+ EXPAND_NORMAL);
|
||||
+ fn = TREE_OPERAND (fn, 1);
|
||||
+ }
|
||||
if (TREE_CODE (fn) == CALL_EXPR)
|
||||
CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
|
||||
return expand_expr (fn, target, mode, EXPAND_NORMAL);
|
||||
--- gcc/testsuite/gcc.c-torture/compile/20070915-1.c.jj 2007-09-16 22:29:37.000000000 +0200
|
||||
+++ gcc/testsuite/gcc.c-torture/compile/20070915-1.c 2007-09-16 22:29:37.000000000 +0200
|
||||
@@ -0,0 +1,20 @@
|
||||
+/* PR middle-end/33423 */
|
||||
+
|
||||
+static struct
|
||||
+{
|
||||
+ char buf[15];
|
||||
+} u2;
|
||||
+
|
||||
+void
|
||||
+test6 (void)
|
||||
+{
|
||||
+ int len;
|
||||
+ char *p;
|
||||
+
|
||||
+ for (len = 0; len < 2; len++)
|
||||
+ {
|
||||
+ p = __builtin___memset_chk (u2.buf, '\0', len, 15);
|
||||
+ if (p != u2.buf)
|
||||
+ return;
|
||||
+ }
|
||||
+}
|
@ -1,89 +0,0 @@
|
||||
2007-08-17 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* decl.c (variable_decl): Don't share charlen structs if
|
||||
length == NULL.
|
||||
* trans-decl.c (create_function_arglist): Assert
|
||||
f->sym->ts.cl->backend_decl is NULL instead of unsharing
|
||||
charlen struct here.
|
||||
|
||||
* gfortran.dg/assumed_charlen_sharing.f90: New test.
|
||||
|
||||
--- gcc/fortran/decl.c.jj 2007-02-20 22:38:20.000000000 +0100
|
||||
+++ gcc/fortran/decl.c 2007-08-21 20:50:33.000000000 +0200
|
||||
@@ -1086,10 +1086,11 @@ variable_decl (int elem)
|
||||
break;
|
||||
|
||||
/* Non-constant lengths need to be copied after the first
|
||||
- element. */
|
||||
+ element. Also copy assumed lengths. */
|
||||
case MATCH_NO:
|
||||
- if (elem > 1 && current_ts.cl->length
|
||||
- && current_ts.cl->length->expr_type != EXPR_CONSTANT)
|
||||
+ if (elem > 1
|
||||
+ && (current_ts.cl->length == NULL
|
||||
+ || current_ts.cl->length->expr_type != EXPR_CONSTANT))
|
||||
{
|
||||
cl = gfc_get_charlen ();
|
||||
cl->next = gfc_current_ns->cl_list;
|
||||
--- gcc/fortran/trans-decl.c.jj 2007-03-12 08:28:13.000000000 +0100
|
||||
+++ gcc/fortran/trans-decl.c 2007-08-21 20:50:33.000000000 +0200
|
||||
@@ -1417,25 +1417,8 @@ create_function_arglist (gfc_symbol * sy
|
||||
if (!f->sym->ts.cl->length)
|
||||
{
|
||||
TREE_USED (length) = 1;
|
||||
- if (!f->sym->ts.cl->backend_decl)
|
||||
- f->sym->ts.cl->backend_decl = length;
|
||||
- else
|
||||
- {
|
||||
- /* there is already another variable using this
|
||||
- gfc_charlen node, build a new one for this variable
|
||||
- and chain it into the list of gfc_charlens.
|
||||
- This happens for e.g. in the case
|
||||
- CHARACTER(*)::c1,c2
|
||||
- since CHARACTER declarations on the same line share
|
||||
- the same gfc_charlen node. */
|
||||
- gfc_charlen *cl;
|
||||
-
|
||||
- cl = gfc_get_charlen ();
|
||||
- cl->backend_decl = length;
|
||||
- cl->next = f->sym->ts.cl->next;
|
||||
- f->sym->ts.cl->next = cl;
|
||||
- f->sym->ts.cl = cl;
|
||||
- }
|
||||
+ gcc_assert (!f->sym->ts.cl->backend_decl);
|
||||
+ f->sym->ts.cl->backend_decl = length;
|
||||
}
|
||||
|
||||
hidden_typelist = TREE_CHAIN (hidden_typelist);
|
||||
--- gcc/testsuite/gfortran.dg/assumed_charlen_sharing.f90.jj 2007-08-21 08:29:57.000000000 +0200
|
||||
+++ gcc/testsuite/gfortran.dg/assumed_charlen_sharing.f90 2007-08-21 08:29:57.000000000 +0200
|
||||
@@ -0,0 +1,29 @@
|
||||
+! This testcase was miscompiled, because ts.cl
|
||||
+! in function bar was initially shared between both
|
||||
+! dummy arguments. Although it was later unshared,
|
||||
+! all expressions which copied ts.cl from bar2
|
||||
+! before that used incorrectly bar1's length
|
||||
+! instead of bar2.
|
||||
+! { dg-do run }
|
||||
+
|
||||
+subroutine foo (foo1, foo2)
|
||||
+ implicit none
|
||||
+ integer, intent(in) :: foo2
|
||||
+ character(*), intent(in) :: foo1(foo2)
|
||||
+end subroutine foo
|
||||
+
|
||||
+subroutine bar (bar1, bar2)
|
||||
+ implicit none
|
||||
+ character(*), intent(in) :: bar1, bar2
|
||||
+
|
||||
+ call foo ((/ bar2 /), 1)
|
||||
+end subroutine bar
|
||||
+
|
||||
+program test
|
||||
+ character(80) :: str1
|
||||
+ character(5) :: str2
|
||||
+
|
||||
+ str1 = 'String'
|
||||
+ str2 = 'Strng'
|
||||
+ call bar (str2, str1)
|
||||
+end program test
|
@ -1,433 +0,0 @@
|
||||
2007-09-17 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* c-format.h (format_kind_info): Add alloc_char field.
|
||||
* c-format.c (scanf_flag_specs): Add 'm'.
|
||||
(scanf_flag_pairs): Add 'a', 'm' pair.
|
||||
(scan_char_table): Allow 'm' modifier for c, s, [, C and S.
|
||||
(format_types_orig): Add alloc_char fields.
|
||||
(check_format_info_main): Rename aflag to alloc_flag.
|
||||
Handle fki->alloc_char. modifier after width and before length
|
||||
modifiers. Move FMT_FLAG_SCANF_A_KLUDGE handling before
|
||||
length modifiers as well.
|
||||
* config/sol2-c.c (solaris_format_types): Add alloc_char field.
|
||||
|
||||
* gcc.dg/format/c90-scanf-5.c: New test.
|
||||
* gcc.dg/format/c99-scanf-4.c: New test.
|
||||
* gcc.dg/format/ext-7.c: New test.
|
||||
* gcc.dg/format/ext-8.c: New test.
|
||||
|
||||
--- gcc/c-format.h.jj 2007-02-20 22:39:12.000000000 +0100
|
||||
+++ gcc/c-format.h 2007-09-17 22:44:17.000000000 +0200
|
||||
@@ -234,6 +234,8 @@ typedef struct
|
||||
specifiers, but is used to check for bad combinations such as length
|
||||
modifier with assignment suppression in scanf. */
|
||||
int length_code_char;
|
||||
+ /* Assignment-allocation flag character ('m' in scanf), otherwise 0. */
|
||||
+ int alloc_char;
|
||||
/* Pointer to type of argument expected if '*' is used for a width,
|
||||
or NULL if '*' not used for widths. */
|
||||
tree *width_type;
|
||||
--- gcc/c-format.c.jj 2007-02-20 22:39:12.000000000 +0100
|
||||
+++ gcc/c-format.c 2007-09-17 22:51:08.000000000 +0200
|
||||
@@ -423,6 +423,7 @@ static const format_flag_spec scanf_flag
|
||||
{
|
||||
{ '*', 0, 0, N_("assignment suppression"), N_("the assignment suppression scanf feature"), STD_C89 },
|
||||
{ 'a', 0, 0, N_("'a' flag"), N_("the 'a' scanf flag"), STD_EXT },
|
||||
+ { 'm', 0, 0, N_("'m' flag"), N_("the 'm' scanf flag"), STD_EXT },
|
||||
{ 'w', 0, 0, N_("field width"), N_("field width in scanf format"), STD_C89 },
|
||||
{ 'L', 0, 0, N_("length modifier"), N_("length modifier in scanf format"), STD_C89 },
|
||||
{ '\'', 0, 0, N_("''' flag"), N_("the ''' scanf flag"), STD_EXT },
|
||||
@@ -434,6 +435,7 @@ static const format_flag_spec scanf_flag
|
||||
static const format_flag_pair scanf_flag_pairs[] =
|
||||
{
|
||||
{ '*', 'L', 0, 0 },
|
||||
+ { 'a', 'm', 0, 0 },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
@@ -648,16 +650,16 @@ static const format_char_info scan_char_
|
||||
{ "u", 1, STD_C89, { T89_UI, T99_UC, T89_US, T89_UL, T9L_ULL, TEX_ULL, T99_ST, T99_UPD, T99_UIM }, "*w'I", "W", NULL },
|
||||
{ "oxX", 1, STD_C89, { T89_UI, T99_UC, T89_US, T89_UL, T9L_ULL, TEX_ULL, T99_ST, T99_UPD, T99_UIM }, "*w", "W", NULL },
|
||||
{ "efgEG", 1, STD_C89, { T89_F, BADLEN, BADLEN, T89_D, BADLEN, T89_LD, BADLEN, BADLEN, BADLEN }, "*w'", "W", NULL },
|
||||
- { "c", 1, STD_C89, { T89_C, BADLEN, BADLEN, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*w", "cW", NULL },
|
||||
- { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*aw", "cW", NULL },
|
||||
- { "[", 1, STD_C89, { T89_C, BADLEN, BADLEN, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*aw", "cW[", NULL },
|
||||
+ { "c", 1, STD_C89, { T89_C, BADLEN, BADLEN, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*mw", "cW", NULL },
|
||||
+ { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*amw", "cW", NULL },
|
||||
+ { "[", 1, STD_C89, { T89_C, BADLEN, BADLEN, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*amw", "cW[", NULL },
|
||||
{ "p", 2, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*w", "W", NULL },
|
||||
{ "n", 1, STD_C89, { T89_I, T99_SC, T89_S, T89_L, T9L_LL, BADLEN, T99_SST, T99_PD, T99_IM }, "", "W", NULL },
|
||||
/* C99 conversion specifiers. */
|
||||
{ "FaA", 1, STD_C99, { T99_F, BADLEN, BADLEN, T99_D, BADLEN, T99_LD, BADLEN, BADLEN, BADLEN }, "*w'", "W", NULL },
|
||||
/* X/Open conversion specifiers. */
|
||||
- { "C", 1, STD_EXT, { TEX_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*w", "W", NULL },
|
||||
- { "S", 1, STD_EXT, { TEX_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*aw", "W", NULL },
|
||||
+ { "C", 1, STD_EXT, { TEX_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*mw", "W", NULL },
|
||||
+ { "S", 1, STD_EXT, { TEX_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*amw", "W", NULL },
|
||||
{ NULL, 0, 0, NOLENGTHS, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
@@ -700,59 +702,59 @@ static const format_kind_info format_typ
|
||||
{ "printf", printf_length_specs, print_char_table, " +#0-'I", NULL,
|
||||
printf_flag_specs, printf_flag_pairs,
|
||||
FMT_FLAG_ARG_CONVERT|FMT_FLAG_DOLLAR_MULTIPLE|FMT_FLAG_USE_DOLLAR|FMT_FLAG_EMPTY_PREC_OK,
|
||||
- 'w', 0, 'p', 0, 'L',
|
||||
+ 'w', 0, 'p', 0, 'L', 0,
|
||||
&integer_type_node, &integer_type_node
|
||||
},
|
||||
{ "asm_fprintf", asm_fprintf_length_specs, asm_fprintf_char_table, " +#0-", NULL,
|
||||
asm_fprintf_flag_specs, asm_fprintf_flag_pairs,
|
||||
FMT_FLAG_ARG_CONVERT|FMT_FLAG_EMPTY_PREC_OK,
|
||||
- 'w', 0, 'p', 0, 'L',
|
||||
+ 'w', 0, 'p', 0, 'L', 0,
|
||||
NULL, NULL
|
||||
},
|
||||
{ "gcc_diag", gcc_diag_length_specs, gcc_diag_char_table, "q+", NULL,
|
||||
gcc_diag_flag_specs, gcc_diag_flag_pairs,
|
||||
FMT_FLAG_ARG_CONVERT,
|
||||
- 0, 0, 'p', 0, 'L',
|
||||
+ 0, 0, 'p', 0, 'L', 0,
|
||||
NULL, &integer_type_node
|
||||
},
|
||||
{ "gcc_tdiag", gcc_tdiag_length_specs, gcc_tdiag_char_table, "q+", NULL,
|
||||
gcc_tdiag_flag_specs, gcc_tdiag_flag_pairs,
|
||||
FMT_FLAG_ARG_CONVERT,
|
||||
- 0, 0, 'p', 0, 'L',
|
||||
+ 0, 0, 'p', 0, 'L', 0,
|
||||
NULL, &integer_type_node
|
||||
},
|
||||
{ "gcc_cdiag", gcc_cdiag_length_specs, gcc_cdiag_char_table, "q+", NULL,
|
||||
gcc_cdiag_flag_specs, gcc_cdiag_flag_pairs,
|
||||
FMT_FLAG_ARG_CONVERT,
|
||||
- 0, 0, 'p', 0, 'L',
|
||||
+ 0, 0, 'p', 0, 'L', 0,
|
||||
NULL, &integer_type_node
|
||||
},
|
||||
{ "gcc_cxxdiag", gcc_cxxdiag_length_specs, gcc_cxxdiag_char_table, "q+#", NULL,
|
||||
gcc_cxxdiag_flag_specs, gcc_cxxdiag_flag_pairs,
|
||||
FMT_FLAG_ARG_CONVERT,
|
||||
- 0, 0, 'p', 0, 'L',
|
||||
+ 0, 0, 'p', 0, 'L', 0,
|
||||
NULL, &integer_type_node
|
||||
},
|
||||
{ "gcc_gfc", NULL, gcc_gfc_char_table, "", NULL,
|
||||
NULL, gcc_gfc_flag_pairs,
|
||||
FMT_FLAG_ARG_CONVERT,
|
||||
- 0, 0, 0, 0, 0,
|
||||
+ 0, 0, 0, 0, 0, 0,
|
||||
NULL, NULL
|
||||
},
|
||||
{ "scanf", scanf_length_specs, scan_char_table, "*'I", NULL,
|
||||
scanf_flag_specs, scanf_flag_pairs,
|
||||
FMT_FLAG_ARG_CONVERT|FMT_FLAG_SCANF_A_KLUDGE|FMT_FLAG_USE_DOLLAR|FMT_FLAG_ZERO_WIDTH_BAD|FMT_FLAG_DOLLAR_GAP_POINTER_OK,
|
||||
- 'w', 0, 0, '*', 'L',
|
||||
+ 'w', 0, 0, '*', 'L', 'm',
|
||||
NULL, NULL
|
||||
},
|
||||
{ "strftime", NULL, time_char_table, "_-0^#", "EO",
|
||||
strftime_flag_specs, strftime_flag_pairs,
|
||||
- FMT_FLAG_FANCY_PERCENT_OK, 'w', 0, 0, 0, 0,
|
||||
+ FMT_FLAG_FANCY_PERCENT_OK, 'w', 0, 0, 0, 0, 0,
|
||||
NULL, NULL
|
||||
},
|
||||
{ "strfmon", strfmon_length_specs, monetary_char_table, "=^+(!-", NULL,
|
||||
strfmon_flag_specs, strfmon_flag_pairs,
|
||||
- FMT_FLAG_ARG_CONVERT, 'w', '#', 'p', 0, 'L',
|
||||
+ FMT_FLAG_ARG_CONVERT, 'w', '#', 'p', 0, 'L', 0,
|
||||
NULL, NULL
|
||||
}
|
||||
};
|
||||
@@ -1462,7 +1464,7 @@ check_format_info_main (format_check_res
|
||||
const format_length_info *fli = NULL;
|
||||
const format_char_info *fci = NULL;
|
||||
char flag_chars[256];
|
||||
- int aflag = 0;
|
||||
+ int alloc_flag = 0;
|
||||
const char *format_start = format_chars;
|
||||
if (*format_chars == 0)
|
||||
{
|
||||
@@ -1721,6 +1723,31 @@ check_format_info_main (format_check_res
|
||||
}
|
||||
}
|
||||
|
||||
+ if (fki->alloc_char && fki->alloc_char == *format_chars)
|
||||
+ {
|
||||
+ i = strlen (flag_chars);
|
||||
+ flag_chars[i++] = fki->alloc_char;
|
||||
+ flag_chars[i] = 0;
|
||||
+ format_chars++;
|
||||
+ }
|
||||
+
|
||||
+ /* Handle the scanf allocation kludge. */
|
||||
+ if (fki->flags & (int) FMT_FLAG_SCANF_A_KLUDGE)
|
||||
+ {
|
||||
+ if (*format_chars == 'a' && !flag_isoc99)
|
||||
+ {
|
||||
+ if (format_chars[1] == 's' || format_chars[1] == 'S'
|
||||
+ || format_chars[1] == '[')
|
||||
+ {
|
||||
+ /* 'a' is used as a flag. */
|
||||
+ i = strlen (flag_chars);
|
||||
+ flag_chars[i++] = 'a';
|
||||
+ flag_chars[i] = 0;
|
||||
+ format_chars++;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
/* Read any length modifier, if this kind of format has them. */
|
||||
fli = fki->length_char_specs;
|
||||
length_chars = NULL;
|
||||
@@ -1783,23 +1810,6 @@ check_format_info_main (format_check_res
|
||||
}
|
||||
}
|
||||
|
||||
- /* Handle the scanf allocation kludge. */
|
||||
- if (fki->flags & (int) FMT_FLAG_SCANF_A_KLUDGE)
|
||||
- {
|
||||
- if (*format_chars == 'a' && !flag_isoc99)
|
||||
- {
|
||||
- if (format_chars[1] == 's' || format_chars[1] == 'S'
|
||||
- || format_chars[1] == '[')
|
||||
- {
|
||||
- /* 'a' is used as a flag. */
|
||||
- i = strlen (flag_chars);
|
||||
- flag_chars[i++] = 'a';
|
||||
- flag_chars[i] = 0;
|
||||
- format_chars++;
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
-
|
||||
format_char = *format_chars;
|
||||
if (format_char == 0
|
||||
|| (!(fki->flags & (int) FMT_FLAG_FANCY_PERCENT_OK)
|
||||
@@ -1872,7 +1882,9 @@ check_format_info_main (format_check_res
|
||||
|
||||
if ((fki->flags & (int) FMT_FLAG_SCANF_A_KLUDGE)
|
||||
&& strchr (flag_chars, 'a') != 0)
|
||||
- aflag = 1;
|
||||
+ alloc_flag = 1;
|
||||
+ if (fki->alloc_char && strchr (flag_chars, fki->alloc_char) != 0)
|
||||
+ alloc_flag = 1;
|
||||
|
||||
if (fki->suppression_char
|
||||
&& strchr (flag_chars, fki->suppression_char) != 0)
|
||||
@@ -2044,13 +2056,13 @@ check_format_info_main (format_check_res
|
||||
|
||||
wanted_type_ptr->wanted_type = wanted_type;
|
||||
wanted_type_ptr->wanted_type_name = wanted_type_name;
|
||||
- wanted_type_ptr->pointer_count = fci->pointer_count + aflag;
|
||||
+ wanted_type_ptr->pointer_count = fci->pointer_count + alloc_flag;
|
||||
wanted_type_ptr->char_lenient_flag = 0;
|
||||
if (strchr (fci->flags2, 'c') != 0)
|
||||
wanted_type_ptr->char_lenient_flag = 1;
|
||||
wanted_type_ptr->writing_in_flag = 0;
|
||||
wanted_type_ptr->reading_from_flag = 0;
|
||||
- if (aflag)
|
||||
+ if (alloc_flag)
|
||||
wanted_type_ptr->writing_in_flag = 1;
|
||||
else
|
||||
{
|
||||
--- gcc/config/sol2-c.c.jj 2007-02-20 22:39:11.000000000 +0100
|
||||
+++ gcc/config/sol2-c.c 2007-09-17 22:44:17.000000000 +0200
|
||||
@@ -74,7 +74,7 @@ const format_kind_info solaris_format_ty
|
||||
{ "cmn_err", cmn_err_length_specs, cmn_err_char_table, "", NULL,
|
||||
cmn_err_flag_specs, cmn_err_flag_pairs,
|
||||
FMT_FLAG_ARG_CONVERT|FMT_FLAG_EMPTY_PREC_OK,
|
||||
- 'w', 0, 0, 0, 'L',
|
||||
+ 'w', 0, 0, 0, 'L', 0,
|
||||
&integer_type_node, &integer_type_node
|
||||
}
|
||||
};
|
||||
--- gcc/testsuite/gcc.dg/format/c90-scanf-5.c.jj 2007-09-17 22:44:17.000000000 +0200
|
||||
+++ gcc/testsuite/gcc.dg/format/c90-scanf-5.c 2007-09-17 22:44:17.000000000 +0200
|
||||
@@ -0,0 +1,19 @@
|
||||
+/* Test for scanf formats. Formats using extensions to the standard
|
||||
+ should be rejected in strict pedantic mode.
|
||||
+*/
|
||||
+/* { dg-do compile } */
|
||||
+/* { dg-options "-std=iso9899:1990 -pedantic -Wformat" } */
|
||||
+
|
||||
+#include "format.h"
|
||||
+
|
||||
+void
|
||||
+foo (char **sp, wchar_t **lsp)
|
||||
+{
|
||||
+ /* m assignment-allocation modifier, recognized in both C90
|
||||
+ and C99 modes, is a POSIX and ISO/IEC WDTR 24731-2 extension. */
|
||||
+ scanf ("%ms", sp); /* { dg-warning "C" "%ms" } */
|
||||
+ scanf ("%mS", lsp); /* { dg-warning "C" "%mS" } */
|
||||
+ scanf ("%mls", lsp); /* { dg-warning "C" "%mls" } */
|
||||
+ scanf ("%m[bcd]", sp); /* { dg-warning "C" "%m[]" } */
|
||||
+ scanf ("%ml[bcd]", lsp); /* { dg-warning "C" "%ml[]" } */
|
||||
+}
|
||||
--- gcc/testsuite/gcc.dg/format/c99-scanf-4.c.jj 2007-09-17 22:44:17.000000000 +0200
|
||||
+++ gcc/testsuite/gcc.dg/format/c99-scanf-4.c 2007-09-17 22:44:17.000000000 +0200
|
||||
@@ -0,0 +1,19 @@
|
||||
+/* Test for scanf formats. Formats using extensions to the standard
|
||||
+ should be rejected in strict pedantic mode.
|
||||
+*/
|
||||
+/* { dg-do compile } */
|
||||
+/* { dg-options "-std=iso9899:1999 -pedantic -Wformat" } */
|
||||
+
|
||||
+#include "format.h"
|
||||
+
|
||||
+void
|
||||
+foo (char **sp, wchar_t **lsp)
|
||||
+{
|
||||
+ /* m assignment-allocation modifier, recognized in both C90
|
||||
+ and C99 modes, is a POSIX and ISO/IEC WDTR 24731-2 extension. */
|
||||
+ scanf ("%ms", sp); /* { dg-warning "C" "%ms" } */
|
||||
+ scanf ("%mS", lsp); /* { dg-warning "C" "%mS" } */
|
||||
+ scanf ("%mls", lsp); /* { dg-warning "C" "%mls" } */
|
||||
+ scanf ("%m[bcd]", sp); /* { dg-warning "C" "%m[]" } */
|
||||
+ scanf ("%ml[bcd]", lsp); /* { dg-warning "C" "%ml[]" } */
|
||||
+}
|
||||
--- gcc/testsuite/gcc.dg/format/ext-7.c.jj 2007-09-17 22:44:17.000000000 +0200
|
||||
+++ gcc/testsuite/gcc.dg/format/ext-7.c 2007-09-17 22:44:17.000000000 +0200
|
||||
@@ -0,0 +1,85 @@
|
||||
+/* Test for scanf formats. %a and %m extensions. */
|
||||
+/* { dg-do compile } */
|
||||
+/* { dg-options "-std=gnu89 -Wformat" } */
|
||||
+
|
||||
+#include "format.h"
|
||||
+
|
||||
+void
|
||||
+foo (char **sp, wchar_t **lsp, int *ip, float *fp, void **pp, double *dp)
|
||||
+{
|
||||
+ /* %a formats for allocation, only recognized in C90 mode, are a
|
||||
+ GNU extension. Followed by other characters, %a is not treated
|
||||
+ specially.
|
||||
+ */
|
||||
+ scanf ("%as", sp);
|
||||
+ scanf ("%aS", lsp);
|
||||
+ scanf ("%las", dp);
|
||||
+ scanf ("%la", lsp); /* { dg-warning "but argument 2 has type" } */
|
||||
+ scanf ("%las", lsp); /* { dg-warning "but argument 2 has type" } */
|
||||
+ scanf ("%a[bcd]", sp);
|
||||
+ scanf ("%la[bcd]", dp);
|
||||
+ scanf ("%*as");
|
||||
+ scanf ("%*aS");
|
||||
+ scanf ("%*las"); /* { dg-warning "assignment suppression and length modifier" } */
|
||||
+ scanf ("%*a[bcd]");
|
||||
+ scanf ("%*la[bcd]"); /* { dg-warning "assignment suppression and length modifier" } */
|
||||
+ scanf ("%10as", sp);
|
||||
+ scanf ("%5aS", lsp);
|
||||
+ scanf ("%9las", dp);
|
||||
+ scanf ("%25a[bcd]", sp);
|
||||
+ scanf ("%48la[bcd]", dp);
|
||||
+ scanf ("%*10as");
|
||||
+ scanf ("%*5aS");
|
||||
+ scanf ("%*9las"); /* { dg-warning "assignment suppression and length modifier" } */
|
||||
+ scanf ("%*25a[bcd]");
|
||||
+ scanf ("%*48la[bcd]"); /* { dg-warning "assignment suppression and length modifier" } */
|
||||
+
|
||||
+ /* m assignment-allocation modifier, recognized in both C90
|
||||
+ and C99 modes, is a POSIX and ISO/IEC WDTR 24731-2 extension. */
|
||||
+ scanf ("%ms", sp);
|
||||
+ scanf ("%mS", lsp);
|
||||
+ scanf ("%mls", lsp);
|
||||
+ scanf ("%m[bcd]", sp);
|
||||
+ scanf ("%ml[bcd]", lsp);
|
||||
+ scanf ("%mc", sp);
|
||||
+ scanf ("%mlc", lsp);
|
||||
+ scanf ("%mC", lsp);
|
||||
+ scanf ("%*ms");
|
||||
+ scanf ("%*mS");
|
||||
+ scanf ("%*mls"); /* { dg-warning "assignment suppression and length modifier" } */
|
||||
+ scanf ("%*m[bcd]");
|
||||
+ scanf ("%*ml[bcd]"); /* { dg-warning "assignment suppression and length modifier" } */
|
||||
+ scanf ("%*mc");
|
||||
+ scanf ("%*mlc"); /* { dg-warning "assignment suppression and length modifier" } */
|
||||
+ scanf ("%*mC");
|
||||
+ scanf ("%10ms", sp);
|
||||
+ scanf ("%5mS", lsp);
|
||||
+ scanf ("%9mls", lsp);
|
||||
+ scanf ("%25m[bcd]", sp);
|
||||
+ scanf ("%41ml[bcd]", lsp);
|
||||
+ scanf ("%131mc", sp);
|
||||
+ scanf ("%27mlc", lsp);
|
||||
+ scanf ("%2mC", lsp);
|
||||
+ scanf ("%*10ms");
|
||||
+ scanf ("%*5mS");
|
||||
+ scanf ("%*9mls"); /* { dg-warning "assignment suppression and length modifier" } */
|
||||
+ scanf ("%*25m[bcd]");
|
||||
+ scanf ("%*41ml[bcd]"); /* { dg-warning "assignment suppression and length modifier" } */
|
||||
+ scanf ("%*131mc");
|
||||
+ scanf ("%*27mlc"); /* { dg-warning "assignment suppression and length modifier" } */
|
||||
+ scanf ("%*2mC");
|
||||
+
|
||||
+ scanf ("%md", ip); /* { dg-warning "flag used with" } */
|
||||
+ scanf ("%mi", ip); /* { dg-warning "flag used with" } */
|
||||
+ scanf ("%mo", ip); /* { dg-warning "flag used with" } */
|
||||
+ scanf ("%mu", ip); /* { dg-warning "flag used with" } */
|
||||
+ scanf ("%mx", ip); /* { dg-warning "flag used with" } */
|
||||
+ scanf ("%me", fp); /* { dg-warning "flag used with" } */
|
||||
+ scanf ("%mf", fp); /* { dg-warning "flag used with" } */
|
||||
+ scanf ("%mg", fp); /* { dg-warning "flag used with" } */
|
||||
+ scanf ("%mp", pp); /* { dg-warning "flag used with" } */
|
||||
+
|
||||
+ scanf ("%mas", sp); /* { dg-warning "flag together" } */
|
||||
+ scanf ("%maS", lsp); /* { dg-warning "flag together" } */
|
||||
+ scanf ("%ma[bcd]", sp); /* { dg-warning "flag together" } */
|
||||
+}
|
||||
--- gcc/testsuite/gcc.dg/format/ext-8.c.jj 2007-09-17 22:44:17.000000000 +0200
|
||||
+++ gcc/testsuite/gcc.dg/format/ext-8.c 2007-09-17 22:44:17.000000000 +0200
|
||||
@@ -0,0 +1,56 @@
|
||||
+/* Test for scanf formats. %m extensions. */
|
||||
+/* { dg-do compile } */
|
||||
+/* { dg-options "-std=gnu99 -Wformat" } */
|
||||
+
|
||||
+#include "format.h"
|
||||
+
|
||||
+void
|
||||
+foo (char **sp, wchar_t **lsp, int *ip, float *fp, void **pp)
|
||||
+{
|
||||
+ /* m assignment-allocation modifier, recognized in both C90
|
||||
+ and C99 modes, is a POSIX and ISO/IEC WDTR 24731-2 extension. */
|
||||
+ scanf ("%ms", sp);
|
||||
+ scanf ("%mS", lsp);
|
||||
+ scanf ("%mls", lsp);
|
||||
+ scanf ("%m[bcd]", sp);
|
||||
+ scanf ("%ml[bcd]", lsp);
|
||||
+ scanf ("%mc", sp);
|
||||
+ scanf ("%mlc", lsp);
|
||||
+ scanf ("%mC", lsp);
|
||||
+ scanf ("%*ms");
|
||||
+ scanf ("%*mS");
|
||||
+ scanf ("%*mls"); /* { dg-warning "assignment suppression and length modifier" } */
|
||||
+ scanf ("%*m[bcd]");
|
||||
+ scanf ("%*ml[bcd]"); /* { dg-warning "assignment suppression and length modifier" } */
|
||||
+ scanf ("%*mc");
|
||||
+ scanf ("%*mlc"); /* { dg-warning "assignment suppression and length modifier" } */
|
||||
+ scanf ("%*mC");
|
||||
+ scanf ("%10ms", sp);
|
||||
+ scanf ("%5mS", lsp);
|
||||
+ scanf ("%9mls", lsp);
|
||||
+ scanf ("%25m[bcd]", sp);
|
||||
+ scanf ("%41ml[bcd]", lsp);
|
||||
+ scanf ("%131mc", sp);
|
||||
+ scanf ("%27mlc", lsp);
|
||||
+ scanf ("%2mC", lsp);
|
||||
+ scanf ("%*10ms");
|
||||
+ scanf ("%*5mS");
|
||||
+ scanf ("%*9mls"); /* { dg-warning "assignment suppression and length modifier" } */
|
||||
+ scanf ("%*25m[bcd]");
|
||||
+ scanf ("%*41ml[bcd]"); /* { dg-warning "assignment suppression and length modifier" } */
|
||||
+ scanf ("%*131mc");
|
||||
+ scanf ("%*27mlc"); /* { dg-warning "assignment suppression and length modifier" } */
|
||||
+ scanf ("%*2mC");
|
||||
+
|
||||
+ scanf ("%md", ip); /* { dg-warning "flag used with" } */
|
||||
+ scanf ("%mi", ip); /* { dg-warning "flag used with" } */
|
||||
+ scanf ("%mo", ip); /* { dg-warning "flag used with" } */
|
||||
+ scanf ("%mu", ip); /* { dg-warning "flag used with" } */
|
||||
+ scanf ("%mx", ip); /* { dg-warning "flag used with" } */
|
||||
+ scanf ("%ma", fp); /* { dg-warning "flag used with" } */
|
||||
+ scanf ("%mA", fp); /* { dg-warning "flag used with" } */
|
||||
+ scanf ("%me", fp); /* { dg-warning "flag used with" } */
|
||||
+ scanf ("%mf", fp); /* { dg-warning "flag used with" } */
|
||||
+ scanf ("%mg", fp); /* { dg-warning "flag used with" } */
|
||||
+ scanf ("%mp", pp); /* { dg-warning "flag used with" } */
|
||||
+}
|
@ -1,519 +0,0 @@
|
||||
2006-03-02 David S. Miller <davem@sunset.davemloft.net>
|
||||
|
||||
Sun Niagara specific optimizations.
|
||||
* config.gcc: Recognize niagara as target.
|
||||
* config/sparc/sparc.h (SPARC_RELAXED_ORDERING): Mention Niagara.
|
||||
(TARGET_CPU_niagara): Define.
|
||||
(CPP_CPU64_DEFAULT_SPEC): Define __sparc_v9__ for Niagara.
|
||||
(ASM_CPU64_DEFAULT_SPEC): Pass -Av9b for Niagara.
|
||||
(CPP_CPU_SPEC): Handle -mcpu=niagara.
|
||||
(ASM_CPU_SPEC): Likewise.
|
||||
(PROCESSOR_NIAGARA): New enum entry.
|
||||
(REGISTER_MOVE_COST): Handle Niagara.
|
||||
(BRANCH_COST, PREFETCH_BLOCK, SIMULTANEOUS_PREFETCHES): Likewise.
|
||||
* config/sparc/sparc.c (niagara_costs): New processor_costs entry.
|
||||
(sparc_override_options): Recognize "niagara", set appropriate
|
||||
default MASK_* values for it, and align functions to 32-bytes
|
||||
by default just like ULTRASPARC/ULTRASPARC3.
|
||||
(sparc_initialize_trampoline): Handle niagara like ultrasparc.
|
||||
(sparc64_initialize_trampoline): Likewise.
|
||||
(sparc_use_sched_lookahead): Use zero for niagara.
|
||||
(sparc_issue_rate): Use one for niagara.
|
||||
* config/sparc/niagara.md: New file.
|
||||
* config/sparc/sparc.md: Include it.
|
||||
* config/sparc/sol2-bi.h (CPP_CPU64_DEFAULT_SPEC,
|
||||
ASM_CPU32_DEFAULT_SPEC, ASM_CPU64_DEFAULT_SPEC): Set appropriately
|
||||
when default cpu is niagara.
|
||||
(CPP_CPU_SPEC): Handle -mcpu=niagara.
|
||||
(ASM_CPU_SPEC): Likewise.
|
||||
* config/sparc/sol2.h (ASM_CPU_DEFAULT_SPEC): Set appropriately
|
||||
when default cpu is niagara.
|
||||
(ASM_CPU_SPEC): Handle -mcpu=niagara.
|
||||
* config/sparc/linux64.h: Handle a default of TARGET_CPU_niagara
|
||||
just like v9/ultrasparc/ultrasparc3.
|
||||
* doc/invoke.texi: Add documentation for "niagara" and improve
|
||||
existing documentation for ultrasparc variants.
|
||||
|
||||
--- gcc/doc/invoke.texi (revision 111647)
|
||||
+++ gcc/doc/invoke.texi (revision 111648)
|
||||
@@ -12268,8 +12268,8 @@ Set the instruction set, register set, a
|
||||
for machine type @var{cpu_type}. Supported values for @var{cpu_type} are
|
||||
@samp{v7}, @samp{cypress}, @samp{v8}, @samp{supersparc}, @samp{sparclite},
|
||||
@samp{f930}, @samp{f934}, @samp{hypersparc}, @samp{sparclite86x},
|
||||
-@samp{sparclet}, @samp{tsc701}, @samp{v9}, @samp{ultrasparc}, and
|
||||
-@samp{ultrasparc3}.
|
||||
+@samp{sparclet}, @samp{tsc701}, @samp{v9}, @samp{ultrasparc},
|
||||
+@samp{ultrasparc3}, and @samp{niagara}.
|
||||
|
||||
Default instruction scheduling parameters are used for values that select
|
||||
an architecture and not an implementation. These are @samp{v7}, @samp{v8},
|
||||
@@ -12283,7 +12283,7 @@ implementations.
|
||||
v8: supersparc, hypersparc
|
||||
sparclite: f930, f934, sparclite86x
|
||||
sparclet: tsc701
|
||||
- v9: ultrasparc, ultrasparc3
|
||||
+ v9: ultrasparc, ultrasparc3, niagara
|
||||
@end smallexample
|
||||
|
||||
By default (unless configured otherwise), GCC generates code for the V7
|
||||
@@ -12317,9 +12317,11 @@ With @option{-mcpu=v9}, GCC generates co
|
||||
architecture. This adds 64-bit integer and floating-point move instructions,
|
||||
3 additional floating-point condition code registers and conditional move
|
||||
instructions. With @option{-mcpu=ultrasparc}, the compiler additionally
|
||||
-optimizes it for the Sun UltraSPARC I/II chips. With
|
||||
+optimizes it for the Sun UltraSPARC I/II/IIi chips. With
|
||||
@option{-mcpu=ultrasparc3}, the compiler additionally optimizes it for the
|
||||
-Sun UltraSPARC III chip.
|
||||
+Sun UltraSPARC III/III+/IIIi/IIIi+/IV/IV+ chips. With
|
||||
+@option{-mcpu=niagara}, the compiler additionally optimizes it for
|
||||
+Sun UltraSPARC T1 chips.
|
||||
|
||||
@item -mtune=@var{cpu_type}
|
||||
@opindex mtune
|
||||
@@ -12331,8 +12333,8 @@ The same values for @option{-mcpu=@var{c
|
||||
@option{-mtune=@var{cpu_type}}, but the only useful values are those
|
||||
that select a particular cpu implementation. Those are @samp{cypress},
|
||||
@samp{supersparc}, @samp{hypersparc}, @samp{f930}, @samp{f934},
|
||||
-@samp{sparclite86x}, @samp{tsc701}, @samp{ultrasparc}, and
|
||||
-@samp{ultrasparc3}.
|
||||
+@samp{sparclite86x}, @samp{tsc701}, @samp{ultrasparc},
|
||||
+@samp{ultrasparc3}, and @samp{niagara}.
|
||||
|
||||
@item -mv8plus
|
||||
@itemx -mno-v8plus
|
||||
--- gcc/config.gcc (revision 111647)
|
||||
+++ gcc/config.gcc (revision 111648)
|
||||
@@ -2830,7 +2830,7 @@ case "${target}" in
|
||||
"" | sparc | sparcv9 | sparc64 | sparc86x \
|
||||
| v7 | cypress | v8 | supersparc | sparclite | f930 \
|
||||
| f934 | hypersparc | sparclite86x | sparclet | tsc701 \
|
||||
- | v9 | ultrasparc | ultrasparc3)
|
||||
+ | v9 | ultrasparc | ultrasparc3 | niagara)
|
||||
# OK
|
||||
;;
|
||||
*)
|
||||
--- gcc/config/sparc/niagara.md (revision 0)
|
||||
+++ gcc/config/sparc/niagara.md (revision 111648)
|
||||
@@ -0,0 +1,119 @@
|
||||
+;; Scheduling description for Niagara.
|
||||
+;; Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
+;;
|
||||
+;; This file is part of GCC.
|
||||
+;;
|
||||
+;; GCC is free software; you can redistribute it and/or modify
|
||||
+;; it under the terms of the GNU General Public License as published by
|
||||
+;; the Free Software Foundation; either version 2, or (at your option)
|
||||
+;; any later version.
|
||||
+;;
|
||||
+;; GCC is distributed in the hope that it will be useful,
|
||||
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+;; GNU General Public License for more details.
|
||||
+;;
|
||||
+;; You should have received a copy of the GNU General Public License
|
||||
+;; along with GCC; see the file COPYING. If not, write to
|
||||
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
+;; Boston, MA 02110-1301, USA.
|
||||
+
|
||||
+;; Niagara is a single-issue processor.
|
||||
+
|
||||
+(define_automaton "niagara_0")
|
||||
+
|
||||
+(define_cpu_unit "niag_pipe" "niagara_0")
|
||||
+
|
||||
+(define_insn_reservation "niag_5cycle" 5
|
||||
+ (and (eq_attr "cpu" "niagara")
|
||||
+ (eq_attr "type" "multi,flushw,iflush,trap"))
|
||||
+ "niag_pipe*5")
|
||||
+
|
||||
+(define_insn_reservation "niag_4cycle" 4
|
||||
+ (and (eq_attr "cpu" "niagara")
|
||||
+ (eq_attr "type" "savew"))
|
||||
+ "niag_pipe*4")
|
||||
+
|
||||
+/* Most basic operations are single-cycle. */
|
||||
+(define_insn_reservation "niag_ialu" 1
|
||||
+ (and (eq_attr "cpu" "niagara")
|
||||
+ (eq_attr "type" "ialu,shift,compare,cmove"))
|
||||
+ "niag_pipe")
|
||||
+
|
||||
+(define_insn_reservation "niag_imul" 11
|
||||
+ (and (eq_attr "cpu" "niagara")
|
||||
+ (eq_attr "type" "imul"))
|
||||
+ "niag_pipe*11")
|
||||
+
|
||||
+(define_insn_reservation "niag_idiv" 72
|
||||
+ (and (eq_attr "cpu" "niagara")
|
||||
+ (eq_attr "type" "idiv"))
|
||||
+ "niag_pipe*72")
|
||||
+
|
||||
+(define_insn_reservation "niag_branch" 3
|
||||
+ (and (eq_attr "cpu" "niagara")
|
||||
+ (eq_attr "type" "call,sibcall,call_no_delay_slot,uncond_branch,branch"))
|
||||
+ "niag_pipe*3")
|
||||
+
|
||||
+(define_insn_reservation "niag_3cycle_load" 3
|
||||
+ (and (eq_attr "cpu" "niagara")
|
||||
+ (eq_attr "type" "load"))
|
||||
+ "niag_pipe*3")
|
||||
+
|
||||
+(define_insn_reservation "niag_9cycle_load" 9
|
||||
+ (and (eq_attr "cpu" "niagara")
|
||||
+ (eq_attr "type" "fpload"))
|
||||
+ "niag_pipe*9")
|
||||
+
|
||||
+(define_insn_reservation "niag_1cycle_store" 1
|
||||
+ (and (eq_attr "cpu" "niagara")
|
||||
+ (eq_attr "type" "store"))
|
||||
+ "niag_pipe")
|
||||
+
|
||||
+(define_insn_reservation "niag_8cycle_store" 8
|
||||
+ (and (eq_attr "cpu" "niagara")
|
||||
+ (eq_attr "type" "fpstore"))
|
||||
+ "niag_pipe*8")
|
||||
+
|
||||
+/* Things incorrectly modelled here:
|
||||
+ * FPADD{s,d}: 26 cycles
|
||||
+ * FPSUB{s,d}: 26 cycles
|
||||
+ * FABSD: 26 cycles
|
||||
+ * F{s,d}TO{s,d}: 26 cycles
|
||||
+ * F{s,d}TO{i,x}: 26 cycles
|
||||
+ * FSMULD: 29 cycles
|
||||
+ */
|
||||
+(define_insn_reservation "niag_fmov" 8
|
||||
+ (and (eq_attr "cpu" "niagara")
|
||||
+ (eq_attr "type" "fpmove,fpcmove,fpcrmove"))
|
||||
+ "niag_pipe*8")
|
||||
+
|
||||
+(define_insn_reservation "niag_fpcmp" 26
|
||||
+ (and (eq_attr "cpu" "niagara")
|
||||
+ (eq_attr "type" "fpcmp"))
|
||||
+ "niag_pipe*26")
|
||||
+
|
||||
+(define_insn_reservation "niag_fmult" 29
|
||||
+ (and (eq_attr "cpu" "niagara")
|
||||
+ (eq_attr "type" "fpmul"))
|
||||
+ "niag_pipe*29")
|
||||
+
|
||||
+(define_insn_reservation "niag_fdivs" 54
|
||||
+ (and (eq_attr "cpu" "niagara")
|
||||
+ (eq_attr "type" "fpdivs"))
|
||||
+ "niag_pipe*54")
|
||||
+
|
||||
+(define_insn_reservation "niag_fdivd" 83
|
||||
+ (and (eq_attr "cpu" "niagara")
|
||||
+ (eq_attr "type" "fpdivd"))
|
||||
+ "niag_pipe*83")
|
||||
+
|
||||
+/* Things incorrectly modelled here:
|
||||
+ * FPADD{16,32}: 10 cycles
|
||||
+ * FPSUB{16,32}: 10 cycles
|
||||
+ * FALIGNDATA: 10 cycles
|
||||
+ */
|
||||
+(define_insn_reservation "niag_vis" 8
|
||||
+ (and (eq_attr "cpu" "niagara")
|
||||
+ (eq_attr "type" "fga,fgm_pack,fgm_mul,fgm_cmp,fgm_pdist"))
|
||||
+ "niag_pipe*8")
|
||||
--- gcc/config/sparc/sparc.md (revision 111647)
|
||||
+++ gcc/config/sparc/sparc.md (revision 111648)
|
||||
@@ -94,7 +94,8 @@ (define_attr "cpu"
|
||||
sparclet,tsc701,
|
||||
v9,
|
||||
ultrasparc,
|
||||
- ultrasparc3"
|
||||
+ ultrasparc3,
|
||||
+ niagara"
|
||||
(const (symbol_ref "sparc_cpu_attr")))
|
||||
|
||||
;; Attribute for the instruction set.
|
||||
@@ -315,6 +316,7 @@ (define_delay (eq_attr "type" "return")
|
||||
(include "sparclet.md")
|
||||
(include "ultra1_2.md")
|
||||
(include "ultra3.md")
|
||||
+(include "niagara.md")
|
||||
|
||||
|
||||
;; Operand and operator predicates.
|
||||
--- gcc/config/sparc/sparc.c (revision 111647)
|
||||
+++ gcc/config/sparc/sparc.c (revision 111648)
|
||||
@@ -197,6 +197,30 @@ struct processor_costs ultrasparc3_costs
|
||||
0, /* shift penalty */
|
||||
};
|
||||
|
||||
+static const
|
||||
+struct processor_costs niagara_costs = {
|
||||
+ COSTS_N_INSNS (3), /* int load */
|
||||
+ COSTS_N_INSNS (3), /* int signed load */
|
||||
+ COSTS_N_INSNS (3), /* int zeroed load */
|
||||
+ COSTS_N_INSNS (9), /* float load */
|
||||
+ COSTS_N_INSNS (8), /* fmov, fneg, fabs */
|
||||
+ COSTS_N_INSNS (8), /* fadd, fsub */
|
||||
+ COSTS_N_INSNS (26), /* fcmp */
|
||||
+ COSTS_N_INSNS (8), /* fmov, fmovr */
|
||||
+ COSTS_N_INSNS (29), /* fmul */
|
||||
+ COSTS_N_INSNS (54), /* fdivs */
|
||||
+ COSTS_N_INSNS (83), /* fdivd */
|
||||
+ COSTS_N_INSNS (100), /* fsqrts - not implemented in hardware */
|
||||
+ COSTS_N_INSNS (100), /* fsqrtd - not implemented in hardware */
|
||||
+ COSTS_N_INSNS (11), /* imul */
|
||||
+ COSTS_N_INSNS (11), /* imulX */
|
||||
+ 0, /* imul bit factor */
|
||||
+ COSTS_N_INSNS (72), /* idiv */
|
||||
+ COSTS_N_INSNS (72), /* idivX */
|
||||
+ COSTS_N_INSNS (1), /* movcc/movr */
|
||||
+ 0, /* shift penalty */
|
||||
+};
|
||||
+
|
||||
const struct processor_costs *sparc_costs = &cypress_costs;
|
||||
|
||||
#ifdef HAVE_AS_RELAX_OPTION
|
||||
@@ -597,6 +621,7 @@ sparc_override_options (void)
|
||||
{ TARGET_CPU_v9, "v9" },
|
||||
{ TARGET_CPU_ultrasparc, "ultrasparc" },
|
||||
{ TARGET_CPU_ultrasparc3, "ultrasparc3" },
|
||||
+ { TARGET_CPU_niagara, "niagara" },
|
||||
{ 0, 0 }
|
||||
};
|
||||
const struct cpu_default *def;
|
||||
@@ -632,6 +657,8 @@ sparc_override_options (void)
|
||||
/* TI ultrasparc III */
|
||||
/* ??? Check if %y issue still holds true in ultra3. */
|
||||
{ "ultrasparc3", PROCESSOR_ULTRASPARC3, MASK_ISA, MASK_V9|MASK_DEPRECATED_V8_INSNS},
|
||||
+ /* UltraSPARC T1 */
|
||||
+ { "niagara", PROCESSOR_NIAGARA, MASK_ISA, MASK_V9|MASK_DEPRECATED_V8_INSNS},
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
const struct cpu_table *cpu;
|
||||
@@ -741,7 +768,8 @@ sparc_override_options (void)
|
||||
/* Supply a default value for align_functions. */
|
||||
if (align_functions == 0
|
||||
&& (sparc_cpu == PROCESSOR_ULTRASPARC
|
||||
- || sparc_cpu == PROCESSOR_ULTRASPARC3))
|
||||
+ || sparc_cpu == PROCESSOR_ULTRASPARC3
|
||||
+ || sparc_cpu == PROCESSOR_NIAGARA))
|
||||
align_functions = 32;
|
||||
|
||||
/* Validate PCC_STRUCT_RETURN. */
|
||||
@@ -790,6 +818,9 @@ sparc_override_options (void)
|
||||
case PROCESSOR_ULTRASPARC3:
|
||||
sparc_costs = &ultrasparc3_costs;
|
||||
break;
|
||||
+ case PROCESSOR_NIAGARA:
|
||||
+ sparc_costs = &niagara_costs;
|
||||
+ break;
|
||||
};
|
||||
|
||||
#ifdef TARGET_DEFAULT_LONG_DOUBLE_128
|
||||
@@ -7099,7 +7130,8 @@ sparc_initialize_trampoline (rtx tramp,
|
||||
aligned on a 16 byte boundary so one flush clears it all. */
|
||||
emit_insn (gen_flush (validize_mem (gen_rtx_MEM (SImode, tramp))));
|
||||
if (sparc_cpu != PROCESSOR_ULTRASPARC
|
||||
- && sparc_cpu != PROCESSOR_ULTRASPARC3)
|
||||
+ && sparc_cpu != PROCESSOR_ULTRASPARC3
|
||||
+ && sparc_cpu != PROCESSOR_NIAGARA)
|
||||
emit_insn (gen_flush (validize_mem (gen_rtx_MEM (SImode,
|
||||
plus_constant (tramp, 8)))));
|
||||
|
||||
@@ -7141,7 +7173,8 @@ sparc64_initialize_trampoline (rtx tramp
|
||||
emit_insn (gen_flushdi (validize_mem (gen_rtx_MEM (DImode, tramp))));
|
||||
|
||||
if (sparc_cpu != PROCESSOR_ULTRASPARC
|
||||
- && sparc_cpu != PROCESSOR_ULTRASPARC3)
|
||||
+ && sparc_cpu != PROCESSOR_ULTRASPARC3
|
||||
+ && sparc_cpu != PROCESSOR_NIAGARA)
|
||||
emit_insn (gen_flushdi (validize_mem (gen_rtx_MEM (DImode, plus_constant (tramp, 8)))));
|
||||
|
||||
/* Call __enable_execute_stack after writing onto the stack to make sure
|
||||
@@ -7321,6 +7354,8 @@ sparc_sched_init (FILE *dump ATTRIBUTE_U
|
||||
static int
|
||||
sparc_use_sched_lookahead (void)
|
||||
{
|
||||
+ if (sparc_cpu == PROCESSOR_NIAGARA)
|
||||
+ return 0;
|
||||
if (sparc_cpu == PROCESSOR_ULTRASPARC
|
||||
|| sparc_cpu == PROCESSOR_ULTRASPARC3)
|
||||
return 4;
|
||||
@@ -7336,6 +7371,7 @@ sparc_issue_rate (void)
|
||||
{
|
||||
switch (sparc_cpu)
|
||||
{
|
||||
+ case PROCESSOR_NIAGARA:
|
||||
default:
|
||||
return 1;
|
||||
case PROCESSOR_V9:
|
||||
--- gcc/config/sparc/sol2-bi.h (revision 111647)
|
||||
+++ gcc/config/sparc/sol2-bi.h (revision 111648)
|
||||
@@ -39,6 +39,15 @@
|
||||
#define ASM_CPU64_DEFAULT_SPEC AS_SPARC64_FLAG "b"
|
||||
#endif
|
||||
|
||||
+#if TARGET_CPU_DEFAULT == TARGET_CPU_niagara
|
||||
+#undef CPP_CPU64_DEFAULT_SPEC
|
||||
+#define CPP_CPU64_DEFAULT_SPEC ""
|
||||
+#undef ASM_CPU32_DEFAULT_SPEC
|
||||
+#define ASM_CPU32_DEFAULT_SPEC "-xarch=v8plusb"
|
||||
+#undef ASM_CPU64_DEFAULT_SPEC
|
||||
+#define ASM_CPU64_DEFAULT_SPEC AS_SPARC64_FLAG "b"
|
||||
+#endif
|
||||
+
|
||||
#if DEFAULT_ARCH32_P
|
||||
#define DEF_ARCH32_SPEC(__str) "%{!m64:" __str "}"
|
||||
#define DEF_ARCH64_SPEC(__str) "%{m64:" __str "}"
|
||||
@@ -57,7 +66,7 @@
|
||||
%{mcpu=sparclite|mcpu-f930|mcpu=f934:-D__sparclite__} \
|
||||
%{mcpu=v8:" DEF_ARCH32_SPEC("-D__sparcv8") "} \
|
||||
%{mcpu=supersparc:-D__supersparc__ " DEF_ARCH32_SPEC("-D__sparcv8") "} \
|
||||
-%{mcpu=v9|mcpu=ultrasparc|mcpu=ultrasparc3:" DEF_ARCH32_SPEC("-D__sparcv8") "} \
|
||||
+%{mcpu=v9|mcpu=ultrasparc|mcpu=ultrasparc3|mcpu=niagara:" DEF_ARCH32_SPEC("-D__sparcv8") "} \
|
||||
%{!mcpu*:%{!mcypress:%{!msparclite:%{!mf930:%{!mf934:%{!mv8:%{!msupersparc:%(cpp_cpu_default)}}}}}}} \
|
||||
"
|
||||
|
||||
@@ -66,7 +75,8 @@
|
||||
%{mcpu=v9:" DEF_ARCH32_SPEC("-xarch=v8plus") DEF_ARCH64_SPEC(AS_SPARC64_FLAG) "} \
|
||||
%{mcpu=ultrasparc:" DEF_ARCH32_SPEC("-xarch=v8plusa") DEF_ARCH64_SPEC(AS_SPARC64_FLAG "a") "} \
|
||||
%{mcpu=ultrasparc3:" DEF_ARCH32_SPEC("-xarch=v8plusb") DEF_ARCH64_SPEC(AS_SPARC64_FLAG "b") "} \
|
||||
-%{!mcpu=ultrasparc3:%{!mcpu=ultrasparc:%{!mcpu=v9:%{mcpu*:" DEF_ARCH32_SPEC("-xarch=v8") DEF_ARCH64_SPEC(AS_SPARC64_FLAG) "}}}} \
|
||||
+%{mcpu=niagara:" DEF_ARCH32_SPEC("-xarch=v8plusb") DEF_ARCH64_SPEC(AS_SPARC64_FLAG "b") "} \
|
||||
+%{!mcpu=niagara:%{!mcpu=ultrasparc3:%{!mcpu=ultrasparc:%{!mcpu=v9:%{mcpu*:" DEF_ARCH32_SPEC("-xarch=v8") DEF_ARCH64_SPEC(AS_SPARC64_FLAG) "}}}}} \
|
||||
%{!mcpu*:%(asm_cpu_default)} \
|
||||
"
|
||||
|
||||
--- gcc/config/sparc/sparc.h (revision 111647)
|
||||
+++ gcc/config/sparc/sparc.h (revision 111648)
|
||||
@@ -206,7 +206,7 @@ extern enum cmodel sparc_cmodel;
|
||||
which requires the following macro to be true if enabled. Prior to V9,
|
||||
there are no instructions to even talk about memory synchronization.
|
||||
Note that the UltraSPARC III processors don't implement RMO, unlike the
|
||||
- UltraSPARC II processors.
|
||||
+ UltraSPARC II processors. Niagara does not implement RMO either.
|
||||
|
||||
Default to false; for example, Solaris never enables RMO, only ever uses
|
||||
total memory ordering (TMO). */
|
||||
@@ -238,10 +238,12 @@ extern enum cmodel sparc_cmodel;
|
||||
#define TARGET_CPU_sparc64 7 /* alias */
|
||||
#define TARGET_CPU_ultrasparc 8
|
||||
#define TARGET_CPU_ultrasparc3 9
|
||||
+#define TARGET_CPU_niagara 10
|
||||
|
||||
#if TARGET_CPU_DEFAULT == TARGET_CPU_v9 \
|
||||
|| TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc \
|
||||
- || TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc3
|
||||
+ || TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc3 \
|
||||
+ || TARGET_CPU_DEFAULT == TARGET_CPU_niagara
|
||||
|
||||
#define CPP_CPU32_DEFAULT_SPEC ""
|
||||
#define ASM_CPU32_DEFAULT_SPEC ""
|
||||
@@ -262,6 +264,10 @@ extern enum cmodel sparc_cmodel;
|
||||
#define CPP_CPU64_DEFAULT_SPEC "-D__sparc_v9__"
|
||||
#define ASM_CPU64_DEFAULT_SPEC "-Av9b"
|
||||
#endif
|
||||
+#if TARGET_CPU_DEFAULT == TARGET_CPU_niagara
|
||||
+#define CPP_CPU64_DEFAULT_SPEC "-D__sparc_v9__"
|
||||
+#define ASM_CPU64_DEFAULT_SPEC "-Av9b"
|
||||
+#endif
|
||||
|
||||
#else
|
||||
|
||||
@@ -352,6 +358,7 @@ extern enum cmodel sparc_cmodel;
|
||||
%{mcpu=v9:-D__sparc_v9__} \
|
||||
%{mcpu=ultrasparc:-D__sparc_v9__} \
|
||||
%{mcpu=ultrasparc3:-D__sparc_v9__} \
|
||||
+%{mcpu=niagara:-D__sparc_v9__} \
|
||||
%{!mcpu*:%{!mcypress:%{!msparclite:%{!mf930:%{!mf934:%{!mv8:%{!msupersparc:%(cpp_cpu_default)}}}}}}} \
|
||||
"
|
||||
#define CPP_ARCH32_SPEC ""
|
||||
@@ -401,6 +408,7 @@ extern enum cmodel sparc_cmodel;
|
||||
%{mcpu=v9:-Av9} \
|
||||
%{mcpu=ultrasparc:%{!mv8plus:-Av9a}} \
|
||||
%{mcpu=ultrasparc3:%{!mv8plus:-Av9b}} \
|
||||
+%{mcpu=niagara:%{!mv8plus:-Av9b}} \
|
||||
%{!mcpu*:%{!mcypress:%{!msparclite:%{!mf930:%{!mf934:%{!mv8:%{!msupersparc:%(asm_cpu_default)}}}}}}} \
|
||||
"
|
||||
|
||||
@@ -524,7 +532,8 @@ enum processor_type {
|
||||
PROCESSOR_TSC701,
|
||||
PROCESSOR_V9,
|
||||
PROCESSOR_ULTRASPARC,
|
||||
- PROCESSOR_ULTRASPARC3
|
||||
+ PROCESSOR_ULTRASPARC3,
|
||||
+ PROCESSOR_NIAGARA
|
||||
};
|
||||
|
||||
/* This is set from -m{cpu,tune}=xxx. */
|
||||
@@ -2137,7 +2146,8 @@ do {
|
||||
|| (GENERAL_OR_I64 (CLASS1) && FP_REG_CLASS_P (CLASS2)) \
|
||||
|| (CLASS1) == FPCC_REGS || (CLASS2) == FPCC_REGS) \
|
||||
? ((sparc_cpu == PROCESSOR_ULTRASPARC \
|
||||
- || sparc_cpu == PROCESSOR_ULTRASPARC3) ? 12 : 6) : 2)
|
||||
+ || sparc_cpu == PROCESSOR_ULTRASPARC3 \
|
||||
+ || sparc_cpu == PROCESSOR_NIAGARA) ? 12 : 6) : 2)
|
||||
|
||||
/* Provide the cost of a branch. For pre-v9 processors we use
|
||||
a value of 3 to take into account the potential annulling of
|
||||
@@ -2147,22 +2157,30 @@ do {
|
||||
|
||||
On v9 and later, which have branch prediction facilities, we set
|
||||
it to the depth of the pipeline as that is the cost of a
|
||||
- mispredicted branch. */
|
||||
+ mispredicted branch.
|
||||
+
|
||||
+ On Niagara, normal branches insert 3 bubbles into the pipe
|
||||
+ and annulled branches insert 4 bubbles. */
|
||||
|
||||
#define BRANCH_COST \
|
||||
((sparc_cpu == PROCESSOR_V9 \
|
||||
|| sparc_cpu == PROCESSOR_ULTRASPARC) \
|
||||
? 7 \
|
||||
: (sparc_cpu == PROCESSOR_ULTRASPARC3 \
|
||||
- ? 9 : 3))
|
||||
+ ? 9 \
|
||||
+ : (sparc_cpu == PROCESSOR_NIAGARA \
|
||||
+ ? 4 \
|
||||
+ : 3)))
|
||||
|
||||
#define PREFETCH_BLOCK \
|
||||
((sparc_cpu == PROCESSOR_ULTRASPARC \
|
||||
- || sparc_cpu == PROCESSOR_ULTRASPARC3) \
|
||||
+ || sparc_cpu == PROCESSOR_ULTRASPARC3 \
|
||||
+ || sparc_cpu == PROCESSOR_NIAGARA) \
|
||||
? 64 : 32)
|
||||
|
||||
#define SIMULTANEOUS_PREFETCHES \
|
||||
- ((sparc_cpu == PROCESSOR_ULTRASPARC) \
|
||||
+ ((sparc_cpu == PROCESSOR_ULTRASPARC \
|
||||
+ || sparc_cpu == PROCESSOR_NIAGARA) \
|
||||
? 2 \
|
||||
: (sparc_cpu == PROCESSOR_ULTRASPARC3 \
|
||||
? 8 : 3))
|
||||
--- gcc/config/sparc/linux64.h (revision 111647)
|
||||
+++ gcc/config/sparc/linux64.h (revision 111648)
|
||||
@@ -43,7 +43,8 @@ Boston, MA 02110-1301, USA. */
|
||||
|
||||
#if TARGET_CPU_DEFAULT == TARGET_CPU_v9 \
|
||||
|| TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc \
|
||||
- || TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc3
|
||||
+ || TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc3 \
|
||||
+ || TARGET_CPU_DEFAULT == TARGET_CPU_niagara
|
||||
/* A 64 bit v9 compiler with stack-bias,
|
||||
in a Medium/Low code model environment. */
|
||||
|
||||
--- gcc/config/sparc/sol2.h (revision 111647)
|
||||
+++ gcc/config/sparc/sol2.h (revision 111648)
|
||||
@@ -41,11 +41,17 @@ Boston, MA 02110-1301, USA. */
|
||||
#define ASM_CPU_DEFAULT_SPEC "-xarch=v8plusb"
|
||||
#endif
|
||||
|
||||
+#if TARGET_CPU_DEFAULT == TARGET_CPU_niagara
|
||||
+#undef ASM_CPU_DEFAULT_SPEC
|
||||
+#define ASM_CPU_DEFAULT_SPEC "-xarch=v8plusb"
|
||||
+#endif
|
||||
+
|
||||
#undef ASM_CPU_SPEC
|
||||
#define ASM_CPU_SPEC "\
|
||||
%{mcpu=v9:-xarch=v8plus} \
|
||||
%{mcpu=ultrasparc:-xarch=v8plusa} \
|
||||
%{mcpu=ultrasparc3:-xarch=v8plusb} \
|
||||
+%{mcpu=niagara:-xarch=v8plusb} \
|
||||
%{!mcpu*:%(asm_cpu_default)} \
|
||||
"
|
||||
|
65
gcc41.spec
65
gcc41.spec
@ -1,6 +1,6 @@
|
||||
%define DATE 20070821
|
||||
%define DATE 20070925
|
||||
%define gcc_version 4.1.2
|
||||
%define gcc_release 26
|
||||
%define gcc_release 28
|
||||
%define _unpackaged_files_terminate_build 0
|
||||
%define multilib_64_archs sparc64 ppc64 s390x x86_64
|
||||
%define include_gappletviewer 1
|
||||
@ -138,24 +138,13 @@ Patch21: gcc41-rh235008.patch
|
||||
Patch22: gcc41-build-id.patch
|
||||
Patch23: gcc41-pr28690.patch
|
||||
Patch24: gcc41-rh247256.patch
|
||||
Patch25: gcc41-pr22244.patch
|
||||
Patch26: gcc41-pr32678.patch
|
||||
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
|
||||
Patch34: gcc41-builtin-chk-anticipated.patch
|
||||
Patch35: gcc41-builtin-throw.patch
|
||||
Patch36: gcc41-builtin-va-arg-pack.patch
|
||||
Patch37: gcc41-builtin-va-arg-pack-len.patch
|
||||
Patch38: gcc41-pr27954.patch
|
||||
Patch39: gcc41-pr33423.patch
|
||||
Patch40: gcc41-scanf-fmt-check.patch
|
||||
Patch41: gcc41-pr33506.patch
|
||||
Patch42: gcc41-makeinfo-ver.patch
|
||||
Patch25: gcc41-ppc64-ia64-GNU-stack.patch
|
||||
Patch26: gcc41-pr33506.patch
|
||||
Patch27: gcc41-artificial-attrib.patch
|
||||
Patch28: gcc41-error-attrib.patch
|
||||
Patch29: gcc41-jdwp.patch
|
||||
Patch30: gcc41-pr20880.patch
|
||||
Patch31: gcc41-pr32694.patch
|
||||
|
||||
# On ARM EABI systems, we do want -gnueabi to be part of the
|
||||
# target triple.
|
||||
@ -463,24 +452,13 @@ which are required to run programs compiled with the GNAT.
|
||||
%patch22 -p0 -b .build-id~
|
||||
%patch23 -p0 -b .pr28690~
|
||||
%patch24 -p0 -b .rh247256~
|
||||
%patch25 -p0 -b .pr22244~
|
||||
%patch26 -p0 -b .pr32678~
|
||||
%patch27 -p0 -b .pr32912~
|
||||
%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~
|
||||
%patch34 -p0 -b .builtin-chk-anticipated~
|
||||
%patch35 -p0 -b .builtin-throw~
|
||||
%patch36 -p0 -b .builtin-va-arg-pack~
|
||||
%patch37 -p0 -b .builtin-va-arg-pack-len~
|
||||
%patch38 -p0 -b .pr27954~
|
||||
%patch39 -p0 -b .pr33423~
|
||||
%patch40 -p0 -b .scanf-fmt-check~
|
||||
%patch41 -p0 -b .pr33506~
|
||||
%patch42 -p0 -b .makeinfo-ver~
|
||||
%patch25 -p0 -b .ppc64-ia64-GNU-stack~
|
||||
%patch26 -p0 -b .pr33506~
|
||||
%patch27 -p0 -b .artificial-attrib~
|
||||
%patch28 -p0 -b .error-attrib~
|
||||
%patch29 -p0 -b .jdwp~
|
||||
%patch30 -p0 -b .pr20880~
|
||||
%patch31 -p0 -b .pr32694~
|
||||
|
||||
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
|
||||
@ -1635,6 +1613,17 @@ fi
|
||||
%doc rpm.doc/changelogs/libmudflap/ChangeLog*
|
||||
|
||||
%changelog
|
||||
* Tue Sep 25 2007 Jakub Jelinek <jakub@redhat.com> 4.1.2-28
|
||||
- update from gcc-4_1-branch (-r127672:128736)
|
||||
- PRs bootstrap/33418, c++/31941, c++/32113, java/31842, target/33256,
|
||||
tree-optimization/33142
|
||||
- add support for artificial, error and warning attributes
|
||||
- restore Java CNI ABI compatibility broken by JDWP changes (Keith Seitz)
|
||||
- fix ICE with set_rhs allowing non-gimple (Roger Sayle, #247407,
|
||||
PR tree-optimization/32694)
|
||||
- fix ICE on Fortran interface-body declaring current subroutine name
|
||||
(Paul Thomas, #300851, PR fortran/20880)
|
||||
|
||||
* Sat Sep 22 2007 Jakub Jelinek <jakub@redhat.com> 4.1.2-26
|
||||
- don't ignore throw specification of function types in type hashing
|
||||
(PR c++/33506)
|
||||
|
Loading…
Reference in New Issue
Block a user