1 /* This testcase derives from gnu obstack.c/obstack.h and failed with
2    -O3 -funroll-all-loops, or -O1 -frename-registers -funroll-loops on
3    sparc-sun-solaris2.7.
4 
5    Copyright (C) 2001  Free Software Foundation.  */
6 
7 /* { dg-require-effective-target indirect_calls } */
8 
9 # define PTR_INT_TYPE __PTRDIFF_TYPE__
10 
11 struct _obstack_chunk
12 {
13   char  *limit;
14   struct _obstack_chunk *prev;
15   char	contents[4];
16 };
17 
18 struct obstack
19 {
20   long	chunk_size;
21   struct _obstack_chunk *chunk;
22   char	*object_base;
23   char	*next_free;
24   char	*chunk_limit;
25   PTR_INT_TYPE temp;
26   int   alignment_mask;
27   struct _obstack_chunk *(*chunkfun) (void *, long);
28   void (*freefun) (void *, struct _obstack_chunk *);
29   void *extra_arg;
30   unsigned use_extra_arg:1;
31   unsigned maybe_empty_object:1;
32   unsigned alloc_failed:1;
33 };
34 
35 extern void _obstack_newchunk (struct obstack *, int);
36 
37 struct fooalign {char x; double d;};
38 #define DEFAULT_ALIGNMENT  \
39   ((PTR_INT_TYPE) ((char *) &((struct fooalign *) 0)->d - (char *) 0))
40 union fooround {long x; double d;};
41 #define DEFAULT_ROUNDING (sizeof (union fooround))
42 
43 #ifndef COPYING_UNIT
44 #define COPYING_UNIT int
45 #endif
46 
47 #define CALL_CHUNKFUN(h, size) \
48   (((h) -> use_extra_arg) \
49    ? (*(h)->chunkfun) ((h)->extra_arg, (size)) \
50    : (*(struct _obstack_chunk *(*) (long)) (h)->chunkfun) ((size)))
51 
52 #define CALL_FREEFUN(h, old_chunk) \
53   do { \
54     if ((h) -> use_extra_arg) \
55       (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \
56     else \
57       (*(void (*) (void *)) (h)->freefun) ((old_chunk)); \
58   } while (0)
59 
60 void
_obstack_newchunk(h,length)61 _obstack_newchunk (h, length)
62      struct obstack *h;
63      int length;
64 {
65   register struct _obstack_chunk *old_chunk = h->chunk;
66   register struct _obstack_chunk *new_chunk;
67   register long	new_size;
68   register long obj_size = h->next_free - h->object_base;
69   register long i;
70   long already;
71 
72   new_size = (obj_size + length) + (obj_size >> 3) + 100;
73   if (new_size < h->chunk_size)
74     new_size = h->chunk_size;
75 
76   new_chunk = CALL_CHUNKFUN (h, new_size);
77   h->chunk = new_chunk;
78   new_chunk->prev = old_chunk;
79   new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size;
80 
81   if (h->alignment_mask + 1 >= DEFAULT_ALIGNMENT)
82     {
83       for (i = obj_size / sizeof (COPYING_UNIT) - 1;
84 	   i >= 0; i--)
85 	((COPYING_UNIT *)new_chunk->contents)[i]
86 	  = ((COPYING_UNIT *)h->object_base)[i];
87       already = obj_size / sizeof (COPYING_UNIT) * sizeof (COPYING_UNIT);
88     }
89   else
90     already = 0;
91   for (i = already; i < obj_size; i++)
92     new_chunk->contents[i] = h->object_base[i];
93 
94   if (h->object_base == old_chunk->contents && ! h->maybe_empty_object)
95     {
96       new_chunk->prev = old_chunk->prev;
97       CALL_FREEFUN (h, old_chunk);
98     }
99 
100   h->object_base = new_chunk->contents;
101   h->next_free = h->object_base + obj_size;
102   h->maybe_empty_object = 0;
103 }
104