analnew.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 913 行 · 第 1/3 页
C
913 行
node = NodeDupExpr( &dup );
expr = setupArrayStorage( dup, new_expr_type, array_number );
node = newCheckForNULL( node, expr );
}
}
} else {
ScopeFreeResult( result_dlt );
if( initial != NULL || sym_ctor != NULL ) {
dup = node;
node = NodeDupExpr( &dup );
#if 0
dup->type = type;
dup->flags |= PTF_LVALUE;
#else
dup = NodeConvertFlags( type, dup, PTF_LVALUE );
#endif
if( sym_ctor != NULL && placement == NULL ) {
dup = PtdNewAlloc( dup );
}
expr = EffectCtor( initial
, sym_ctor
, base_type
, dup
, &err_locn
, EFFECT_EXACT | EFFECT_VALUE_THIS );
if( expr->op == PT_ERROR ) {
NodeFreeDupedExpr( node );
node = expr;
} else {
if( sym_ctor != NULL && placement == NULL ) {
FunctionHasRegistration();
expr = PtdNewCtor( expr, class_type );
}
expr = NodeConvert( new_expr_type, expr );
node = newCheckForNULL( node, expr );
}
}
}
PTreeSetLocn( node, &err_locn );
return( node );
}
static PTREE deleteCheckForNULL( PTREE value, PTREE t_expr )
{
PTREE b_expr;
PTREE f_expr;
b_expr = NodeCompareToZero( value );
f_expr = NodeOffset( 0 );
return( NodeTestExpr( b_expr, t_expr, f_expr ) );
}
static PTREE setDeleteType( PTREE expr, TOKEN_LOCN *locn )
{
expr = NodeConvertFlags( GetBasicType( TYP_VOID )
, expr
, PTF_MEANINGFUL | PTF_SIDE_EFF );
PTreeSetLocn( expr, locn );
return( expr );
}
PTREE AnalyseDelete( // ANALYSE DELETE OPERATOR
PTREE expr, // - delete expression
boolean in_dtor ) // - TRUE ==> call from inside DTOR
{
CGOP oper; // - operator (original)
CGOP del_op; // - delete operator class
TYPE type; // - type of expression
TYPE ptr_type; // - pointer part of type
TYPE pted; // - type pointed at
TYPE cltype; // - class type pointed at
TYPE offset_type; // - type of size to pass to op del()
PTREE data; // - data to be deleted
PTREE dup; // - duplicate of pointer value
PTREE arg; // - temporary arg
PTREE args; // - args for delete
SCOPE class_scope; // - scope of class type
SCOPE opdel_scope; // - scope to search op del for
SYMBOL sym; // - symbol for delete routine
CLASSINFO *info; // - info part of delete type
TOKEN_LOCN err_locn; // - error location
unsigned dtor_code; // - code for DTOR routine
unsigned num_args; // - # of args for "op delete"
struct {
unsigned test_null:1; // - TRUE ==> test for 0 address
unsigned array_delete:1; // - TRUE ==> delete[]
unsigned inside_dtor:1; // - TRUE ==> delete gening in DTOR
unsigned num_in_alloc:1; // - TRUE ==> number elements is in allocation
unsigned really_dtorable:1;//- TRUE ==> non-trivial destructor req'd
unsigned adjust_for_num:1;// - TRUE ==> subtract sizeof(int) from ptr
} flag;
flag.inside_dtor = in_dtor;
oper = expr->cgop;
flag.array_delete = ( oper == CO_DELETE_ARRAY || oper == CO_DELETE_G_ARRAY );
data = expr->u.subtree[0];
PTreeExtractLocn( expr, &err_locn );
PTreeFree( expr );
data = NodeRvalue( data );
type = data->type;
ptr_type = PointerType( type );
if( ptr_type == NULL ) {
PTreeErrorExpr( data, ERR_DLT_NOT_PTR_TO_DATA );
return( data );
}
pted = ptr_type->of;
if( TypeIsConst( pted ) ) {
// 5.3.5 para 4 note
PTreeErrorExpr( data, WARN_DLT_PTR_TO_CONST );
}
if( TypeTruncByMemModel( pted ) ) {
PTreeErrorExpr( data, ERR_DLT_OBJ_MEM_MODEL );
return( data );
}
del_op = flag.array_delete ? CO_DELETE_ARRAY : CO_DELETE;
flag.num_in_alloc = FALSE;
pted = ArrayBaseType( pted );
cltype = StructType( pted );
if( cltype == NULL ) {
/* simple type */
if( FunctionDeclarationType( pted ) != NULL ) {
PTreeErrorExpr( data, ERR_DLT_PTR_TO_FUNCTION );
return( data );
}
opdel_scope = GetFileScope();
} else {
if( ! TypeDefined( cltype ) ) {
// 5.3.5 para 5 can delete undef'd class ptr
PTreeErrorExpr( data, WARN_CANT_DEL_UNDEFD );
}
info = cltype->u.c.info;
class_scope = TypeScope( cltype );
if( info->needs_dtor && ! flag.inside_dtor ) {
/* class type needs a destructor */
if( !info->needs_vdtor && ScopeHasVirtualFunctions( class_scope ) ) {
/* possible problem: class has vfns but a non-virtual dtor */
PTreeWarnExpr( data, WARN_VIRTUAL_DTOR_DELETE );
}
}
opdel_scope = class_scope;
switch( oper ) {
case CO_DELETE_G_ARRAY:
// find out what the op new side assumed
accessDelete( del_op, opdel_scope, &num_args, NULL );
if( num_args == 2 ) {
flag.num_in_alloc = TRUE;
}
/* fall through */
case CO_DELETE_G:
opdel_scope = GetFileScope();
break;
}
}
sym = checkDeleteAccess( del_op, opdel_scope, &num_args, &err_locn, flag.inside_dtor );
if( sym == NULL ) {
PTreeErrorNode( data );
return( data );
}
flag.test_null = FALSE;
if( cltype == NULL ) {
// delete a simple type; call op del() or op del []()
args = NodeArgument( NULL, data );
expr = NodeMakeCall( sym, GetBasicType( TYP_VOID ), args );
} else {
if( ! flag.inside_dtor && info->needs_vdtor ) {
// call virtual dtor
if( flag.array_delete ) {
dtor_code = DTOR_DELETE_VECTOR;
} else {
dtor_code = DTOR_DELETE_THIS;
}
flag.test_null = TRUE;
dup = data;
data = NodeDupExpr( &dup );
expr = AnalyseDtorCall( cltype, data, dtor_code );
} else {
target_size_t elem_size; // - size of an element
// cases:
// 1 - simple delete
// 2 - simple delete (needs dtor)
// 3 - array delete
// 4 - array delete (needs dtor)
// 5 - simple delete (inside dtor)
// 6 - array delete (inside dtor)
elem_size = CgMemorySize( pted );
if( ! ( flag.inside_dtor && oper == CO_DELETE ) && info->needs_dtor ) {
// class needs a dtor
// handle cases: 2, 4, 6
flag.really_dtorable = TypeReallyDtorable( cltype );
if( !flag.inside_dtor && !flag.really_dtorable ) {
// no dtor to call but check access anyway
// call to delete is done later in this code
// optimizes cases: 2, 4
ClassAccessDtor( cltype );
if( flag.array_delete ) {
flag.test_null = TRUE;
dup = data;
data = NodeDupExpr( &dup );
expr = NodeBinary( CO_MINUS, data, sizeOfUInt() );
expr->type = expr->u.subtree[0]->type;
} else {
expr = data;
}
} else if( flag.array_delete ) {
// handle cases: 4, 6
boolean errors; // - errors accessing DTOR
TYPE_SIG* sig; // - class type signature
sig = TypeSigFind( TSA_DTOR, cltype, &err_locn, &errors );
if( !errors ) {
if( num_args == 2 ) {
data = PtdDltDtorSize( data, elem_size );
}
data = PtdDltDtorArr( data, sym );
TypeSigReferenced( sig );
arg = NodeTypeSig( sig );
args = NodeArguments( arg, data, NULL );
expr = RunTimeCall( args, type, RTF_DTOR_AR_STORE );
expr = PtdDltDtorEnd( expr );
} else {
expr = data;
}
} else {
// handle case: 2
flag.test_null = TRUE;
dup = data;
data = NodeDupExpr( &dup );
if( num_args == 2 ) {
data = PtdDltDtorSize( data, elem_size );
}
data = PtdDltDtorElm( data, sym );
dtor_code = DTOR_NULL;
expr = AnalyseDtorCall( cltype, data, dtor_code );
expr = PtdDltDtorEnd( expr );
}
} else {
// no dtor call required
// handle cases: 1, 3, 5
if( flag.array_delete ) {
flag.adjust_for_num = FALSE;
if( num_args == 2 ) {
flag.adjust_for_num = TRUE;
} else if( flag.inside_dtor && oper == CO_DELETE_ARRAY ) {
flag.adjust_for_num = TRUE;
} else if( flag.num_in_alloc ) {
flag.adjust_for_num = TRUE;
}
if( flag.adjust_for_num ) {
flag.test_null = TRUE;
dup = data;
data = NodeDupExpr( &dup );
expr = NodeBinary( CO_MINUS, data, sizeOfUInt() );
expr->type = expr->u.subtree[0]->type;
} else {
expr = data;
}
} else {
expr = data;
}
}
if( num_args == 2 ) {
args = NodeOffset( elem_size );
if( flag.array_delete ) {
PTREE dup2;
// 'expr' must already be adjusted down by sizeof(unsigned)
dup2 = expr;
expr = NodeDupExpr( &dup2 );
expr = NodeConvert( MakeReferenceTo( GetBasicType( TYP_UINT ) )
, expr );
args = NodeBinary( CO_TIMES, NodeRvalue( expr ), args );
offset_type = args->u.subtree[1]->type;
args->type = offset_type;
args = NodeBinary( CO_PLUS, args, sizeOfUInt() );
args->type = offset_type;
expr = dup2;
if( ! flag.test_null ) {
flag.test_null = TRUE;
dup = expr;
expr = NodeDupExpr( &dup );
}
}
} else {
args = NULL;
}
if( args != NULL ) {
args = NodeArg( args );
}
args = NodeArgument( args, expr );
expr = NodeMakeCall( sym, GetBasicType( TYP_VOID ), args );
}
}
if( flag.test_null ) {
// 'dup' must be setup with a duplicate of the ptr expr
expr = deleteCheckForNULL( dup, expr );
}
return setDeleteType( expr, &err_locn );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?