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 + -
显示快捷键?