/* { dg-do run } */ /* { dg-options "-Os" } */ /* Based on gethostbyname_r, * Copyright (C) 2000-2006 Erik Andersen * * Licensed under the LGPL v2.1, see the file COPYING.LIB * * Extraction / wrapping as test by * Joern Rennecke * Copyright (C) 2013 Free Software Foundation, Inc. */ typedef unsigned size_t; typedef int ssize_t; typedef unsigned uint32_t; struct resolv_answer { char *dotted; int atype; int aclass; int ttl; int rdlength; const unsigned char *rdata; int rdoffset; char* buf; size_t buflen; size_t add_count; }; struct hostent { char *h_name; char **h_aliases; int h_addrtype; int h_length; char **h_addr_list; }; int *__attribute__ ((noinline,weak)) nop (void * p) { return p; }; void __attribute__ ((noinline,weak)) seta (struct resolv_answer * p) { p->atype = 1;} int ghostbyname_r( struct hostent *result_buf, char *buf, size_t buflen, struct hostent **result, int *h_errnop) { char **addr_list; char **alias; char *alias0; int i0; struct resolv_answer a; int i; *result = ((void *)0); *h_errnop = -1; if ((ssize_t)buflen <= 5) return 34; alias = (char **)buf; addr_list = (char **)buf; /* This got turned into branch with conditional move in delay slot. */ if ((ssize_t)buflen < 256) return 34; { if (!nop(&i0)) { result_buf->h_aliases = alias; result_buf->h_addrtype = 2; result_buf->h_length = 4; result_buf->h_addr_list = addr_list; *result = result_buf; *h_errnop = 0; return 0; } } seta (&a); if (a.atype == 1) { int need_bytes = sizeof(addr_list[0]) * (a.add_count + 1 + 1); int ips_len = a.add_count * a.rdlength; buflen -= (need_bytes + ips_len); if ((ssize_t)buflen < 0) { i = 34; goto free_and_ret; } result_buf->h_addrtype = 2; *result = result_buf; *h_errnop = 0; i = 0; goto free_and_ret; } /* For cse, the 1 was is loaded into a call-saved register; the load was hoisted into a delay slot before the conditional load, clobbering result_buf, which (conditionally) lived in the same call-saved register, because mark_referenced_resources considered the destination of the COND_EXEC only clobbered, but not used. */ *h_errnop = 1; *nop(&i0) = 1; i = 2; free_and_ret: nop (&i0); return i; } int main () { struct hostent buf, *res; int i; char c; ghostbyname_r (&buf, &c, 1024, &res, &i); ghostbyname_r (&buf, 0, 1024, &res, &i); return 0; }