changeset 487:b4d9809d6ee2

type attribute (half done)
author kono
date Fri, 16 Dec 2005 20:27:34 +0900
parents 66d4b78f6219
children 62f3c801b6ac
files Changes mc-code-powerpc.c mc-codegen.c mc-parse.c mc-parse.h test/tmp7.c
diffstat 6 files changed, 223 insertions(+), 119 deletions(-) [+]
line wrap: on
line diff
--- a/Changes	Fri Dec 16 13:00:01 2005 +0900
+++ b/Changes	Fri Dec 16 20:27:34 2005 +0900
@@ -7399,4 +7399,18 @@
 取り除くコードを入れないといけないらしい。ちょっと影響が大きい
 ので、気が重い。
 
-
+attribute の情報は構文木には入らない。変数には attr field 
+があるので入る。関数の引数の情報はtypeに入るはずなので、そ
+れでだいじょうぶ? 引数のリストは構文解析中しかないので、型
+に入れるしかない。structのfieldに入る場合もあるしね。それを
+実際にチェックするかどうかはコンパイラの方針だけど。代入時
+にチェックすることは面倒だが可能。
+
+    list(ATTRIBUTE,type,value)
+
+ですか? value はint = (ctmode)?
+
+    type = set_type_attr(type,ctmode);
+    get_type_attr(type)
+
+かな。type_value みたいなのもいるかも。
--- a/mc-code-powerpc.c	Fri Dec 16 13:00:01 2005 +0900
+++ b/mc-code-powerpc.c	Fri Dec 16 20:27:34 2005 +0900
@@ -1852,9 +1852,9 @@
 static void
 increment_function_arg(int e3,int *pnargs,int *preg_arg,int *pfreg_arg) {
     int nargs=0,reg_arg=0,freg_arg=0;
-    int t=caddr(e3);
+    int t=type_value(caddr(e3));
     if (t>=0&&(car(t)==BIT_FIELD)) {
-	t = cadr(t);
+	t = type_value(cadr(t));
     }
     if(scalar(t)) {
 	nargs ++ ; reg_arg++;
@@ -1890,8 +1890,9 @@
 static int
 get_input_arg(int t,int mode,int nargs,int reg_arg,int freg_arg) 
 {
+    t = type_value(t);
     if (t>=0&&(car(t)==BIT_FIELD)) {
-	t = cadr(t);
+	t = type_value(cadr(t));
     }
     if(scalar(t)) {
 	if (mode==AS_SAVE) {
@@ -2064,7 +2065,7 @@
 		increment_function_arg(e3,&nargs,&reg_arg,&freg_arg),
 		e3 = cadr(e3)) {	
 	if (!(e4=car(e3))) continue;
-	t=caddr(e3);
+	t=type_value(caddr(e3));
 	arg = get_input_arg(t,AS_ARG,nargs,reg_arg,freg_arg);
 	if(scalar(t)) {
 	    reg_arg_list = list2(arg,reg_arg_list);
--- a/mc-codegen.c	Fri Dec 16 13:00:01 2005 +0900
+++ b/mc-codegen.c	Fri Dec 16 20:27:34 2005 +0900
@@ -770,14 +770,14 @@
 extern int 
 is_code(NMTBL *fnptr)
 {
-    int type = fnptr->ty;
+    int type = type_value(fnptr->ty);
     return type==CODE|| (type>0 && car(type)==CODE);
 }
 
 extern int 
 is_function(NMTBL *fnptr)
 {
-    int type = fnptr->ty;
+    int type = type_value(fnptr->ty);
     return type==FUNCTION || (type>0 && car(type)==FUNCTION);
 }
 
@@ -791,16 +791,16 @@
 function_type(int e1,int *dots)
 {
     int ret_type,t;
-    ret_type = cadr(e1);
+    ret_type = type_value(cadr(e1));
     if (ret_type==CHAR) ret_type=INT;
 
     /* check argments type is DOTS? */
     t = caddr(e1);
-    if (/* t==0 || */ t==DOTS) *dots = 1;
+    if (/* t==0 || */ type_value(t)==DOTS) *dots = 1;
     else {
         *dots = 0;
         for(;t;t = cadr(t)) {
-            if (car(t)==DOTS) *dots = 1;
+            if (type_value(car(t))==DOTS) *dots = 1;
         }
     }
 
@@ -1776,7 +1776,8 @@
 static int
 double_value(int e2)
 {
-    if (type>0&&car(type)==BIT_FIELD) e2=rvalue(e2);
+    int t = type_value(type);
+    if (t>0&&car(t)==BIT_FIELD) e2=rvalue(e2);
     switch(car(e2)) {
     case LCONST:
 #if LONGLONG_CODE
@@ -1787,25 +1788,26 @@
     case FCONST:
 	e2 = dlist2(DCONST,dcadr(e2)); break;
     default:
-	switch(type) {
+	switch(t) {
 	case DOUBLE: break;
 	case FLOAT: e2 =  list3(CONV,rvalue(e2),F2D); break;
 	case UNSIGNED: e2 =  list3(CONV,rvalue(e2),U2D); break;
 	case LONGLONG: e2 =  list3(CONV,rvalue(e2),LL2D); break;
 	case ULONGLONG: e2 =  list3(CONV,rvalue(e2),ULL2D); break;
 	default:
-	    if(integral(type)) e2 =  list3(CONV,rvalue(e2),I2D);
+	    if(integral(t)) e2 =  list3(CONV,rvalue(e2),I2D);
 	    else { error(TYERR); e2 =  dlist2(DCONST,1.0); }
 	}
     }
-    type = DOUBLE;
+    type = set_type_with_attr(DOUBLE,type);
     return e2;
 }
 
 static int
 float_value(int e2)
 {
-    if (type>0&&car(type)==BIT_FIELD) e2=rvalue(e2);
+    int t = type_value(type);
+    if (t>0&&car(t)==BIT_FIELD) e2=rvalue(e2);
     if (0) ;
 #if LONGLONG_CODE
     else if (car(e2)==LCONST)  e2 =  dlist2(FCONST,(double)lcadr(e2));
@@ -1813,18 +1815,18 @@
     else if (car(e2)==CONST)  e2 = dlist2(FCONST,(double)cadr(e2));
     else if (car(e2)==DCONST)  e2 = dlist2(FCONST,dcadr(e2));
     else {
-	switch(type) {
+	switch(t) {
 	case LONGLONG: e2 = list3(CONV,rvalue(e2),LL2F); break;
 	case ULONGLONG: e2 = list3(CONV,rvalue(e2),ULL2F); break;
 	case FLOAT: break;
 	case DOUBLE: e2 =  list3(CONV,rvalue(e2),D2F); break;
 	case UNSIGNED: e2 =  list3(CONV,rvalue(e2),U2F); break;
 	default:
-	    if(integral(type)) e2 =  list3(CONV,rvalue(e2),I2F);
+	    if(integral(t)) e2 =  list3(CONV,rvalue(e2),I2F);
 	    else { error(TYERR); e2 =  dlist2(DCONST,1.0); }
 	}
     }
-    type = FLOAT;
+    type = set_type_with_attr(FLOAT,type);
     return e2;
 }
 #endif
@@ -1833,7 +1835,8 @@
 static int
 longlong_value(int e2)
 {
-    if (type>0&&car(type)==BIT_FIELD) e2=rvalue(e2);
+    int t = type_value(type);
+    if (t>0&&car(t)==BIT_FIELD) e2=rvalue(e2);
     if (0) ;
     else if (car(e2)==CONST)  e2 = llist2(LCONST,(long long)cadr(e2));
     else if (car(e2)==LCONST) ;
@@ -1842,25 +1845,26 @@
         e2 = llist2(LCONST,(long long)dcadr(e2));
 #endif
     else {
-	switch(type) {
+	switch(t) {
 	case FLOAT: e2 = list3(CONV,rvalue(e2),F2LL); break;
 	case DOUBLE: e2 = list3(CONV,rvalue(e2),D2LL); break;
 	case UNSIGNED: e2 = list3(CONV,rvalue(e2),U2LL); break;
 	case LONGLONG: break;
 	case ULONGLONG: break;
 	default:
-	    if(integral(type)) e2 = list3(CONV,rvalue(e2),I2LL);
+	    if(integral(t)) e2 = list3(CONV,rvalue(e2),I2LL);
 	    else { error(TYERR); e2 = llist2(LCONST,0LL); }
 	}
     }
-    type = LONGLONG;
+    type = set_type_with_attr(LONGLONG,type);
     return e2;
 }
 
 static int
 ulonglong_value(int e2)
 {
-    if (type>0&&car(type)==BIT_FIELD) e2=rvalue(e2);
+    int t = type_value(type);
+    if (t>0&&car(t)==BIT_FIELD) e2=rvalue(e2);
     if (0);
     else if (car(e2)==CONST)  e2 = llist2(LCONST,(unsigned long long)cadr(e2));
     else if (car(e2)==LCONST)  ;
@@ -1876,11 +1880,11 @@
 	case LONGLONG: break;
 	case ULONGLONG: break;
 	default:
-	    if(integral(type)) e2 = list3(CONV,rvalue(e2),I2ULL);
+	    if(integral(t)) e2 = list3(CONV,rvalue(e2),I2ULL);
 	    else { error(TYERR); e2 = llist2(LCONST,0LL); }
 	}
     }
-    type = ULONGLONG;
+    type = set_type_with_attr(ULONGLONG,type);
     return e2;
 }
 #endif
@@ -1888,10 +1892,11 @@
 static int
 int_value(int e2)
 {
-    if (type>0&&car(type)==BIT_FIELD) e2=rvalue(e2);
+    int t = type_value(type);
+    if (t>0&&car(t)==BIT_FIELD) e2=rvalue(e2);
     if (0);
-    else if(type>0&&car(type)==ARRAY) return e2;
-    else if(scalar(type)) return e2;
+    else if(t>0&&car(t)==ARRAY) return e2;
+    else if(scalar(t)) return e2;
 #if FLOAT_CODE
     else if (car(e2)==DCONST||car(e2)==FCONST)  e2 = list2(CONST,(int)dcadr(e2));
 #endif
@@ -1899,7 +1904,7 @@
     else if (car(e2)==LCONST)  e2 = list2(CONST,(int)lcadr(e2));
 #endif
     else {
-	switch(type) {
+	switch(t) {
 	case FLOAT: e2 = list3(CONV,rvalue(e2),F2I); break;
 	case DOUBLE: e2 = list3(CONV,rvalue(e2),D2I); break;
 	case LONGLONG: e2 = list3(CONV,rvalue(e2),LL2I); break;
@@ -1908,15 +1913,17 @@
 	    error(TYERR); e2 = list2(CONST,1);
 	}
     }
-    type = INT;
+    type = set_type_with_attr(INT,type);
     return e2;
 }
 
 static int
 char_value(int e2)
 {
-    if (type!=CHAR&&type!=INT) { 
-	e2 = list3(CONV,int_value(rvalue(e2)),I2C); type = INT; 
+    int t = type_value(type);
+    if (t!=CHAR&&t!=INT) { 
+	e2 = list3(CONV,int_value(rvalue(e2)),I2C); 
+	type = set_type_with_attr(INT,type);
     }
     return e2;
 }
@@ -1924,8 +1931,10 @@
 static int
 short_value(int e2)
 {
-    if (type!=SHORT&&type!=INT) { 
-	e2 = list3(CONV,int_value(rvalue(e2)),I2S); type = INT; 
+    int t = type_value(type);
+    if (t!=SHORT&&t!=INT) { 
+	e2 = list3(CONV,int_value(rvalue(e2)),I2S); 
+	type = set_type_with_attr(INT,type);
     }
     return e2;
 }
@@ -1933,10 +1942,11 @@
 static int
 unsigned_value(int e2)
 {
-    if (type>0&&car(type)==BIT_FIELD) e2=rvalue(e2);
-    else if(type>0&&car(type)==ARRAY) return e2;
+    int t = type_value(type);
+    if (t>0&&car(t)==BIT_FIELD) e2=rvalue(e2);
+    else if(t>0&&car(t)==ARRAY) return e2;
     if (0);
-    else if(scalar(type)) return e2;
+    else if(scalar(t)) return e2;
 #if FLOAT_CODE
     else if (car(e2)==DCONST||car(e2)==FCONST)  e2 = list2(CONST,(int)dcadr(e2));
 #endif
@@ -1944,7 +1954,7 @@
     else if (car(e2)==LCONST)  e2 = list2(CONST,(unsigned)lcadr(e2));
 #endif
     else {
-	switch(type) {
+	switch(t) {
 	case LONGLONG: e2 = list3(CONV,rvalue(e2),LL2U); break;
 	case ULONGLONG: e2 = list3(CONV,rvalue(e2),ULL2U); break;
 	case FLOAT: e2 = list3(CONV,rvalue(e2),F2U); break;
@@ -1953,15 +1963,17 @@
 	    error(TYERR); 
 	}
     }
-    type = UNSIGNED;
+    type = set_type_with_attr(UNSIGNED,type);
     return e2;
 }
 
 static int
 uchar_value(int e2)
 {
-    if (type!=UCHAR&&type!=UNSIGNED) { 
-	e2 = list3(CONV,unsigned_value(rvalue(e2)),U2UC); type = UNSIGNED; 
+    int t = type_value(type);
+    if (t!=UCHAR&&t!=UNSIGNED) { 
+	e2 = list3(CONV,unsigned_value(rvalue(e2)),U2UC);
+	type = set_type_with_attr(UNSIGNED,type);
     }
     return e2;
 }
@@ -1969,8 +1981,10 @@
 static int
 ushort_value(int e2)
 {
-    if (type!=USHORT&&type!=UNSIGNED) { 
-	e2 = list3(CONV,unsigned_value(rvalue(e2)),U2US); type = UNSIGNED; 
+    int t = type_value(type);
+    if (t!=USHORT&&t!=UNSIGNED) { 
+	e2 = list3(CONV,unsigned_value(rvalue(e2)),U2US); 
+	type = set_type_with_attr(UNSIGNED,type);
     }
     return e2;
 }
@@ -1996,6 +2010,7 @@
 
 extern int
 assign_expr(int e1,int e2,int t) {
+    /* we should check const / assign violation here */
     switch(t) {
     case VOID:
 	break;
@@ -2023,10 +2038,10 @@
 #endif
     default:
 	if(scalar(t)) {
-	    e2=(t==UNSIGNED)?unsigned_value(e2):int_value(e2);
+	    e2=(type_value(t)==UNSIGNED)?unsigned_value(e2):int_value(e2);
 	    return(list3(ASS,e1,e2));
 	}
-	switch(car(t)) {
+	switch(car(type_value(t))) {
 	case BIT_FIELD:
             //        type = list4(BIT_FIELD,type,
             //            list3(type /*store type*/,0 /*bit offset*/,bitsize));
@@ -2034,7 +2049,7 @@
 	    return(list4(BASS,e1,e2,list2(BASS,t)));
 	case STRUCT:case UNION:
 	    if (size(t)!=size(type)) error(TYERR);
-	    type=t;
+	    type=t;    // dispose attr
 	    if(car(e2)==RSTRUCT && car(cadr(e2))==FUNCTION) {
 		replace_return_struct(cadr(e2),e1);
 		return cadr(e2);
@@ -2049,41 +2064,43 @@
 extern int
 cond(int t,int e1,int e2,int e3)
 {
+    int t0 = type_value(t);
+    int t1 = type_value(type);
     if(car(e1)==CONST) {
-	if(cadr(e1)) {type=t;return e2?e2:e1;} else return e3;
+	if(cadr(e1)) {type=set_type_with_attr(t,type);return e2?e2:e1;} else return e3;
     }
 #if FLOAT_CODE
     if(car(e1)==DCONST) {
 	if(dcadr(e1)) {type=t;return e2?e2:e1;} else return e3;
     }
-    if(type==DOUBLE||t==DOUBLE) {
+    if(t1==DOUBLE||t0==DOUBLE) {
 	e3=double_value(e3);
-	type = t; if (e2) e2=double_value(e2);
+	type = set_type_with_attr(t,type); if (e2) e2=double_value(e2);
 	return(list4(DCOND,e1,e2,e3));
     }
-    if(type==FLOAT||t==FLOAT) {
+    if(t1==FLOAT||t0==FLOAT) {
 	e3=float_value(e3);
-	type = t; if (e2) e2=float_value(e2);
+	type = set_type_with_attr(t,type); if (e2) e2=float_value(e2);
 	return(list4(FCOND,e1,e2,e3));
     }
 #endif
 #if LONGLONG_CODE
     if(car(e1)==LCONST) {
-	if(lcadr(e1)) {type=t;return e2?e2:e1;} else return e3;
+	if(lcadr(e1)) {type=set_type_with_attr(t,type);return e2?e2:e1;} else return e3;
     }
-    if(type==LONGLONG||t==LONGLONG) {
+    if(t1==LONGLONG||t0==LONGLONG) {
 	e3=longlong_value(e3);
-	type = t; if (e2) e2=longlong_value(e2);
+	type = set_type_with_attr(t,type); if (e2) e2=longlong_value(e2);
 	return(list4(LCOND,e1,e2,e3));
     }
-    if(type==ULONGLONG||t==ULONGLONG) {
+    if(t1==ULONGLONG||t0==ULONGLONG) {
 	e3=ulonglong_value(e3);
-	type = t; if (e2) e2=ulonglong_value(e2);
+	type = set_type_with_attr(t,type); if (e2) e2=ulonglong_value(e2);
 	return(list4(LCOND,e1,e2,e3));
     }
 #endif
-    if(type==INT||(t!=INT&&type==UNSIGNED))
-	type=t;
+    if(t1==INT||(t0!=INT&&t1==UNSIGNED))
+	type=set_type_with_attr(t,type);
     /* if (t!=type) error(TYERR); */
     return(list4(COND,e1,e2,e3));
 }
@@ -2092,8 +2109,9 @@
 assop(int e1,int e2,int op,int t,int no_float)
 {
     int ass,u = 0;
-    if(!(integral(type)||type==FLOAT||type==DOUBLE||
-	type==LONGLONG||type==ULONGLONG
+    int t0 = type_value(type);
+    if(!(integral(t0)||t0==FLOAT||t0==DOUBLE||
+	t0==LONGLONG||t0==ULONGLONG
 	    )) error(TYERR);
     switch(t) {
 #if FLOAT_CODE
@@ -2115,23 +2133,23 @@
 	return(list4(LASSOP,e1,e2,op+LOP+((op==MUL+AS||op==DIV+AS)?US:0)));
 #endif
     case CHAR:
-	type= INT; ass = CASSOP;  break;
+	type= set_type_with_attr(INT,type); ass = CASSOP;  break;
     case SHORT:
-	type= INT; ass = SASSOP; break;
+	type= set_type_with_attr(INT,type); ass = SASSOP; break;
     case INT:
-	type= INT; ass = ASSOP;  break;
+	type= set_type_with_attr(INT,type); ass = ASSOP;  break;
     case UCHAR:
-	type= UNSIGNED; ass = CUASSOP; u=1; break;
+	type= set_type_with_attr(UNSIGNED,type); ass = CUASSOP; u=1; break;
     case USHORT:
-	type= UNSIGNED; ass = SUASSOP; u=1; break;
+	type= set_type_with_attr(UNSIGNED,type); ass = SUASSOP; u=1; break;
     case UNSIGNED:
-	type= UNSIGNED; ass = ASSOP;  u=1; break;
+	type= set_type_with_attr(UNSIGNED,type); ass = ASSOP;  u=1; break;
     default:
 	if (t>0 && car(t)==BIT_FIELD) {
             //        type = list4(BIT_FIELD,type,
             //            list3(type /*store type*/,0 /*bit offset*/,symval));
 	    e2 = correct_type(e2,car(caddr(t))); /* store type */
-	    type = cadr(t); /* value type */
+	    type = set_type_with_attr(cadr(t),type); /* value type */
 	    return(list4(BASSOP,e1,e2,list2(op,t)));
 	}
     }
@@ -2144,12 +2162,12 @@
 	    }
 	}
     }
-    type=t;
+    type = set_type_with_attr(t,type);
     if(integral(t)) return(list4(ass,e1,e2,op));
     /* pointer += ... */
     if((op!=ADD&&op!=SUB)||car(t)!=POINTER) error(TYERR);
     e2=binop(MUL,e2,list2(CONST,size(cadr(t))),INT,UNSIGNED);
-    type=t;
+    type = set_type_with_attr(t,type);
 
     return list4(ASSOP,e1,e2,op);
 }
@@ -2664,6 +2682,7 @@
 {
     int sz,nsc,ndsp;
     int sbit_f = bit_field_disp;
+    int type0 = type_value(type);
     bit_field_disp = 0;  // default is 0, recover only in bit-field
 
     if (n==0) {
@@ -2673,7 +2692,7 @@
     nsc=ndsp=0;
     if (stmode==EXTRN||mode==GDECL)
 	n->ty = type;  /* must be in global table/heap */
-    if(type>0&&(car(type)==FUNCTION || car(type)==CODE)) {
+    if(type0>0&&(car(type0)==FUNCTION || car(type0)==CODE)) {
 	if ((mode==GDECL)) {
 	    fcheck(n);
 	    set_ctmode(n,ctmode);
@@ -2686,19 +2705,19 @@
         /* Struct fields name lists are in the struct type or tag. */
         /* Only name in the table is used. Do not set n->ty! */
 	/* Struct field may volatile... where do I put? list2(VOLATILE,type)? */
-	if (type>0 && car(type)==BIT_FIELD) {
+	if (type0>0 && car(type0)==BIT_FIELD) {
 	    bit_field_disp=sbit_f;   // default is 0, recover only here.
             //        type = list4(BIT_FIELD,value type,
             //            list3(store type,bit offset,bit_width));
 #if BIT_FIELD_CODE
-	    cadr(caddr(type)) = code_bit_field_disp(
+	    cadr(caddr(type0)) = code_bit_field_disp(
 		type,&disp,&bit_field_disp,&sz);
 	    /* bit_field_disp is next bit posision */
 #else
 	    error(-1);
 #endif
 	}  else {
-	    sz = size(type);
+	    sz = size(type0);
             if (sz%size_of_int==0) {
                 disp = ((disp+(size_of_int-1))&~(size_of_int-1));
             }
@@ -2706,10 +2725,10 @@
 	if (n!=&null_nptr)
 	    fields = list4(type,fields,(int)(n->nm),disp);
     } else if (mode==GUDECL||mode==LUDECL) {
-	if (type>0 && car(type)==BIT_FIELD) {
-	    cadr(caddr(type)) = 0; sz = size(cadr(type));
+	if (type0>0 && car(type0)==BIT_FIELD) {
+	    cadr(caddr(type0)) = 0; sz = size(cadr(type0));
 	}  else {
-	    sz = size(type);
+	    sz = size(type0);
 	}
 	fields = list4(type,fields,(int)(n->nm),0);
     } else {
@@ -2770,25 +2789,27 @@
 	    ndsp = fwdlabel();
 	break;
     case ADECL:
-	if(!integral(type)&&type>0&&(car(type)==FUNCTION||car(type)==CODE)) {
+	if(!integral(type0)&&type0>0&&(car(type0)==FUNCTION||car(type0)==CODE)) {
 	    type=list2(POINTER,type); n->ty = type;
+	    type0=type;
 	}
 	fnptr->dsp=list4(type,fnptr->dsp,(int)n,0);
 	n->sc = LVAR;
-	if(type==CHAR||type==UCHAR) {
+	if(type0==CHAR||type0==UCHAR) {
 	    if (n->dsp==0) {
 		n->dsp = args;
 		if (endian) n->dsp += size_of_int-1;
 	    }
 	    args += size_of_int;
-	} else if(type==SHORT||type==USHORT) {
+	} else if(type0==SHORT||type0==USHORT) {
 	    if (n->dsp==0) {
 		n->dsp = args;
 		if (endian) n->dsp += size_of_int-size_of_short;
 	    }
 	    args += size_of_int;
 #if  1
-	} else if(type>0&&(car(type)==UNION||car(type)==STRUCT)) {
+	} else if(type0>0&&(car(type0)==UNION||car(type0)==STRUCT)) {
+	    /* alignment in struct in argument */
 	    n->dsp = args;
 	    args += ((sz+(size_of_int-1))&~(size_of_int-1));
 #endif
@@ -2799,7 +2820,7 @@
 	    args += sz;
 	}
 	cadddr(fnptr->dsp)=sz;
-	if(type==VOID) {
+	if(type0==VOID) {
 	} else {
 	    n->ty = type;
 	}
@@ -2808,16 +2829,16 @@
     case STAT: /* return (struct hoge)f() case? */
     case LDECL:
 	if (stmode==REGISTER && !inmode) {
-	    if(scalar(type)) {
+	    if(scalar(type0)) {
 		ndsp = get_register_var(n);
 #if FLOAT_CODE
-	    } else if (type==FLOAT) {
+	    } else if (type0==FLOAT) {
 		ndsp = get_dregister_var(n,0);
-	    } else if (type==DOUBLE) {
+	    } else if (type0==DOUBLE) {
 		ndsp = get_dregister_var(n,1);
 #endif
 #if LONGLONG_CODE
-	    } else if (type==LONGLONG||type==ULONGLONG) {
+	    } else if (type0==LONGLONG||type0==ULONGLONG) {
 		ndsp = get_lregister_var(n);
 #endif
 	    } else error(DCERR);
@@ -2867,6 +2888,7 @@
 {
     int l;
     char *name;
+    t = type_value(t);
     name = n->nm; 
     if(mode!=GDECL && mode!=STADECL)  { 
 	error(-1); return;
@@ -3112,8 +3134,9 @@
 extern void
 fcheck(NMTBL *n)
 {
+    int type0 = type_value(type);
     if(!(mode==GDECL||mode==ADECL)||
-             (car(type)!=FUNCTION&&car(type)!=CODE)) error(DCERR);
+             (car(type0)!=FUNCTION&&car(type0)!=CODE)) error(DCERR);
     if (n->sc==EMPTY) {
 	n->sc=EXTRN;
 	n->ty=type;
@@ -3127,6 +3150,8 @@
 static void
 compatible(int t1, int t2)
 {
+    t1 = type_value(t1);
+    t2 = type_value(t2);
     if(integral(t1)) {
 	    if(t1!=t2) error(TYERR);
     }
@@ -3143,12 +3168,14 @@
 extern int
 scalar(int t)
 {
+    t = type_value(t);
     return(integral(t)||(t>0 && car(t)==POINTER));
 }
 
 extern int
 integral(int t)
 {
+    t = type_value(t);
     return(t==INT||t==SIGNED||t==CHAR||t==UNSIGNED||
         t==UCHAR||t==SHORT||t==USHORT||t==ENUM);
 }
@@ -3208,17 +3235,18 @@
 {
     int op,c;
     NMTBL *n;    
+    int type0 = type_value(type);
 
     if (e==0) error(-1);
     op = 0;
-    switch(type) {
+    switch(type0) {
     case INT:		break;
     case UNSIGNED:	break;
     case VOID:		break;
-    case CHAR:		op=COP; type=INT; break;
-    case UCHAR:		op=COP+US; type=UNSIGNED; break;
-    case SHORT:		op=SOP; type=SIGNED; break;
-    case USHORT:	op=SOP+US; type=UNSIGNED; break;
+    case CHAR:		op=COP; type=set_type_with_attr(INT,type); break;
+    case UCHAR:		op=COP+US; type=set_type_with_attr(UNSIGNED,type); break;
+    case SHORT:		op=SOP; type=set_type_with_attr(SIGNED,type); break;
+    case USHORT:	op=SOP+US; type=set_type_with_attr(UNSIGNED,type); break;
     case LONGLONG:	op=LOP; break;
     case ULONGLONG:	op=LOP+US; break;
     case FLOAT:		op=FOP; break;
@@ -3226,17 +3254,17 @@
     case CODE:	return e;
     case 0:	error(-1); return e;
     default:
-	if (integral(type)) break;
-	switch(car(type)) {
+	if (integral(type0)) break;
+	switch(car(type0)) {
 	case ARRAY:
-	    type=list2(POINTER,cadr(type));
+	    type=set_type_with_attr(list2(POINTER,cadr(type)),type);
 	    if(car(e)==INDIRECT) return cadr(e);
 	    return list2(ADDRESS,e);
 	case STRUCT: case UNION:
 	    if(car(e)==RSTRUCT) return e; /* ??? */
 	    return list3(RSTRUCT,e,cadr(type) /* size */);
 	case FUNCTION:
-	    type=cadr(type);
+	    type=set_type_with_attr(cadr(type0),type);
 	    return e;
 	case CODE:
 	    return e;
@@ -3245,7 +3273,7 @@
 	case BIT_FIELD:
 	    e =  list3(RBIT_FIELD,cadr(e),type);
             /*                         byte rvalue,   store type */
-	    type = cadr(type); /* value type */
+	    type=set_type_with_attr(cadr(type0),type);/* value type */
 	    return e;
 	    break;
 	default:
@@ -3285,8 +3313,9 @@
 lcheck(int e)
 {
     int t;
-    if(scalar(type)) return;
-    switch(type) {
+    int type0 = type_value(type);
+    if(scalar(type0)) return;
+    switch(type0) {
     case DOUBLE: case FLOAT : case LONGLONG: case ULONGLONG:
 	return;
     default:
@@ -3296,21 +3325,22 @@
 	return;
 	}
     }
-    if ((t=car(type))<0 && t!=STRUCT && t!=UNION)
+    if ((t=car(type0))<0 && t!=STRUCT && t!=UNION)
 	error(LVERR);
 }
 
 extern int
 indop(int e)
 {
-    if(type!=INT&&type!=UNSIGNED) {
-	if(car(type)==POINTER)
-	    type=cadr(type);
-	else if(car(type)==CODE || car(type)==FUNCTION)
-	    type=type;
-	else error(TYERR);
+    int type0 = type_value(type);
+    if(type0!=INT&&type0!=UNSIGNED) {
+	if(car(type0)==POINTER)
+	    type=set_type_with_attr(cadr(type),type);
+	else if(car(type0)==CODE || car(type0)==FUNCTION) {
+	    // type=type;
+	} else error(TYERR);
     } else
-	type= CHAR;  // ?!
+	type= set_type_with_attr(CHAR,type);  // ?!
     if(car(e)==ADDRESS)
 	return(cadr(e));
     return(list2(INDIRECT,e));
@@ -3325,7 +3355,7 @@
 {
     int t;
     NMTBL *nptr0;
-    t = caddr(type);
+    t = caddr(type_value(type));
     if (t==0) {
 	nptr0=(NMTBL*)cadddr(type);
 	t = caddr(type) = caddr(nptr0->ty);
@@ -3343,9 +3373,11 @@
 strop(int e,int ind)
 {
     int dsp = 0;
+    int type0;
 
     if (ind) e = indop(rvalue(e));
-    if (integral(type)||(car(type)!=STRUCT && car(type)!=UNION))
+    type0 = type_value(type);
+    if (integral(type0)||(car(type0)!=STRUCT && car(type0)!=UNION))
 	e=rvalue(e);
     /* type = list4(s,disp,fields,tag_nptr); */
     /* print_fields(caddr(type),"strop"); */
@@ -3374,6 +3406,7 @@
 	    e=list2(INDIRECT,e);
 	}
     }
+    type0 = type_value(type);
     if (type>0&&car(type)==BIT_FIELD) {
 	// n->ty = list4(BIT_FIELD,type,bit_offset, bit_size);
 	e=list3(BIT_FIELD,e,type);  //  ???
@@ -3381,6 +3414,10 @@
     return e;
 }
 
+/*
+   I don't know how to handle type attribute (const/volatie) in binop
+ */
+
 #if FLOAT_CODE
 /* binary floating computation */
 
@@ -3786,8 +3823,9 @@
 /* coarse for function/code segments arguments */
 
 extern int
-correct_type(int e,int t)
+correct_type(int e,int t0)
 {
+    int t = type_value(t0);
     /* e = rvalue(e); */
 #if BIT_FIELD_CODE
     if (type==BIT_FIELD) e = rvalue(e);
@@ -3826,7 +3864,7 @@
 	    if (integral(t)) e = int_value(e);
 	}
     }
-    type = t;
+    type = t0;
     return e;
 }
 
--- a/mc-parse.c	Fri Dec 16 13:00:01 2005 +0900
+++ b/mc-parse.c	Fri Dec 16 20:27:34 2005 +0900
@@ -952,6 +952,9 @@
 	t= INT;                     // empty typespec 
     }
     qualifiers();
+    if (ctmode) {
+	t = set_type_attr(t,ctmode);
+    }
     return t;
 }
 
@@ -1184,6 +1187,7 @@
 extern int
 size(int t)
 {
+    t = type_value(t);
     if (t<0) {
 	switch(t) {
 	case CHAR: return 1;
@@ -1367,9 +1371,10 @@
 static int
 decl_data(int t, NMTBL *n,int offset,int skip)
 {
-    int t1,e,i,mode_save;
+    int t0,t1,e,i,mode_save;
 
     conv->decl_data_();
+    t0 = type_value(t);
     mode_save = mode;
     mode=STAT;
     if (offset==0) {
@@ -1395,13 +1400,13 @@
  	offset = assign_data(e,t,n,offset);
  	type=t;
 	return offset;
-    } else if (t==FLOAT||t==DOUBLE||t==LONGLONG||t==ULONGLONG) {
+    } else if (t0==FLOAT||t0==DOUBLE||t0==LONGLONG||t0==ULONGLONG) {
  	e=expr1();
 	mode = mode_save;
  	offset = assign_data(e,t,n,offset);
  	type=t;
 	return offset;
-    } else if ((t1 = car(t)) && t1==ARRAY) {
+    } else if ((t1 = car(t0)) && t1==ARRAY) {
 	if (sym==LC) {
 	    conv->decl_data_begin_();
 	    mode = mode_save;
@@ -1428,15 +1433,15 @@
 		}
 	    }
 	    /* NOT REACHED */
-	} else if (cadr(t)==CHAR) {
+	} else if (cadr(t0)==CHAR) {
 	    e=expr1();
 	    mode = mode_save;
 	    if(car(e)!=STRING)
 		error(TYERR);
 	    offset=assign_data(e,list3(ARRAY,CHAR,size(type)),n,offset);
-	    if (caddr(t)==0) {                  /* size not defined      */
-		caddr(t)=size(type);           /* define array size     */
-	    } else if (caddr(t)!=size(type)) {  /* size match?           */
+	    if (caddr(t0)==0) {                  /* size not defined      */
+		caddr(t0)=size(type);           /* define array size     */
+	    } else if (caddr(t0)!=size(type)) {  /* size match?           */
 		error(TYERR);
 	    }
 	    return offset; /* not reached */
@@ -4651,6 +4656,47 @@
     fprintf(stderr,"nptr->nm %s\n",n->nm);
 }
 
+extern int
+set_type_attr(int type,int attr)
+{
+    if (type>0 && car(type)==ATTRIBUTE) {
+	caddr(type) = attr;
+    } else {
+	type = list3(ATTRIBUTE,type,attr);
+    }
+    return type;
+}
+
+extern int
+get_type_attr(int type)
+{
+    if (type>0 && car(type)==ATTRIBUTE) {
+	return caddr(type);
+    } else {
+	return 0;
+    }
+}
+
+extern int
+type_value(int type)
+{
+    if (type>0 && car(type)==ATTRIBUTE) {
+	return cadr(type);
+    } else {
+	return type;
+    }
+}
+
+extern int
+set_type_with_attr(int type,int type_with_attr)
+{
+    if (type_with_attr>0 && car(type_with_attr)==ATTRIBUTE) {
+	return list3(ATTRIBUTE,type_value(type),get_type_attr(type_with_attr));
+    } else {
+	return type;
+    }
+}
+
 /* for gdb... */
 
 extern int c0(int d)  { fprintf(stderr,"heap[%d]=",d);return car(d); }
--- a/mc-parse.h	Fri Dec 16 13:00:01 2005 +0900
+++ b/mc-parse.h	Fri Dec 16 20:27:34 2005 +0900
@@ -117,6 +117,11 @@
 extern int has_attr(NMTBL *n,int attr);
 extern int attr_value(NMTBL *n,int attr);
 extern void set_attr(NMTBL *n,int attr,int value);
+extern int set_type_attr(int type,int attr);
+extern int get_type_attr(int type);
+extern int type_value(int type);
+extern int set_type_with_attr(int type,int type_with_attr);
+
 
 #if LONGLONG_CODE
 extern int llist2(int e1, long long d1);
--- a/test/tmp7.c	Fri Dec 16 13:00:01 2005 +0900
+++ b/test/tmp7.c	Fri Dec 16 20:27:34 2005 +0900
@@ -66,7 +66,7 @@
 	main2(aaa);
 } 
 
-
+int
 main(ac,av)
 int ac;
 char *av[];
@@ -111,7 +111,7 @@
 /* main aaa.a[55] 0 */
     printf("#0110:main aaa.a[55] %d\n",aaa.a[55]); 
     p = av[0];
-    if (!p) return;
+    if (!p) return 55;
     i = p[1];
     p = p+i;
 /* 47 ./a.out */