📄 cmath2.c
字号:
result_type = TYPE_VOID;
} else if( op1_type == TYPE_UNION ||
op1_type == TYPE_STRUCT ||
op2_type == TYPE_UNION ||
op2_type == TYPE_STRUCT ) {
result_type = ERR;
} else {
result_type = BinResult[ op1_type ][ op2_type ];
if( opr == T_PERCENT && result_type >= TYPE_FLOAT ) {
CErr1( ERR_EXPR_MUST_BE_INTEGRAL );
}
if( result_type < INT ) result_type = INT;
}
if( result_type == ERR ) {
CErr1( ERR_EXPR_MUST_BE_ARITHMETIC );
result_type = INT;
}
switch( opr ) {
case T_XOR_EQUAL:
case T_OR_EQUAL:
/* if op2 is a constant, check to see if constant truncated */
if( op2->op.opr == OPR_PUSHINT ) {
unsigned long max_value;
switch( TypeSize( typ ) ) {
case 1:
max_value = 0x000000FF;
break;
case 2:
max_value = 0x0000FFFF;
break;
default:
max_value = ~0ul;
break;
}
if( op2->op.ulong_value > max_value ) {
CWarn1( WARN_CONSTANT_TOO_BIG, ERR_CONSTANT_TOO_BIG );
}
}
case T_AND_EQUAL:
case T_RSHIFT_EQUAL:
case T_LSHIFT_EQUAL:
case T_PERCENT_EQUAL:
/* check for integral operand. 16-nov-89 */
result_type = IntResult[ op1_type ][ op2_type ];
if( result_type == ERR ) {
CErr1( ERR_EXPR_MUST_BE_INTEGRAL );
}
case T_TIMES_EQUAL:
case T_DIVIDE_EQUAL:
result_type = op1_type;
break;
default:
op1 = Convert( op1, op1_type, result_type );
op2 = Convert( op2, op2_type, result_type );
typ = GetType( result_type );
}
tree = ExprNode( op1, TokenToOperator( opr ), op2 );
if( result_type == ERR ) {
tree = ErrorNode( tree );
} else {
tree->expr_type = GetType( result_type );
tree->op.result_type = typ;
}
return( tree );
}
local int LValue( TREEPTR op1 )
{
TYPEPTR typ;
if( op1->op.opr == OPR_ERROR ) return( 1 );
if( IsLValue( op1 ) ) {
typ = TypeOf( op1 );
if( typ->decl_type != TYPE_ARRAY ) {
if( TypeSize(typ) == 0 ) {
CErr1( ERR_INCOMPLETE_EXPR_TYPE );
}
if( op1->op.flags & OPFLAG_LVALUE_CAST ) {
op1->op.flags &= ~(OPFLAG_LVALUE_CAST|OPFLAG_RVALUE);
CWarn1( WARN_LVALUE_CAST, ERR_LVALUE_CAST );
}
return( 1 );
}
}
CErr1( ERR_MUST_BE_LVALUE );
return( 0 );
}
local void SetSymAssigned( TREEPTR opnd )
{
auto SYM_ENTRY sym;
while( opnd->op.opr == OPR_INDEX ) opnd = opnd->left;
if( opnd->op.opr == OPR_PUSHADDR ) {
SymGet( &sym, opnd->op.sym_handle );
if( sym.level != 0 ) {
if( !(sym.flags & SYM_ASSIGNED) ) {
sym.flags |= SYM_ASSIGNED;
SymReplace( &sym, opnd->op.sym_handle );
}
}
}
}
TREEPTR InitAsgn( TYPEPTR typ, TREEPTR op2 )
{
if( op2->op.opr == OPR_ERROR ) {
return( op2 );
}
op2 = RValue( op2 );
if( !CompFlags.no_check_inits ){ // else fuck em
ParmAsgnCheck( typ, op2, 0 );
}
return( op2 );
}
TREEPTR AsgnOp( TREEPTR op1, TOKEN opr, TREEPTR op2 )
{
TYPEPTR typ;
pointer_class op1_class;
pointer_class op2_class;
int isLValue;
if( op1->op.opr == OPR_ERROR ) {
FreeExprTree( op2 );
return( op1 );
}
if( op2->op.opr == OPR_ERROR ) {
FreeExprTree( op1 );
return( op2 );
}
if(op1->op.flags & OPFLAG_LVALUE_CAST) { /* 18-aug-95 */
if( CompFlags.extensions_enabled ){
op1->op.flags &= ~(OPFLAG_LVALUE_CAST|OPFLAG_RVALUE);
if( op1->op.opr == OPR_PUSHSYM ){
op1->op.opr = OPR_PUSHADDR;
}
CWarn1( WARN_LVALUE_CAST, ERR_LVALUE_CAST );
}else{
CErr1( ERR_CANT_TAKE_ADDR_OF_RVALUE );
}
}
if( (op1->op.opr == OPR_CONVERT || op1->op.opr == OPR_CONVERT_PTR)
&& CompFlags.extensions_enabled ) {
op1 = LCastAdj( op1 );
}
isLValue = LValue( op1 );
if( isLValue ) {
op_flags volatile_flag;
volatile_flag = op1->op.flags & OPFLAG_VOLATILE;
if( opr != T_EQUAL && opr != T_ASSIGN_LAST ) {
if( opr == T_PLUS_EQUAL || opr == T_MINUS_EQUAL ) {
op1 = AddOp( op1, opr, op2 );
} else {
op1 = BinOp( op1, opr, op2 );
}
op1->op.flags |= volatile_flag;
return( op1 );
}
SetSymAssigned( op1 );
typ = TypeOf( op1 );
op2 = RValue( op2 );
op2 = BaseConv( typ, op2 );
ParmAsgnCheck( typ, op2, 0 );
if( opr == T_ASSIGN_LAST ) opr = T_EQUAL;
op1_class = ExprTypeClass( typ );
op2_class = ExprTypeClass( op2->expr_type );
if( op1_class != op2_class ) {
if( op1_class == PTR_FAR16 || op2_class == PTR_FAR16 ) { // if far16 pointer
op2 = ExprNode( NULL, OPR_CONVERT_PTR, op2 );
op2->op.oldptr_class = op2_class;
op2->op.newptr_class = op1_class;
} else {
op2 = ExprNode( NULL, OPR_CONVERT, op2 );
op2->op.result_type = typ;
}
op2->expr_type = typ;
}
op1 = ExprNode( op1, TokenToOperator( opr ), op2 );
op1->op.flags |= volatile_flag;
op1->expr_type = typ;
op1->op.result_type = typ;
} else {
FreeExprTree( op2 );
}
return( op1 );
}
void ChkConst( TREEPTR opnd )
{
if( opnd->op.opr != OPR_ERROR ) {
if( opnd->op.flags & OPFLAG_CONST ) {
CErr1( ERR_CANNOT_MODIFY_CONST );
}
}
}
TREEPTR IntOp( TREEPTR op1, TOKEN opr, TREEPTR op2 )
{
type_modifiers op1_type, op2_type, result_type;
if( op1->op.opr == OPR_ERROR ) {
FreeExprTree( op2 );
return( op1 );
}
if( op2->op.opr == OPR_ERROR ) {
FreeExprTree( op1 );
return( op2 );
}
op1 = RValue( op1 );
op2 = RValue( op2 );
op1_type = DataTypeOf( TypeOf( op1 )->decl_type );
op2_type = DataTypeOf( TypeOf( op2 )->decl_type );
if( op1_type == TYPE_VOID || op2_type == TYPE_VOID ) {
result_type = TYPE_VOID;
} else if( op1_type == TYPE_UNION || op2_type == TYPE_UNION ) {
result_type = ERR;
} else {
result_type = IntResult[ op1_type ][ op2_type ];
}
if( result_type == ERR ) {
CErr1( ERR_EXPR_MUST_BE_INTEGRAL );
result_type = INT;
}
op1 = Convert( op1, op1_type, result_type );
op2 = Convert( op2, op2_type, result_type );
op1 = ExprNode( op1, TokenToOperator( opr ), op2 );
if( result_type == ERR ) {
op1 = ErrorNode( op1 );
} else {
op1->expr_type = GetType( result_type );
op1->op.result_type = op1->expr_type;
}
return( op1 );
}
TREEPTR ShiftOp( TREEPTR op1, TOKEN opr, TREEPTR op2 )
{
DATA_TYPE op1_type, op2_type, result_type;
if( op1->op.opr == OPR_ERROR ) {
FreeExprTree( op2 );
return( op1 );
}
if( op2->op.opr == OPR_ERROR ) {
FreeExprTree( op1 );
return( op2 );
}
op1 = RValue( op1 );
op2 = RValue( op2 );
op1_type = DataTypeOf( TypeOf( op1 )->decl_type );
op2_type = DataTypeOf( TypeOf( op2 )->decl_type );
if( op1_type == TYPE_VOID || op2_type == TYPE_VOID ) {
result_type = TYPE_VOID;
} else {
if( op1_type <= TYPE_STRUCT ) {
result_type = ShiftResult[ op1_type ];
} else {
result_type = ERR;
}
if( result_type == ERR || op2_type > UL8 ) {
CErr1( ERR_EXPR_MUST_BE_INTEGRAL );
result_type = INT;
}
}
op1 = Convert( op1, op1_type, result_type );
op1 = ExprNode( op1, TokenToOperator( opr ), op2 );
if( result_type == ERR ) {
op1 = ErrorNode( op1 );
} else {
op1->expr_type = GetType( result_type );
op1->op.result_type = op1->expr_type;
}
return( op1 );
}
int FuncPtr( TYPEPTR typ )
{
while( typ->decl_type == TYPE_TYPEDEF ) typ = typ->object;
if( typ->decl_type != TYPE_POINTER ) return( 0 );
typ = typ->object;
while( typ->decl_type == TYPE_TYPEDEF ) typ = typ->object;
if( typ->decl_type != TYPE_FUNCTION ) return( 0 );
return( 1 );
}
#define NEAR_FAR_HUGE (FLAG_NEAR|FLAG_FAR|FLAG_HUGE|FLAG_FAR16)
TREEPTR CnvOp( TREEPTR opnd, TYPEPTR newtyp, int cast_op )
{
TYPEPTR typ;
enum conv_types cnv;
enum ops opr;
op_flags flags;
type_modifiers opnd_type;
if( opnd->op.opr == OPR_ERROR ) return( opnd );
while( newtyp->decl_type == TYPE_TYPEDEF ) newtyp = newtyp->object;
opr = opnd->op.opr;
if( newtyp->decl_type == TYPE_VOID ) { /* 26-oct-88 */
typ = TypeOf( opnd );
if( typ->decl_type == TYPE_VOID ) return( opnd );
}
flags = OPFLAG_NONE;
if( cast_op && CompFlags.extensions_enabled ) {
if( IsLValue( opnd ) ) {
flags |= OPFLAG_LVALUE_CAST;
}
}
opnd_type = opnd->expr_type->decl_type;
if( ! CompFlags.pre_processing ) opnd = RValue( opnd );
typ = TypeOf( opnd );
if( newtyp->decl_type > TYPE_POINTER ) {
if( newtyp->decl_type == TYPE_VOID ) {
opnd = ExprNode( 0, OPR_CONVERT, opnd );
opnd->expr_type = newtyp;
opnd->op.result_type = newtyp;
if( cast_op ) CompFlags.meaningless_stmt = 0; /* 21-jul-89 */
} else if( newtyp->decl_type == TYPE_ENUM ) {
if( typ->decl_type == TYPE_POINTER ) {
CWarn1( WARN_POINTER_TYPE_MISMATCH,
ERR_POINTER_TYPE_MISMATCH );
}
newtyp = newtyp->object; /* 02-feb-93 */
goto convert;
} else {
if( cast_op ) {
CErr1( ERR_MUST_BE_SCALAR_TYPE );
return( ErrorNode( opnd ) );
} else if( typ != newtyp ) { /* 16-aug-91, added cond */
CErr1( ERR_TYPE_MISMATCH );
return( ErrorNode( opnd ) );
}
}
} else if( typ->decl_type != TYPE_VOID ) {
convert: /* moved here 30-aug-89 */
cnv = CnvTable[ DataTypeOf( typ->decl_type ) ]
[ DataTypeOf( newtyp->decl_type ) ];
if( cnv == CER ) {
CErr1( ERR_INVALID_CONVERSION );
return( ErrorNode( opnd ) );
} else if( cnv != NIL ) {
if( cnv == P2P ) {
if( ( typ->u.p.decl_flags & NEAR_FAR_HUGE )
!= ( newtyp->u.p.decl_flags & NEAR_FAR_HUGE )
|| ( opnd_type == TYPE_ARRAY ) ) {
if( cast_op == 0 ) {
if( TypeSize(typ) > TypeSize(newtyp) ) {
CWarn1( WARN_POINTER_TRUNCATION,
ERR_POINTER_TRUNCATION );
}
if( (typ->u.p.decl_flags & FLAG_BASED) &&
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -