/*ident "@(#)cls4:src/typ2.c 1.6" */ /******************************************************************************* C++ source for the C++ Language System, Release 3.0. This product is a new release of the original cfront developed in the computer science research center of AT&T Bell Laboratories. Copyright (c) 1993 UNIX System Laboratories, Inc. Copyright (c) 1991, 1992 AT&T and UNIX System Laboratories, Inc. Copyright (c) 1984, 1989, 1990 AT&T. All Rights Reserved. THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE of AT&T and UNIX System Laboratories, Inc. The copyright notice above does not evidence any actual or intended publication of such source code. *******************************************************************************/ #include "cfront.h" #include "size.h" #include "template.h" extern int chars_in_largest; int largest_int; void typ_init() { chars_in_largest = strlen(LARGEST_INT); largest_int = int(str_to_long(LARGEST_INT)); defa_type = new basetype(INT,0); // note defa_type!=int_type int_type = new basetype(INT,0); // but they both represent `int' PERM(int_type); int_type->defined = DEFINED ; PERM(defa_type); defa_type->defined = DEFINED ; moe_type = new basetype(INT,0); PERM(moe_type); moe_type->defined = DEFINED ; moe_type->b_const = 1; moe_type->check(0); uint_type = new basetype(INT,0); PERM(uint_type); uint_type->defined = DEFINED ; uint_type->type_adj(UNSIGNED); uint_type->check(0); long_type = new basetype(LONG,0); PERM(long_type); long_type->defined = DEFINED ; long_type->check(0); ulong_type = new basetype(LONG,0); PERM(ulong_type); ulong_type->defined = DEFINED ; ulong_type->type_adj(UNSIGNED); ulong_type->check(0); short_type = new basetype(SHORT,0); PERM(short_type); short_type->defined = DEFINED ; short_type->check(0); ushort_type = new basetype(SHORT,0); PERM(ushort_type); ushort_type->defined = DEFINED ; ushort_type->type_adj(UNSIGNED); ushort_type->check(0); float_type = new basetype(FLOAT,0); PERM(float_type); float_type->defined = DEFINED ; double_type = new basetype(DOUBLE,0); PERM(double_type); double_type->defined = DEFINED ; ldouble_type = new basetype(LDOUBLE,0); PERM(ldouble_type); ldouble_type->defined = DEFINED ; zero_type = new basetype(ZTYPE,0); PERM(zero_type); zero_type->defined = DEFINED ; zero->tp = zero_type; void_type = new basetype(VOID,0); PERM(void_type); void_type->defined = DEFINED ; char_type = new basetype(CHAR,0); PERM(char_type); char_type->defined = DEFINED ; uchar_type = new basetype(CHAR,0); PERM(uchar_type); uchar_type->defined = DEFINED ; uchar_type->type_adj(UNSIGNED); uchar_type->check(0); Pchar_type = char_type->addrof(); PERM(Pchar_type); Pchar_type->defined = DEFINED ; Pint_type = int_type->addrof(); PERM(Pint_type); Pint_type->defined = DEFINED ; Pvoid_type = void_type->addrof(); PERM(Pvoid_type); Pvoid_type->defined = DEFINED ; Pfctvec_type = new fct(int_type,0,0); // must be last, see basetype::normalize() Pfctvec_type = Pfctvec_type->addrof(); Pfctvec_type = Pfctvec_type->addrof(); PERM(Pfctvec_type); Pfctvec_type->defined = DEFINED ; gtbl = new table(GTBLSIZE,0,0); gtbl->t_name = new name("global"); ptbl = new table(CTBLSIZE,0,0); ptbl->t_name = new name("ptbl"); // tmp_tbl = new table(CTBLSIZE,0,0); templ_compilation::templates = new table(128,0,0); bound_expr_tbl = new table(12,0,0); } Pbase basetype::arit_conv(Pbase t) /* perform the "usual arithmetic conversions" C ref Manual 6.6 on "this" op "t" "this" and "t" are integral or floating "t" may be 0 */ { // error('d', "arit_conv: this: %k %d %t %d", base, base, this, this ); bit l; bit u; bit f; bit l1 = (base == LONG); bit u1 = b_unsigned; bit f1 = (base==FLOAT || base==DOUBLE || base==LDOUBLE); if (t) { t = (Pbase)t->skiptypedefs(); // error('d', "arit_conv: t: %k %d %t %d", t->base, t->base, t, t ); bit l2 = (t->base == LONG); bit u2 = t->b_unsigned; bit f2 = (t->base==FLOAT || t->base==DOUBLE || t->base==LDOUBLE); l = l1 || l2; u = u1 || u2; f = f1 || f2; } else { l = l1; u = u1; f = f1; } if (f) { if (base==LDOUBLE || (t && t->base==LDOUBLE)) return ldouble_type; if (base==DOUBLE || (t && t->base==DOUBLE)) return double_type; return float_type; } if (l & u) return ulong_type; if (l & !u) return long_type; if (u) { if (base==INT || (t && t->base==INT)) return uint_type; if (SZ_SHORT==SZ_INT) // ANSIism if (base==SHORT || (t && t->base==SHORT)) return uint_type; return int_type; } return int_type; } bit vec_const = 0; bit fct_const = 0; bit type::tconst() /* is this type a constant */ { Ptype t = this; vec_const = 0; fct_const = 0; //error('d',"tconst %t",t); xxx: switch (t->base) { case TYPE: if (Pbase(t)->b_const) return 1; t = Pbase(t)->b_name->tp; goto xxx; case VEC: vec_const = 1; return 1; case PTR: case RPTR: return Pptr(t)->b_const; case FCT: case OVERLOAD: fct_const = 1; return 1; default: return Pbase(t)->b_const; } } bit type::is_const_object() { int cc = this->tconst(); Ptype tt = this->skiptypedefs(); while ( cc && tt->base == VEC ) { tt = Pvec(tt)->typ; cc = tt->tconst(); tt = tt->skiptypedefs(); } return cc; } TOK type::set_const(bit mode) /* make someting a constant or variable, return old status */ { Ptype t = this; int m; xxx: switch (t->base) { case TYPE: m = Pbase(t)->b_const; Pbase(t)->b_const = mode; t = Pbase(t)->b_name->tp; goto xxx; case ANY: case RPTR: case VEC: return t->base; // constant by definition case PTR: m = Pptr(t)->b_const; Pptr(t)->b_const = mode; return m; default: m = Pbase(t)->b_const; Pbase(t)->b_const = mode; return m; } } Pptr type::is_ref() { Ptype t = skiptypedefs(); switch (t->base) { case RPTR: return Pptr(t); default: return 0; } } Pclass Mptr; Pptr type::is_ptr() { Ptype t = skiptypedefs(); switch (t->base) { case PTR: case VEC: Mptr = Pptr(t)->memof; return Pptr(t); default: return 0; } } Pptr type::is_ptr_or_ref() { Ptype t = skiptypedefs(); switch (t->base) { case PTR: case RPTR: case VEC: Mptr = Pptr(t)->memof; return Pptr(t); default: return 0; } } int type::align() { Ptype t = skiptypedefs(); /*fprintf(stderr,"align %d %d\n",t,t->base);*/ switch (t->base) { case COBJ: return t->bname_type()->align(); case VEC: return Pvec(t)->typ->align(); case ANY: return 1; case CHAR: return AL_CHAR; case SHORT: return AL_SHORT; case INT: return AL_INT; case LONG: return AL_LONG; case FLOAT: return AL_FLOAT; case DOUBLE: return AL_DOUBLE; case LDOUBLE: return AL_LDOUBLE; case PTR: case RPTR: return AL_WPTR; case CLASS: return Pclass(t)->obj_align; case ENUM: case EOBJ: return AL_INT; case VOID: error("illegal use of void"); return AL_INT; default: error('i',"(%d,%k)->type::align",t,t->base); return 0; } } bit fake_sizeof; int type::tsizeof(int ptmc) /* the sizeof type operator return the size in bytes of the types representation */ { Ptype t = skiptypedefs(); //error('d',"zx %t %d",t,t->base); if (t == 0) error('i',"typ.tsizeof(t==0)"); switch (t->base) { case COBJ: t = t->bname_type(); if (t == 0) return 0; // ``fake'' generated classes: _Sdd return t->tsizeof(ptmc); case ANY: return 1; case VOID: return 0; case ZTYPE: return SZ_WPTR; /* assume pointer */ case CHAR: return SZ_CHAR; case SHORT: return SZ_SHORT; case INT: return SZ_INT; case LONG: return SZ_LONG; case FLOAT: return SZ_FLOAT; case DOUBLE: return SZ_DOUBLE; case LDOUBLE: return SZ_LDOUBLE; case VEC: { Pvec v = Pvec(t); if (v->size == 0) { if (fake_sizeof == 0) error("sizeof array with undeclared dimension"); return SZ_WPTR; // vector argument has sizeof ptr } return v->size * v->typ->tsizeof(); } case RPTR: case PTR: { int k = (Pptr(t)->memof && !ptmc)?sizeof(short)+sizeof(short):0; t = Pptr(t)->typ->skiptypedefs(); switch (t->base) { default: return SZ_WPTR; case CHAR: return SZ_BPTR; case FCT: return SZ_WPTR+k; } } case FIELD: error("sizeof(field)"); return int(Pbase(t)->b_bits)/BI_IN_BYTE+1; case OVERLOAD: case FCT: error("sizeof(function)"); return 0; case CLASS: { Pclass cl = Pclass(t); if ((cl->defined&(DEFINED|SIMPLIFIED)) == 0) { if ( cl->class_base == CL_TEMPLATE || cl->class_base == UNINSTANTIATED ) error("YC%t not yet instantiated; please add an explicit instantiation (Tdef%t)",cl,cl); else error("%tU, size not known",cl); return SZ_INT; } if (cl->c_body == 1) // detect first allocation or sizeof cl->dcl_print(0); return cl->obj_size; } case EOBJ: if ((t->enumtype()->defined&(DEFINED|SIMPLIFIED)) == 0) error("%tU, size not known",t->enumtype()); case ENUM: return SZ_INT; default: return 0; // deref can be called for any type //error('i',"sizeof(%d)",t->base); } } bit type::vec_type() { Ptype t = skiptypedefs(); switch (t->base) { case ANY: case VEC: case PTR: case RPTR: return 1; default: return 0; } } int ref_initializer; Ptype type::deref() /* index==1: *p index==0: p[expr] */ { //error('d',"%t -> deref() refd %d",this,ref_initializer); Ptype t = skiptypedefs(); switch (t->base) { case PTR: case RPTR: case VEC: { if (t == Pvoid_type) error("void* dereferenced"); t = Pvec(t)->typ; if (ref_initializer == 0) { Ptype tt = t->skiptypedefs(); if (tt->base == COBJ) { tt = tt->bname_type(); if (tt && Pclass(tt)->defined&(DEFINED|SIMPLIFIED)) (void) t->tsizeof(); } } // no break } case ANY: return t; default: error("nonP dereferenced"); return any_type; } } Pfct type::memptr() // is ``this'' a pointer to member function { if (this == 0) return 0; Ptype t = skiptypedefs(); if (t->base != PTR || Pptr(t)->memof==0) return 0; t = Pptr(t)->typ->skiptypedefs(); return (t->base == FCT) ? Pfct(t) : 0; } Ptype type::skiptypedefs() // starting from ``this'', return first non-typedef { register Ptype t = this; if(t==0) return t; while (t->base == TYPE) { t = t->bname_type(); } return t; } Ptype type::skiptypedefs(bit &isconst) // starting from ``this'', return first non-typedef { register Ptype t = this; isconst=0; if(t==0) return t; while (t->base == TYPE) { isconst |= Pbase(t)->b_const; t = t->bname_type(); } isconst |= Pbase(t)->b_const; return t; } Ptype type::mkconst() { Ptype r = this; switch(base) { case TYPE: { Ptype t = skiptypedefs(); if(t->base == VEC) return t->mkconst(); } case INT: case CHAR: case SHORT: case LONG: case FLOAT: case DOUBLE: case LDOUBLE: case FIELD: case ZTYPE: case COBJ: case EOBJ: if(b_const==0) { // r = new basetype(*(Pbase)this); // won't compile with 2.0 r = new basetype(base,0); PERM(r); *(Pbase)r = *(Pbase)this; r->b_const=1; } break; case PTR: case RPTR: if(b_const==0) { // r = new ptr(*(Pptr)this); // won't compile with 2.0 r = new ptr(base,0); PERM(r); *(Pptr)r = *(Pptr)this; r->b_const=1; } break; case VEC: { Ptype t = Pvec(this)->typ->mkconst(); if(t != Pvec(this)->typ) { // r = new vec(*(Pvec)this); // won't compile with 2.0 r = new vec(Pvec(this)->typ,0); PERM(r); *(Pvec)r = *(Pvec)this; Pvec(r)->typ=t; } break; } default: error('i',"mkconst for %t",this); } return r; }