diff options
-rw-r--r-- | gcc/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/compile/limits-externdecl.c | 55 | ||||
-rw-r--r-- | gcc/varasm.c | 11 |
4 files changed, 81 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 40405d5..a513fa9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2012-12-12 Steven Bosscher <steven@gcc.gnu.org> + Jakub Jelinek <jakub@redhat.com> + + PR middle-end/52640 + * varasm.c (pending_assemble_externals_set): New pointer set. + (process_pending_assemble_externals): Destroy the pointer set. + (assemble_external): See if decl is in pending_assemble_externals_set, + and add it to pending_assemble_externals if necessary. + (init_varasm_once): Allocate pending_assemble_externals_set. + 2012-12-12 Jakub Jelinek <jakub@redhat.com> PR fortran/55633 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3916a85..f9a68a5 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2012-12-12 Steven Bosscher <steven@gcc.gnu.org> + Jakub Jelinek <jakub@redhat.com> + + PR middle-end/52640 + * gcc.c-torture/compile/limits-externdecl.c: New test. + 2012-12-12 Jakub Jelinek <jakub@redhat.com> * gfortran.dg/vect/fast-math-pr38968.f90: Decrease n diff --git a/gcc/testsuite/gcc.c-torture/compile/limits-externdecl.c b/gcc/testsuite/gcc.c-torture/compile/limits-externdecl.c new file mode 100644 index 0000000..070db97 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/limits-externdecl.c @@ -0,0 +1,55 @@ +/* Inspired by the test case for PR middle-end/52640. */ + +typedef struct +{ + char *value; +} REFERENCE; + +/* Add a few "extern int Xxxxxx ();" declarations. */ +#undef DEF +#undef LIM1 +#undef LIM2 +#undef LIM3 +#undef LIM4 +#undef LIM5 +#undef LIM6 +#define DEF(x) extern int x () +#define LIM1(x) DEF(x##0); DEF(x##1); DEF(x##2); DEF(x##3); DEF(x##4); \ + DEF(x##5); DEF(x##6); DEF(x##7); DEF(x##8); DEF(x##9); +#define LIM2(x) LIM1(x##0) LIM1(x##1) LIM1(x##2) LIM1(x##3) LIM1(x##4) \ + LIM1(x##5) LIM1(x##6) LIM1(x##7) LIM1(x##8) LIM1(x##9) +#define LIM3(x) LIM2(x##0) LIM2(x##1) LIM2(x##2) LIM2(x##3) LIM2(x##4) \ + LIM2(x##5) LIM2(x##6) LIM2(x##7) LIM2(x##8) LIM2(x##9) +#define LIM4(x) LIM3(x##0) LIM3(x##1) LIM3(x##2) LIM3(x##3) LIM3(x##4) \ + LIM3(x##5) LIM3(x##6) LIM3(x##7) LIM3(x##8) LIM3(x##9) +#define LIM5(x) LIM4(x##0) LIM4(x##1) LIM4(x##2) LIM4(x##3) LIM4(x##4) \ + LIM4(x##5) LIM4(x##6) LIM4(x##7) LIM4(x##8) LIM4(x##9) +#define LIM6(x) LIM5(x##0) LIM5(x##1) LIM5(x##2) LIM5(x##3) LIM5(x##4) \ + LIM5(x##5) LIM5(x##6) LIM5(x##7) LIM5(x##8) LIM5(x##9) +LIM5 (X); + +/* Add references to them, or GCC will simply ignore the extern decls. */ +#undef DEF +#undef LIM1 +#undef LIM2 +#undef LIM3 +#undef LIM4 +#undef LIM5 +#undef LIM6 +#define DEF(x) (char *) x +#define LIM1(x) DEF(x##0), DEF(x##1), DEF(x##2), DEF(x##3), DEF(x##4), \ + DEF(x##5), DEF(x##6), DEF(x##7), DEF(x##8), DEF(x##9), +#define LIM2(x) LIM1(x##0) LIM1(x##1) LIM1(x##2) LIM1(x##3) LIM1(x##4) \ + LIM1(x##5) LIM1(x##6) LIM1(x##7) LIM1(x##8) LIM1(x##9) +#define LIM3(x) LIM2(x##0) LIM2(x##1) LIM2(x##2) LIM2(x##3) LIM2(x##4) \ + LIM2(x##5) LIM2(x##6) LIM2(x##7) LIM2(x##8) LIM2(x##9) +#define LIM4(x) LIM3(x##0) LIM3(x##1) LIM3(x##2) LIM3(x##3) LIM3(x##4) \ + LIM3(x##5) LIM3(x##6) LIM3(x##7) LIM3(x##8) LIM3(x##9) +#define LIM5(x) LIM4(x##0) LIM4(x##1) LIM4(x##2) LIM4(x##3) LIM4(x##4) \ + LIM4(x##5) LIM4(x##6) LIM4(x##7) LIM4(x##8) LIM4(x##9) +#define LIM6(x) LIM5(x##0) LIM5(x##1) LIM5(x##2) LIM5(x##3) LIM5(x##4) \ + LIM5(x##5) LIM5(x##6) LIM5(x##7) LIM5(x##8) LIM5(x##9) +REFERENCE references[] = { + LIM5 (X) + 0 +}; diff --git a/gcc/varasm.c b/gcc/varasm.c index b6170e6..bca852d 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -2089,6 +2089,10 @@ contains_pointers_p (tree type) static GTY(()) tree pending_assemble_externals; #ifdef ASM_OUTPUT_EXTERNAL +/* Avoid O(external_decls**2) lookups in the pending_assemble_externals + TREE_LIST in assemble_external. */ +static struct pointer_set_t *pending_assemble_externals_set; + /* True if DECL is a function decl for which no out-of-line copy exists. It is assumed that DECL's assembler name has been set. */ @@ -2140,6 +2144,7 @@ process_pending_assemble_externals (void) assemble_external_real (TREE_VALUE (list)); pending_assemble_externals = 0; + pointer_set_destroy (pending_assemble_externals_set); #endif } @@ -2191,7 +2196,7 @@ assemble_external (tree decl ATTRIBUTE_UNUSED) weak_decls = tree_cons (NULL, decl, weak_decls); #ifdef ASM_OUTPUT_EXTERNAL - if (value_member (decl, pending_assemble_externals) == NULL_TREE) + if (! pointer_set_insert (pending_assemble_externals_set, decl)) pending_assemble_externals = tree_cons (NULL, decl, pending_assemble_externals); #endif @@ -5904,6 +5909,10 @@ init_varasm_once (void) if (readonly_data_section == NULL) readonly_data_section = text_section; + +#ifdef ASM_OUTPUT_EXTERNAL + pending_assemble_externals_set = pointer_set_create (); +#endif } enum tls_model |