cexpr.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 2,035 行 · 第 1/5 页

C
2,035
字号
        NextToken();
    }
    /* if( SizeOfCount == 0 ) */ /* causes defined but not referenced */
    /* always turning it on can cause referenced but not assigned */
    /* for the case:  int i;  j = sizeof(i);  */
    sym.flags |= SYM_REFERENCED;
    if( sym_handle == 0 ) {
        if( CurToken == T_LEFT_PAREN ) {
            sym.stg_class = SC_FORWARD;     /* indicate forward decl */
            if( !CompFlags.extensions_enabled ) {
                /* Warn about unprototyped function here, but only in ISO mode.
                 * In extensions mode, forward declarations are OK. If no prototype
                 * is ever found, we'll warn later in csym.c.
                 */
                CWarn( WARN_ASSUMED_IMPORT, ERR_ASSUMED_IMPORT, sym.name );
            }
            sym_handle = SymAddL0( hash, &sym ); /* add symbol to level 0 */
            sym.flags |= SYM_FUNCTION;
            sym.sym_type = FuncNode( GetType( TYPE_INT ), 0, NULL );
        } else {
            sym.stg_class = SC_EXTERN;      /* indicate extern decl */
            CErr2p( ERR_UNDECLARED_SYM, sym.name );
            sym_handle = SymAdd( hash, &sym ); /* add sym to current level*/
            sym.sym_type = GetType( TYPE_INT );
        }
    }
    IncSymWeight( &sym );
    tree = VarLeaf( &sym, sym_handle );
    SymReplace( &sym, sym_handle );
    return( tree );
}


local void IncSymWeight( SYMPTR sym )
{
    static int  LoopWeights[] = { 1, 0x10, 0x100, 0x1000 };

    if( sym->level != 0 ) {
        if( !(sym->flags & SYM_FUNCTION) ) {
            if( LoopDepth > 3 ) {
                sym->u.var.offset = ~0u >> 1;
            } else {
                sym->u.var.offset += LoopWeights[ LoopDepth ];
            }
        }
    }
}

//-----------------------------CMATH------------------------------------

static bool IsStruct( TYPEPTR typ )
/*********************************/
{
    SKIP_TYPEDEFS( typ );
    if( typ->decl_type == TYPE_STRUCT  ||
        typ->decl_type == TYPE_UNION ) {
            return( TRUE );
    }
    return( FALSE );
}

int IsLValue( TREEPTR tree )
{
    switch( tree->op.opr ) {
    case OPR_ERROR:
    case OPR_ARROW:
    case OPR_INDEX:
    case OPR_PUSHADDR:
    case OPR_POINTS:
        return( 1 );
    case OPR_DOT:
        while( tree->op.opr == OPR_DOT )
            tree = tree->left;
        switch( tree->op.opr ) {
        case OPR_CALL:
        case OPR_QUESTION:
        case OPR_COMMA:
            // These are not lvalues
            break;
        default:
            return( 1 );
            break;
        }
        break;
    }
    return( 0 );
}

static bool IsCallValue( TREEPTR tree )
{
    int ret;

    while( tree->op.opr == OPR_DOT || tree->op.opr == OPR_INDEX ) {
        tree = tree->left;
    }
    if( tree->op.opr == OPR_CALL ) {
        ret = TRUE;
    } else {
        ret = FALSE;
    }
    return( ret );
}

// This RVALUE thing is backwards -mjc
local TREEPTR TakeRValue( TREEPTR tree, int void_ok )
{
    TYPEPTR             typ;
    sym_flags           symb_flags;
    type_modifiers      decl_flags;
    target_uint         value;
    SYM_ENTRY           sym;

    if( tree->op.opr == OPR_ERROR ) return( tree );     /* 16-mar-88*/
    if( CompFlags.pre_processing ) {            /* 07-feb-89 */
        if( tree->op.opr == OPR_PUSHFLOAT ) {
            CErr1( ERR_EXPR_MUST_BE_INTEGRAL );
            return( ErrorNode( tree ) );
        }
    }
    typ = tree->expr_type;
    SKIP_TYPEDEFS( typ );
    if( typ->decl_type == TYPE_VOID ) {
        if( ! void_ok ) {
            CErr1( ERR_EXPR_HAS_VOID_TYPE );
            return( ErrorNode( tree ) );
        }
    } else if( typ->decl_type == TYPE_ARRAY ) {

        if( tree->op.opr == OPR_PUSHSTRING ) {
            if( typ->object->decl_type == TYPE_USHORT ) { /* 02-aug-91 */
                typ = PtrNode( typ->object, FLAG_NONE, SEG_DATA );
            } else {
                StringArrayType = typ;
                typ = StringType;
            }
            tree->expr_type = typ;
        } else {

            decl_flags = FlagOps( tree->op.flags );
            if( tree->op.opr == OPR_PUSHADDR ) {
                SymGet( &sym, tree->op.sym_handle );
                symb_flags = sym.flags;
                sym.flags |= SYM_REFERENCED | SYM_ASSIGNED;
                if( symb_flags != sym.flags ) {
                    SymReplace( &sym, tree->op.sym_handle );
                }
            }
            if( IsCallValue( tree ) ) {
                CErr1( ERR_CANT_TAKE_ADDR_OF_RVALUE );
            }
            tree = ExprNode( NULL, OPR_ADDROF, tree );
            tree->expr_type = PtrNode( typ->object, decl_flags, SEG_DATA );
        }
    } else if( typ->decl_type == TYPE_FUNCTION ) {

        symb_flags = FLAG_NONE;
        if( tree->op.opr == OPR_PUSHADDR ) {
            SymGet( &sym, tree->op.sym_handle );
            decl_flags = sym.attrib;
            symb_flags = sym.flags;
            sym.flags |= SYM_REFERENCED | SYM_ADDR_TAKEN;
            if( symb_flags != sym.flags ) {
                    SymReplace( &sym, tree->op.sym_handle );
            }
        } else if( tree->op.opr == OPR_POINTS ) {
            decl_flags = tree->op.result_type->u.p.decl_flags;
        }
        tree = ExprNode( NULL, OPR_ADDROF, tree );
        tree->expr_type = PtrNode( typ, decl_flags, 0 );
    } else if( TypeSize( typ ) == 0 ) {
        SetDiagType1( typ );
        CErr1( ERR_INCOMPLETE_EXPR_TYPE );
        SetDiagPop();
        return( ErrorNode( tree ) );
    } else {
        if( SizeOfCount == 0 ) {                        /* 05-jan-89 */
            if( tree->op.flags & OPFLAG_VOLATILE ) {    /* 02-nov-91 */
                CompFlags.useful_side_effect = 1;
            }
        }
        if( tree->op.opr == OPR_PUSHSYM || tree->op.opr == OPR_PUSHADDR ) {
            SymGet( &sym, tree->op.sym_handle );
            symb_flags = sym.flags;
            sym.flags |= SYM_REFERENCED;                /* 07-jun-89 */
            if( CompFlags.label_dropped == 0  &&  SizeOfCount == 0 ) {
                if( sym.level != 0      &&
                    sym.stg_class != SC_STATIC &&       /* 15-feb-88 */
                    sym.stg_class != SC_EXTERN ) {
                    if( !(sym.flags & SYM_ASSIGNED) ) {
                      /* turn on flag so msg only comes out once per sym */
                        sym.flags |= SYM_ASSIGNED;
                        CWarn( WARN_SYM_NOT_ASSIGNED,
                                ERR_SYM_NOT_ASSIGNED,
                                SymName( &sym, tree->op.sym_handle ) );
                    }
                }
            }
            if( symb_flags != sym.flags ) {
                SymReplace( &sym, tree->op.sym_handle );
            }
        }
    }
    switch( tree->op.opr ) {
    case OPR_PUSHADDR:
        tree->op.opr = OPR_PUSHSYM;
        break;
    case OPR_QUESTION:
    case OPR_COMMA:
    case OPR_EQUALS:
        if( IsStruct( tree->expr_type ) ) {
            tree->op.flags |= OPFLAG_RVALUE;
        }
        break;
    case OPR_DOT:                       // sym.field
    case OPR_ARROW:                     // ptr->field
    case OPR_INDEX:                     // array[index]
        tree->op.flags |= OPFLAG_RVALUE;
        break;
    case OPR_CALL:                      // func()
        tree->op.flags |= OPFLAG_RVALUE;
        if( tree->left->op.opr == OPR_FUNCNAME ) {
            SymGet( &sym, tree->left->op.sym_handle );
            if( sym.stg_class == SC_FORWARD && !(sym.flags & SYM_TYPE_GIVEN) ) {
                 sym.flags |= SYM_TYPE_GIVEN;
                 SymReplace( &sym, tree->left->op.sym_handle );
            }
        }
        break;
    case OPR_POINTS:
        if( tree->left->op.opr == OPR_PUSHSTRING ) {    // *"abc"
            STRING_LITERAL      *string;

            string = tree->left->op.string_handle;
            value = string->literal[0];
            typ = tree->left->expr_type;
            if( typ->object->decl_type == TYPE_USHORT ) {  /* 24-jul-92 */
                value = (string->literal[1] << 8) | value;
            }
            FreeExprTree( tree );
            tree = IntLeaf( value );
        } else {
            tree->op.flags |= OPFLAG_RVALUE;
        }
        break;
    }
    return( tree );
}


TREEPTR VoidRValue( TREEPTR tree )
{
    tree =  TakeRValue( tree, 1 );
    return( tree );
}

TREEPTR RValue( TREEPTR tree )
{
    tree =  TakeRValue( tree, 0 );
    return( tree );
}

//-----------------------------COPS------------------------------------
static TREEPTR AddrOp( TREEPTR tree )
{
    TYPEPTR         typ;
    TREEPTR         leaf;
    type_modifiers  modifiers;
    int             segid;
    SYM_HANDLE      based_sym;
    SYM_ENTRY       sym;

    if( tree->op.opr == OPR_ERROR )  return( tree );
    typ = tree->expr_type;
    if( typ->decl_type == TYPE_FIELD || typ->decl_type == TYPE_UFIELD ) {
        CErr1( ERR_CANT_TAKE_ADDR_OF_BIT_FIELD );
        return( ErrorNode( tree ) );
    } else if( typ->decl_type == TYPE_VOID ) {
        CErr1( ERR_CANT_TAKE_ADDR_OF_RVALUE );
        return( ErrorNode( tree ) );
    }
    if( tree->op.flags & OPFLAG_LVALUE_CAST ) {     /* 18-aug-95 */
        if( CompFlags.extensions_enabled ) {
            tree->op.flags &= ~(OPFLAG_LVALUE_CAST | OPFLAG_RVALUE);
            CWarn1( WARN_LVALUE_CAST, ERR_LVALUE_CAST );
        } else {
            CErr1( ERR_CANT_TAKE_ADDR_OF_RVALUE );
            return( ErrorNode( tree ) );
        }
    }
    if( (tree->op.opr == OPR_CONVERT || tree->op.opr == OPR_CONVERT_PTR)
      && CompFlags.extensions_enabled ) {
        tree = LCastAdj( tree );
    }
    leaf = tree;
    if( tree->op.opr == OPR_DOT ) {
        if( tree->left->op.opr == OPR_PUSHADDR ) {
            leaf = tree->left;
        }
    } else if( tree->op.opr == OPR_ARROW ) {
        // checking for offsetof macro construct
        // #define offsetof(typ,field) (size_t)&(((typ*)0)->field)
        if( tree->left->op.opr == OPR_PUSHINT ) {
            leaf = tree->left;
            leaf->op.ulong_value += tree->right->op.ulong_value;
            tree->left = NULL;
            FreeExprTree( tree );
            leaf->expr_type = PtrNode( typ, FLAG_NONE, SEG_DATA );
            return( leaf );
        }
    }
    based_sym = 0;
    modifiers  = FLAG_NONE;
    segid = SEG_DATA;
    if( leaf->op.opr == OPR_PUSHADDR ) {
        SymGet( &sym, leaf->op.sym_handle );
        if( sym.stg_class == SC_REGISTER ) {
            CErr1( ERR_CANT_TAKE_ADDR_OF_REGISTER );
        }
        if( sym.level != 0 ) {
            sym.flags |= SYM_ASSIGNED;
        }
        sym.flags |= SYM_ADDR_TAKEN | SYM_REFERENCED;
        SymReplace( &sym, leaf->op.sym_handle );
    }
    if( tree->op.opr == OPR_PUSHADDR ) {
        SymGet( &sym, leaf->op.sym_handle );
        modifiers = sym.attrib;
        if( sym.stg_class == SC_AUTO ) {
            segid = SEG_STACK;
            CompFlags.addr_of_auto_taken = 1;           /* 23-oct-91 */
            if( TargetSwitches & FLOATING_SS ) {        /* 05-oct-88 */
                modifiers |= FLAG_FAR;
            }
        }
        typ = PtrNode( typ, modifiers & PTR_FLAGS, segid );
    } else if( tree->op.opr == OPR_POINTS ) {
        typ = tree->op.result_type;
    } else {
        modifiers = FlagOps( tree->op.flags );
        typ = PtrNode( typ, modifiers, SEG_DATA );
    }
    if( IsLValue( tree ) ) {
        tree = ExprNode( NULL, OPR_ADDROF, tree );
    } else {
        CErr1( ERR_CANT_TAKE_ADDR_OF_RVALUE );
        return( ErrorNode( tree ) );
    }
    tree->expr_type = typ;
    return( tree );
}

static TREEPTR FarPtrCvt( SYMPTR sym, SYM_HANDLE sym_handle )
{
    TYPEPTR         typ;
    TREEPTR         tree;

    typ = sym->sym_type;
    SKIP_TYPEDEFS( typ );
    if( typ->decl_type == TYPE_POINTER ) {
        if( typ->u.p.decl_flags & FLAG_FAR ) {
            tree = VarLeaf( sym, sym_handle );
            tree->op.opr = OPR_PUSHSYM;
        } else if( typ->u.p.decl_flags & FLAG_BASED ) {
            tree = VarLeaf( sym, sym_handle );
            tree->op.opr = OPR_PUSHSYM;
            tree = BasedPtrNode( typ, tree );
        } else {
            tree = VarLeaf( sym, sym_handle );
            tree->op.opr = OPR_PUSHSYM;
            tree = ExprNode( NULL, OPR_CONVERT, tree );
            tree->expr_type = typ;
            tree->op.result_type = PtrNode( typ->object, FLAG_FAR, 0 );
        }
    }
    return( tree );
}

static TREEPTR MakeFarOp( TREEPTR based_sym, TREEPTR tree )
{
    TYPEPTR     typ;

    typ = tree->expr_type;
    SKIP_TYPEDEFS( typ );
    typ = PtrNode( typ->object, FLAG_FAR, 0 );
    tree = ExprNode( based_sym, OPR_FARPTR, tree );
    tree->expr_type = typ;
    return( tree );
}

TREEPTR BasedPtrNode( TYPEPTR ptrtyp, TREEPTR tree )
{
    TREEPTR     based_sym;
    SYM_HANDLE  sym_handle;
    SYMPTR      sym;
    int         segid;

    sym_handle = ptrtyp->u.p.based_sym;
    segid =  ptrtyp->u.p.segment;
    switch( ptrtyp->u.p.based_kind ) {
    case BASED_VOID:          //__based( void )       segment:>offset base op
        break;
    case BASED_NONE:
        break;
    case BASED_SELFSEG:       //__based( (__segment) __self ) use seg of self
        tree->op.flags &= ~OPFLAG_RVALUE;
        based_sym = ExprNode( tree, OPR_DUPE, NULL );
        based_sym->op.flags |= OPFLAG_RVALUE;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?