fnbody.c

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

C
2,160
字号
        case CS_DO:
        case CS_WHILE:
        case CS_SWITCH:
            return( curr );
        }
    }
    return( NULL );
}

static void parseBreakStmt( void )
{
    CSTACK *enclose;

    ensureLiveCode();
    enclose = findBreakable();
    if( enclose == NULL ) {
        CErr1( ERR_MISPLACED_BREAK );
    } else if( ! currFunction->dead_code ) {
        jumpFwdBlkLabel( &enclose->outside );
    }
    nextYYToken();
    mustRecog( T_SEMI_COLON );
}

static CSTACK *findContinuable( void )
{
    CSTACK *curr;

    Stack_forall( currFunction->control, curr ) {
        switch( curr->id ) {
          case CS_FOR:
          case CS_DO:
          case CS_WHILE:
            return( curr );
        }
    }
    return( NULL );
}

static void parseContinueStmt( void )
{
    CSTACK *enclose;

    ensureLiveCode();
    enclose = findContinuable();
    if( enclose == NULL ) {
        CErr1( ERR_MISPLACED_CONTINUE );
    } else {
        jumpFwdBlkLabel( &enclose->u.l.continue_loop );
    }
    nextYYToken();
    mustRecog( T_SEMI_COLON );
}

static void parseReturnStmt( SYMBOL func )
{
    PTREE expr;
    SYMBOL return_sym;
    SYMBOL return_operand;
    boolean expecting_return;
    boolean optimizing_return;

    ensureLiveCode();
    nextYYToken();
    return_sym = SymFunctionReturn();
    expecting_return = TRUE;
    optimizing_return = FALSE;
    if( return_sym == NULL
     || currFunction->is_ctor
     || currFunction->is_dtor ) {
        expecting_return = FALSE;
        currFunction->retn_opt = FALSE;
    }
    return_operand = NULL;
    if( CurToken == T_SEMI_COLON ) {
        if( expecting_return ) {
            CErr1( ERR_MISSING_RETURN_VALUE );
        }
    } else {
        currFunction->ret_reqd = TRUE;
        expr = safeParseExpr( T_SEMI_COLON );
        if( expr != NULL ) {
            if( expecting_return ) {
                if( expr->op == PT_ERROR ) {
                    PTreeFreeSubtrees( expr );
                } else {
                    if( currFunction->retn_opt ) {
                        // start bracketting
                        optimizing_return = TRUE;
                    }
                    emitCodeExpr( AnalyseReturnExpr( func, expr ) );
                    return_operand = return_sym;
                }
            } else {
                if( return_sym == NULL ) {
                    // see C++98 6.6.3 (3)
                    expr = AnalyseStmtExpr( expr );
                    if( ( expr->type != NULL ) && VoidType( expr->type ) ) {
                        emitCodeExpr( expr );
                        expr = NULL;
                    }
                }

                if( expr != NULL ) {
                    PTreeErrorExpr( expr, ERR_NOT_EXPECTING_RETURN_VALUE );
                    PTreeFreeSubtrees( expr );
                }
            }
        }
    }
    CgFrontReturnSymbol( return_operand );
    if( optimizing_return ) {
        // end bracketting
    }
    mustRecog( T_SEMI_COLON );
    FunctionBodyDeadCode();
}

boolean FnRetnOpt(              // TEST IF RETURN OPTIMIZATION ACTIVE
    void )
{
    return currFunction->retn_opt;
}

void FnRetnOptOff(              // TURN OFF RETURN OPTIMIZATION
    void )
{
    currFunction->retn_opt = FALSE;
}

void FnRetnOptSetSym(           // SET SYMBOL FOR RETURN OPTIMIZATION
    SYMBOL sym )                // - the symbol
{
    currFunction->retn_opt_sym = sym;
}

SYMBOL FnRetnOptSym(            // GET SYMBOL FOR RETURN OPTIMIZATION
    void )
{
    return currFunction->retn_opt_sym;
}


boolean FnRetnOptimizable(      // TEST IF SYMBOL COULD BE OPTIMIZED AWAY
    SYMBOL sym )                // - candidate symbol
{
    boolean retn;               // - return: FALSE ==> symbol never optimized

    if( currFunction->retn_opt
     && SymIsAutomatic( sym )
     && ! SymIsInMem( sym )
     && ! SymIsAnonymousMember( sym )
     && ! SymIsArgument( sym ) ) {
        SYMBOL func = ScopeFunctionInProgress();
        TYPE retn_type = FunctionDeclarationType( func->sym_type ) -> of;
        retn = TypesIdentical( retn_type, sym->sym_type );
    } else {
        retn = FALSE;
    }
    return retn;
}


static void parseGotoStmt( void )
{
    FNLABEL *label;
    LAB_REF *lab_ref;

    ensureLiveCode();
    nextYYToken();
    if( CurToken != T_ID ) {
        CErr1( ERR_EXPECTING_LABEL );
    } else {
        label = findLabel( NameCreateLen( Buffer, TokenLen ) );
        lab_ref = LabelAllocLabRef( label->destination.defn );
        if( label->defined ) {
            LabelGotoBwd( lab_ref );
        } else {
            LabelGotoFwd( lab_ref );
        }
        label->referenced = TRUE;
        doJUMP( IC_LABEL_GOTO, O_GOTO, label->destination.id );
    }
    if( CurToken != T_SEMI_COLON ) {
        nextYYToken();
    }
    mustRecog( T_SEMI_COLON );
}


static SYMBOL allocTryVar(      // CREATE TRY VARIABLE, IF REQ'D
    CSTACK *try_block )         // - try block
{
    SYMBOL try_var;             // - try variable for block

    try_var = try_block->next->try_var;
    if( try_var == NULL ) {
        try_var = SymCreate( MakeExpandableType( TYP_CHAR )
                           , SC_AUTO
                           , SF_REFERENCED | SF_ADDR_TAKEN | SF_CG_ADDR_TAKEN
                           , NameDummy()
                           , try_block->u.t.defn_scope );
        try_block->next->try_var = try_var;
    }
    return try_var;
}

static void parseTryBlock(      // PARSE TRY
    void )
{
    CSTACK *try_block;          // - control stack (changed to CS_CATCH later)

    ensureLiveCode();
    ExceptionsCheck();
    ScopeMarkVisibleAutosInMem();
    try_block = beginControl( CS_TRY );
    try_block->u.t.catch_err = FALSE;
    try_block->u.t.catches = NULL;
    try_block->u.t.catch_no = 0;
    try_block->u.t.defn_scope = GetCurrScope();
    try_block->u.t.try_locn = SrcPosnEmitCurrent();
    initBlkLabel( &try_block->outside );
    try_block->u.t.try_var = allocTryVar( try_block );
    CgFrontCodePtr( IC_TRY, try_block->u.t.try_var );
    CgSetTypeExact( GetBasicType( TYP_SINT ) );
    CgFrontSwitchBeg();
    LabelSwitchBeg();
    LabelSwitch( try_block->u.t.defn_scope );
    CgFrontSwitchDefault( try_block->u.t.defn_scope
                        , FALSE
                        , &try_block->u.t.try_locn );
    nextYYToken();
    mustRecog( T_LEFT_BRACE );
    startBlock();
    LabelBlkTry( &try_block->u.t.try_locn, try_block->u.t.try_var );
    FunctionHasRegistration();
}


static void completeTry(        // COMPLETE TRY BLOCK (CALL AFTER LAST CATCH)
    CSTACK *try_block )         // - block to be completed
{
    SrcPosnEmit( &try_block->u.t.try_locn );
    CgFrontSwitchEnd();
    SrcPosnEmitCurrent();
    dumpOutsideLabel( try_block );
    CgFrontLabfreeCs( 1 );
    RingCarveFree( carveFNCATCH, &(try_block->u.t.catches) );
    LabelTryComplete( try_block->u.t.try_var );
}


enum                            // ATTRIBUTES FOR CATCH TYPE
{   CATT_CLS   = 0x01           // - class or ref/ptr to class
,   CATT_PTR   = 0x02           // - pointer
,   CATT_PCPTR = 0x04           // - pointer has __based, __far16
,   CATT_FAR   = 0x08           // - pointer has __far in near model
,   CATT_REF   = 0x10           // - refererence
};

static TYPE getCatchTypeAttrs(  // GET CATCH TYPE ATTRIBUTES
    TYPE spectype,              // - type specified
    TYPE *a_tester,             // - type used to test equivalence
    uint_8 *a_attrs )           // - attributes for catch type
{
    TYPE sptype;                // - type specified (canonical format)
    TYPE type;                  // - type used to test attributes
    TYPE tester;                // - type used to test attributes
    uint_8 attrs;               // - attributes
    type_flag flags;            // - flags for pointed object

    sptype = TypeCanonicalThr( spectype );
    type = TypeReferenced( sptype );
    tester = StructType( type );
    if( tester == NULL ) {
        tester = TypePointedAt( type, &flags );
        if( tester == NULL ) {
            tester = type;
            attrs = 0;
        } else {
            type = tester;
            tester = StructType( tester );
            if( tester == NULL ) {
                tester = type;
                attrs = CATT_PTR;
            } else {
                attrs = CATT_PTR + CATT_CLS;
            }
            TypePointedAt( spectype, &flags );
            if( flags & ( TF1_BASED | TF1_FAR16 ) ) {
                attrs |= CATT_PCPTR;
            } else if( ( flags & TF1_FAR ) && ! IsBigData() ) {
                attrs |= CATT_FAR;
            }
        }
    } else {
        if( NULL == TypeReference( spectype ) ) {
            attrs = CATT_CLS;
        } else {
            attrs = CATT_CLS | CATT_REF;
        }
    }
    *a_attrs = attrs;
    *a_tester = tester;
    return sptype;
}

static void catchMsg( unsigned msg, FNCATCH *catch_entry )
{
    if( CErr1( msg ) & MS_PRINTED ) {
        InfMsgPtr( INF_PREVIOUS_CATCH, &catch_entry->defined );
    }
}

static boolean makeFNCATCH(     // MAKE CATCH ENTRY
    TYPE type,                  // - type of entry
    CSTACK *try_block,          // - try block for entry
    TOKEN_LOCN* cat_locn )      // - position of catch
{
    FNCATCH *catch_entry;       // - entry for catch
    FNCATCH *test;              // - used to validate types
    uint_8 new_attrs;           // - attributes: new
    uint_8 old_attrs;           // - attributes: old
    TYPE new_test;              // - test type: new
    TYPE old_test;              // - test type: old
    boolean errors;             // - indicates errors during typesig lookup
    TYPE_SIG_ACCESS access;     // - type of type-sig access
    boolean retn;               // - TRUE ==> no errors
    #define CATT_REF_PTR_CLS (CATT_CLS | CATT_PTR | CATT_REF)

    SetErrLoc( cat_locn );
    type = getCatchTypeAttrs( type, &new_test, &new_attrs );
    if( new_attrs & CATT_PCPTR ) {
        CErr1( ERR_CANNOT_USE_PCPTR );
        try_block->u.t.catch_err = TRUE;
        return FALSE;
    }
    if( new_attrs & CATT_FAR ) {
        CErr1( ERR_USE_FAR );
        try_block->u.t.catch_err = TRUE;
        return FALSE;
    }
    if( ( new_attrs & CATT_REF_PTR_CLS ) == CATT_CLS ) {
        if( ! TypeDefedNonAbstract( type
                                  , NULL
                                  , ERR_CATCH_ABSTRACT
                                  , ERR_CATCH_UNDEFED ) ) {
            try_block->u.t.catch_err = TRUE;
            return FALSE;
        }
        if( TypeRequiresDtoring( type ) ) {
            access = TSA_COPY_CTOR | TSA_DTOR;
        } else {
            access = TSA_COPY_CTOR;
        }
    } else {
        access = 0;
    }
    retn = TRUE;
    TypeSigFind( access, type, NULL, &errors );
    if( errors ) {
        try_block->u.t.catch_err = TRUE;
        retn = FALSE;
    }
    new_attrs &= ~CATT_REF;
    RingIterBeg( try_block->u.t.catches, test ) {
        if( test->type == NULL ) {
            catchMsg( ERR_CATCH_FOLLOWS_ELLIPSIS, test );
            try_block->u.t.catch_err = TRUE;
            retn = FALSE;
            break;
        }
        getCatchTypeAttrs( test->type, &old_test, &old_attrs );
        old_attrs &= ~CATT_REF;
        if( new_attrs == old_attrs ) {
            if( TypesIdentical( new_test, old_test ) ) {
                catchMsg( WARN_CATCH_PREVIOUS, test );
            } else if( CATT_PTR & new_attrs ) {
                if( old_test->id == TYP_VOID ) {
                    catchMsg( WARN_CATCH_PREVIOUS, test );
                }
            } else if( CATT_CLS & new_attrs ) {
                if( DERIVED_NO != TypeDerived( new_test, old_test ) ) {
                    catchMsg( WARN_CATCH_PREVIOUS, test );
                }
            }
        }
    } RingIterEnd( test )
    SetErrLoc( NULL );
    catch_entry = RingCarveAlloc( carveFNCATCH, &try_block->u.t.catches );
    catch_entry->type = type;
    catch_entry->defined = *cat_locn;
    CgFrontCodePtr( IC_CATCH_VAR, try_block->next->try_var );
    CgFrontCodePtr( IC_CATCH, type );
    return retn;

    #undef CATT_REF_PTR_CLS
}


static SYMBOL updateTryVar(     // UPDATE TRY VARIABLE
    CSTACK *try_block,          // - try block
    TYPE type )                 // - type for catch variable
{
    TYPE try_type;              // - type for try_variable
    target_size_t size;         // - size of catch variable
    SYMBOL try_var;             // - try variable

    try_var = try_block->next->try_var;
    try_type = TypedefModifierRemove( try_var->sym_type );
    size = CgMemorySize( type );
    if( size > try_type->u.a.array_size ) {
        try_type->u.a.array_size = size;
    }
    return try_var;
}


static SYMBOL makeCatchVar(     // CREATE A CATCH VARIABLE
    SYMBOL try_var,             // - aliased symbol
    DECL_INFO *info )           // - parse information
{
    SYMBOL catch_var;           // - new catch variable
    char* name;                 // - variable name

    if( info->id == NULL ) {
        name = NameDummy();
    } else {
        name = info->id->u.id.name;
    }
    catch_var = SymCreateCurrScope( info->type
                                  , SC_AUTO

⌨️ 快捷键说明

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