From: mcgrant@isl.stanford.edu (Michael C. Grant)
Subject: bug in template instantiation
Organization: GNUs Not Usenet
Distribution: gnu
Date: Thu, 5 Nov 1992 03:40:24 GMT

Sorry, the previous version of this bug report was slightly incorrect.

Version:
Reading specs from /usr/local/lib/gcc-lib/sparc/2.3.1/specs
gcc version 2.3.1
on a Sun sparc workstation

Bug in template instantiation: I have a 

template < class T, enum Types Tcode, const char* Name >

and g++ belches on Name, on the line
typedef qdesBase<long,Int,"integer scalar"> intScalar;
saying

cd /u2/mcgrant/src/qdes/ver2/
g++ -DNOINLINE -c bug1.C
qdesVar.C:42: invalid pointer constant for template parameter
 <pointer_type 195b60
    type <integer_type 195b08 char readonly permanent QI
        size <integer_cst 1932a8 constant permanent 8>
        align 8 symtab 0 precision 8
        min <integer_cst 193278 constant permanent -128>
        max <integer_cst 193290 constant permanent 127>
        pointer_to_this <pointer_type 195b60>>
    unsigned permanent SI
    size <integer_cst 1931b0 type <integer_type 193128 int> constant permanent 32>
    align 32 symtab 0
    pointer_to_this <pointer_type 1ab6b8>>
 <nop_expr 1c37a8
    type <pointer_type 195ab0
        type <integer_type 193220 char permanent QI
            size <integer_cst 1932a8 constant permanent 8>
            align 8 symtab 0 precision 8
            min <integer_cst 193278 constant permanent -128>
            max <integer_cst 193290 constant permanent 127>
            pointer_to_this <pointer_type 195ab0>>
        unsigned permanent SI
        size <integer_cst 1931b0 constant permanent 32>
        align 32 symtab 0>
    constant permanent
    arg 0 <addr_expr 1c3790
        type <pointer_type 1c3738 type <array_type 1c3668>
            unsigned permanent SI size <integer_cst 1931b0 32>
            align 32 symtab 0>
        constant permanent
        arg 0 <string_cst 1c35a8 type <array_type 1c3668>
            constant permanent static "integer scalar">>>
qdesVar.H:24: please fix above error, and try recompiling.

Compilation exited abnormally with code 1 at Wed Nov  4 19:37:49


If I substitute '"integer scalar"' with name1 and precede it with
static const char* name1 = "integer scalar", I still get

cd /u2/mcgrant/src/qdes/ver2/
g++ -DNOINLINE -c qdesVar.C
qdesVar.C:44: invalid pointer constant for template parameter
/usr/local/bin/gcc: Internal compiler error: program cc1plus got fatal signal 11

Compilation exited abnormally with code 1 at Wed Nov  4 19:27:54

g++ -E -DNOINLINE qdesVar.C >! bug1.C

# 1 "qdesVar.C"
# 1 "qdesVar.H" 1


#pragma interface



# 1 "Variable.H" 1


#pragma inteface



class VarRep;
class VarCover;
class ostream;

enum Types { Typeless = 0, Int, Real, Cplx, String, RealPoly, CplxPoly, 
             RealRational, CplxRational, IntMatrix, IntRegVect,
             RealMatrix, CplxMatrix, StringMatrix, RealRegVect, CplxRegVect,
             RealPolyMatrix, CplxPolyMatrix, RealRationalMatrix,
             CplxRationalMatrix, TransferFunction, DynamicSystem, numTypes };

class varException {
    const char** strlist;
    int numstr;
    int active;
public:
    varException( void );
    varException( const char*, ... );
    operator int ( void ) const;
    friend ostream& operator << ( ostream&, varException& );
    void reset( void );
};

class VarRep {
public:
    VarRep( Types ntype );
    VarRep( const VarRep& p );
    virtual ~VarRep( void ) {}

    VarRep* ref( void );
    void    deref( void );
    int     shared( void ) const;
    virtual VarRep* clone( void ) const = 0;

    Types type( void ) const;
    virtual const char* typeName( void ) const = 0;
    virtual void output( ostream& ) const = 0;
    friend ostream& operator << ( ostream&, const VarRep& );
private:
    int refs;
    Types _type;
};

typedef VarRep* (*unaryOp)(const VarRep&);
struct unaryStruct {
    Types type;
    unaryOp fptr;
};

class unaryVtable {
    friend class unaryRegister;
    unaryOp funcs[numTypes];
protected:
    const char* name;
public:
    unaryVtable( const char* );
    VarRep* operator()( const VarRep* ) const;
    virtual VarRep* error( const VarRep* ) const = 0;
};

class unaryOperator : public unaryVtable {
public:
    unaryOperator( const char* );
    VarRep* error( const VarRep* ) const;
};

class unaryMethod : public unaryVtable {
    static VarRep* error( const VarRep& );
public:
    unaryMethod( const char* );
    VarRep* error( const VarRep* ) const;
};

class unaryRegister {
public:
    unaryRegister( unaryVtable&, const unaryStruct* );
};

typedef VarRep* (*binaryOp)(const VarRep&,const VarRep&);
struct binaryStruct {
    Types type1,type2;
    binaryOp fptr;
};

class binaryVtable {
    friend class binaryRegister;
    binaryOp funcs[numTypes][numTypes];
protected:
    const char* name;
public:
    binaryVtable( const char* );
    VarRep* operator()( const VarRep*, const VarRep* ) const;
    virtual VarRep* error( const VarRep*, const VarRep* ) const = 0;
};

class binaryRegister {
public:
    binaryRegister( binaryVtable&, const binaryStruct* );
};

class binaryOperator : public binaryVtable {
public:
    binaryOperator( const char* );
    VarRep* error( const VarRep*, const VarRep* ) const;
};

class binaryMethod : public binaryVtable {
public:
    binaryMethod( const char* );
    VarRep* error( const VarRep*, const VarRep* ) const;
};

class Variable {
public:
    static binaryOperator add, sub, mul, ldv, rdv, pow;
    static unaryOperator  neg;
    static unaryMethod    sqrt;
    static varException   exception;
};







# 7 "qdesVar.H" 2


template <class T,Types Tcode,const char* Name>
class qdesVar : public VarRep, public T {
public:
    qdesVar( const T& p ) : VarRep( Tcode ), T( p );
    qdesVar( const qdesVar& p ) : VarRep( Tcode ), T( p );
    
    VarRep* clone( void ) const;
    const char* typeName( void ) const;
    void output( ostream& ) const;
};

template <class T,Types Tcode, const char* Name>
class qdesBase : public VarRep {
    T data;
public:
    qdesBase( const T& p );
    qdesBase( const qdesBase& p );
    operator T& ( void );
    operator const T& ( void );

    VarRep* clone( void ) const;
    const char* typeName( void ) const;
    void output( ostream& cout ) const;
};






# 1 "qdesVar.C" 2

# 1 "RegVect.H" 1


#pragma interface



template <class T>
class RegVect {
    T start, finish, space;
    long len, len1;
public:
    RegVect( const T&, const T&, const T& );
    RegVect( const T&, const T&, long = -1 );

    T operator[]( int ndx );
    RegVect operator[]( int ndx1, int ndx2 );

    RegVect  operator+( const RegVect& ) const;
    RegVect& operator+=( const RegVect& );
    RegVect  operator+( const T& ) const;
    RegVect& operator+=( const T& );
    friend RegVect operator+( const T&, const RegVect& );

    RegVect  operator-( const RegVect& ) const;
    RegVect& operator-=( const RegVect& );
    RegVect  operator-( const T& ) const;
    RegVect& operator-=( const T& );
    friend RegVect operator-( const T&, const RegVect& );

    RegVect operator-( void ) const;

    RegVect operator*( const T& ) const;
    RegVect& operator*=( const T& );
    friend RegVect operator*( const T&, const RegVect& );

    RegVect operator/( const T& ) const;
    RegVect& operator/=( const T& );
};






# 2 "qdesVar.C" 2



#pragma implementation




# 1 "qdesVarI.C" 1
template <class T,Types Tcode,const char* Name>
  qdesVar<T,Tcode,Name>::qdesVar( const T& p ) : VarRep( Tcode ), T( p ) {}

template <class T,Types Tcode,const char* Name>
  qdesVar<T,Tcode,Name>::qdesVar( const qdesVar<T,Tcode,Name>& p )
: VarRep( Tcode ), T( p ) {}

template <class T,Types Tcode,const char* Name>
  qdesBase<T,Tcode,Name>::qdesBase( const T& p )
: VarRep( Tcode ), data(p) {}

template <class T,Types Tcode,const char* Name>
  qdesBase<T,Tcode,Name>::qdesBase( const qdesBase<T,Tcode,Name>& p )
: VarRep( Tcode ), data(p.data) {}

template <class T,Types Tcode,const char* Name>
  qdesBase<T,Tcode,Name>::operator T& ( void ) { return data; }

template <class T,Types Tcode,const char* Name>
  qdesBase<T,Tcode,Name>::operator const T& ( void ) { return data; }

# 10 "qdesVar.C" 2




template <class T,Types Tcode,const char* Name>
inline VarRep* qdesVar<T,Tcode,Name>::clone( void ) const { 
    return new qdesVar<T,Tcode,Name>( *this ); 
}

template <class T,Types Tcode,const char* Name>
inline const char* qdesVar<T,Tcode,Name>::typeName( void ) const { return Name; }

template <class T,Types Tcode,const char* Name>
inline void qdesVar<T,Tcode,Name>::output( ostream& cout ) const { 
    cout << *((const T*)this); 
}

template <class T,Types Tcode,const char* Name>
inline VarRep* qdesBase<T,Tcode,Name>::clone( void ) const { 
    return new qdesBase<T,Tcode,Name>( *this ); 
}

template <class T,Types Tcode,const char* Name>
inline const char* qdesBase<T,Tcode,Name>::typeName( void ) const { 
    return Name; 
}

template <class T,Types Tcode,const char* Name>
inline void qdesBase<T,Tcode,Name>::output( ostream& cout ) const { 
    cout << *((const T*)this); 
}

typedef qdesBase<long,Int,"integer scalar"> intScalar;
typedef qdesBase<double,Real,"real scalar"> realScalar;
typedef qdesBase<complex,Cplx,"complex scalar"> cplxScalar;

typedef qdesVar<RegVect<long>,IntRegVect,"integer regular vector"> intRegVect;
typedef qdesVar<RegVect<double>,RealRegVect,"real regular vector"> realRegVect;
typedef qdesVar<RegVect<complex>,CplxRegVect,"complex regular vector"> cplxRegVect;