- To: gcc-bugs at gcc dot gnu dot org, Jose Angel Sanchez Caso <jasanchez at polar dot es>
- Subject: This little "one file program" puts gcc 2.95.2 into an infinite loop.
- From: Jose Angel Sanchez Caso <jasanchez at polar dot es>
- Date: Thu, 02 Nov 2000 10:37:02 +0100
VERSION:
gcc -v
Reading specs from /usr/local/lib/gcc-lib/i686-pc-linux-gnu/2.95.2/specs
gcc version 2.95.2 19991024 (release)
---------------------------------------------------------
COMMAND LINE THAT TRIGGERS THE BUG:
gcc dlist.cc
dlist.cc:203: semicolon missing after declaration of `troncoIterator'
dlist.cc:204: semicolon missing after declaration of `ramaIterator'
At this point gcc "freeezes"
----------------------------------------------------------
MESSAGES: See above.
----------------------------------------------------------
OPTIONS CONFIGURE-BUILT:
Default.
----------------------------------------------------------
The test program is very simple. Good luck.
#include <stdlib.h>
#include <stdio.h>
typedef struct treeListRec
{ struct treeListRec * up;
struct treeListRec * nxt;
} simpleListRec;
/* -------------------------------------------------------------------------- */
void * simpleListSeed( void * itemArg )
{ treeListRec * item=
(treeListRec *) itemArg;
return(NULL); }
/* -------------------------------------------------------------------------- */
simpleListRec * simpleListNew( size_t size )
{ simpleListRec * newItem=
(simpleListRec *) calloc(1,size);
return(newItem); }
/* -------------------------------------------------------------------------- */
void * simpleListPush( void * upVar, size_t size )
{ treeListRec * up= (treeListRec *)upVar; /* Elemento padre */
treeListRec * item;
if (!upVar)
{ return(NULL); } /* No hay padre */
item= simpleListNew( size + sizeof(treeListRec ));
item->up= up;
item->nxt= up->nxt;
up->nxt= item;
return(item+1);} /* Retorna puntero a datos v lidos */
/* -------------------------------------------------------------------------- */
void * simpleListDetach( void * itemVar )
{ treeListRec * item;
treeListRec * iter;
if (!itemVar)
{ return(NULL); } /* No hay padre ni elemento a eliminar */
item= (treeListRec *)itemVar;
iter= item->up;
while( iter->nxt != item )
{ iter= iter->nxt;
if (!iter) /* Error, no lo encontr¢ en la lista */
{ return(NULL); }}
iter->nxt= item->nxt; /* Desenganche efectivo */
free( item ); /* Liberar recursos */
return( iter ); } /* Retornar el padre */
template <class tipo>
struct list: public simpleListRec
{ list () { up= NULL; nxt= NULL; }
struct iterator
{ list * ptr;
public:
iterator( list * l ) { ptr= l; }
iterator( void ) { ptr= NULL; }
inline void rewind( list & l ) { ptr= &l; next(); }
inline tipo * getData() { return((tipo *)(ptr+1));}
inline void * detach () { getData()->~tipo(); return(simpleListDetach(ptr)); }
inline tipo & attach( ) { return(*(tipo *)simpleListPush( ptr->up, sizeof(tipo))); }
inline tipo & attach(tipo & w) { tipo & tmp= attach(); tmp= w; return(tmp); }
inline tipo & attach(tipo * w) { tipo & tmp= attach(); tmp= *w; ::free(w); return(tmp); }
inline list * next ( ) { ptr= ptr->next(); return( ptr ); }
inline bool empty ( ) { return(ptr==NULL); }
inline bool full ( ) { return(ptr!=NULL); }
inline operator bool ( ) { return(full()) ; }
inline list * operator ++ (int ) { return(next()) ; }
inline tipo * operator -> ( ) { return(getData()); } /* Saltarse la zona de links */
inline void operator * ( ) { return(getData()); } /* Saltarse la zona de links */
inline tipo & operator += (tipo & w) { return(attach(w)); }
inline tipo & operator += (tipo * w) { return(attach(w)); }
};
inline iterator self ( ) { return(iterator( this )); }
inline list * next ( ) { return( ((list *)nxt )); }
inline iterator first ( ) { return(iterator((list *)nxt )); }
inline operator iterator ( ) { return(first()); }
inline operator bool ( ) { return(nxt) ; }
inline tipo * attach( ) { return((tipo *)simpleListPush( this, sizeof(tipo))); }
inline tipo * attach(tipo & w) { tipo * tmp= attach(); *tmp= w; return(tmp); }
inline tipo * attach(tipo * w) { tipo * tmp= attach(); *tmp= *w; ::free(w); return(tmp); }
inline tipo * operator += ( tipo & w ) { return(attach(w)); }
inline tipo * operator += ( tipo * w ) { return(attach(w)); }
inline void detach() /* Elimina los elementos de la lista */
{ while( nxt )
{ simpleListRec * tmp= nxt+1;
((tipo *) tmp)->~tipo(); /* Ejecutar destructor */
simpleListDetach(nxt); }}
inline ~list() { detach(); }
};
/* -------------------------------------------------------------------------- */
struct origenRec;
struct troncoRec;
struct ramaRec;
struct hojaRec {
ramaRec * padre;
hojaRec(int i=0) { hld= i;}
~hojaRec() { printf( "destruyendo hoja %d\n", hld ); }
int hld ; };
struct ramaRec {
troncoRec * padre;
list< hojaRec > hojas;
ramaRec(int i=0) { hld= i;}
~ramaRec() { printf( "destruyendo rama %d\n", hld ); }
int hld ; };
struct troncoRec {
origenRec * padre;
list< ramaRec > ramas;
troncoRec(int i=0) { hld= i; }
~troncoRec() { printf( "destruyendo tronco %d\n", hld ); }
int hld ; };
struct origenRec {
void * padre;
list< troncoRec > troncos;
int hld ;
origenRec(int i=0) { hld= i;}
~origenRec() { printf( "destruyendo origen %d\n", hld ); }
};
struct c { int a; };
typedef list< origenRec > lorgRec;
typedef list< origenRec >::iterator origenIterator; /* Extensi¢n a iterador sobre generales */
#define ITERATOR(nombre,previo,actual,campo,origen) \
struct nombre: actual \
{ previo prevIterator; \
\
nombre( ) { } \
nombre( list < origen > & org ) \
{ printf("creando %s\n", #nombre ); \
\
for( prevIterator= org \
; prevIterator \
; prevIterator ++ ) \
{ if (prevIterator->campo) \
{ rewind( prevIterator->campo ); \
break; }}} \
\
\
inline void operator ++ (int) \
{ for( next () \
; empty() \
; rewind( prevIterator->campo ) ) \
{ prevIterator++; \
if (!prevIterator) \
{ return; }}} \
} \
ITERATOR( troncoIterator, origenIterator, list< troncoRec >::iterator, troncos, origenRec )
ITERATOR( ramaIterator, troncoIterator, list< ramaRec >::iterator, ramas, origenRec )
ITERATOR( hojaIterator, ramaIterator, list< hojaRec >::iterator, hojas, origenRec )
#define FOREACH( base, tipo, name ) for ( list< tipo >::iterator name= base.first(); name; name++ )
main()
{ lorgRec lorg;
lorgRec::iterator iter;
list< troncoRec >::iterator it;
lorg.attach()->hld= 2;
lorg.attach()->hld= 4;
lorg += new origenRec( 100 );
origenRec * elem= lorg += new origenRec( 101 );
lorg += new origenRec( 102 );
lorg += new origenRec( 103 );
elem->troncos+= new troncoRec( 1001 );
elem->troncos+= new troncoRec( 1002 );
elem->troncos+= new troncoRec( 1003 );
troncoRec * trc= elem->troncos+= new troncoRec( 1004 );
trc->ramas+= new ramaRec ( 200001 );
trc->ramas+= new ramaRec ( 200002 );
trc->ramas+= new ramaRec ( 200003 );
trc->ramas+= new ramaRec ( 200004 );
ramaRec * ram= trc->ramas+= new ramaRec ( 200005 );
trc= elem->troncos+= new troncoRec( 1005 );
trc->ramas+= new ramaRec ( 300001 );
trc->ramas+= new ramaRec ( 300002 );
trc->ramas+= new ramaRec ( 300003 );
trc->ramas+= new ramaRec ( 300004 );
ram->hojas+= new hojaRec (7000001 );
ram->hojas+= new hojaRec (7000002 );
ram->hojas+= new hojaRec (7000003 );
ram->hojas+= new hojaRec (7000004 );
ram->hojas+= new hojaRec (7000005 );
ram= trc->ramas+= new ramaRec ( 200005 );
ram->hojas+= new hojaRec (8000001 );
ram->hojas+= new hojaRec (8000002 );
ram->hojas+= new hojaRec (8000003 );
ram->hojas+= new hojaRec (8000004 );
ram->hojas+= new hojaRec (8000005 );
FOREACH( elem->troncos, troncoRec, it )
{ printf("Contenido %d %d\n", elem->hld, it->hld ); }
hojaIterator itert( lorg );
while( itert )
{ printf( "iterando hojas %d\n"
, itert->hld );
itert ++ ;
}
puts("vaciando tronco");
elem->troncos.detach();
puts("tronco vaciado ");
}