analnew.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 913 行 · 第 1/3 页
C
913 行
alist = ArgListTempAlloc( &default_args, count_placement );
ptlist = PtListAlloc( default_list, count_placement );
NodeBuildArgList( alist, ptlist, node, count_placement );
/* find the appropriate "operator new" or operator new[] */
sym = result_new->sym_name->name_syms;
ovret = FuncOverloadedDiag( &sym
, result_new
, sym
, alist
, ptlist
, &fnov_diag ) ;
if( ovret == FNOV_NONAMBIGUOUS ) {
if( ScopeCheckSymbol( result_new, sym ) ) {
PTreeErrorNode( node );
} else {
node = NodeMakeCall( sym, new_expr_type, node );
node = NodeConvertCallArgList( node
, alist->num_args
, sym->sym_type
, &node->u.subtree[1] );
if( node->op != PT_ERROR ) {
AddDefaultArgs( sym, node );
}
}
} else {
sym = result_new->sym_name->name_syms;
node = NodeMakeCall( sym, new_expr_type, node );
switch( ovret ) {
case FNOV_AMBIGUOUS:
CallDiagAmbiguous( node, ERR_NEW_OVERLOAD_AMBIGUOUS, &fnov_diag );
break;
case FNOV_NO_MATCH:
CallDiagNoMatch( node
, ERR_FUNCTION_NO_MATCH
, ERR_NEW_OVERLOAD_FAILURE
, NULL
, sym
, &fnov_diag
);
break;
DbgDefault( "buildNewCall: unexpected return from FuncOverloaded" );
}
}
FnovFreeDiag( &fnov_diag );
ScopeFreeResult( result_new );
ArgListTempFree( alist, count_placement );
PtListFree( ptlist, count_placement );
return node;
}
PTREE AnalyseNew( // ANALYSE A "NEW" OPERATOR (WITH OVERLOADING)
PTREE expr, // - "new" expression
TYPE type ) // - type of expression
{
unsigned count_placement; // - # placement arg.s
unsigned ctor_overload; // - result of ctor overload
unsigned num_args; // - number of args for delete operator
PTREE new_parms1; // - CO_NEW_PARMS1 node
PTREE new_parms2; // - CO_NEW_PARMS2 node
PTREE elem_size; // - constant for size of an element
PTREE node; // - new node
PTREE dup; // - duplicated node
PTREE placement; // - placement arguments
PTREE initial; // - initialization arguments
PTREE array_number; // - number of array arguments
TYPE base_type; // - base type of element
TYPE class_type; // - != NULL if base_type is a class
TYPE new_expr_type; // - final type of the new-expr
TYPE offset_type; // - type for offset computations
SYMBOL sym_ctor; // - constructor function
SYMBOL op_dlt; // - delete operator used to free new'ed store
SYMBOL addr_op_del; // - addressible operator delete
SEARCH_RESULT *result_dlt; // - search result for operator delete
CGOP cgop; // - type of new expression
TOKEN_LOCN err_locn; // - error location
struct {
unsigned needs_dtor : 1; // - class says DTOR is req'd (DTOR may be empty)
unsigned really_dtorable:1;//- class DTOR really req'd
unsigned needs_count:1; // - array new needs count in allocation
unsigned free_array_no :1;// - "array_number" needs to be freed
} flag;
/*
CO_NEW
/ \
PT_TYPE(type) CO_NEW_PARMS1
/ \
placement -> , CO_NEW_PARMS2
/ \ / \
, arg n nelem , <- new-init
/ \ (may be NULL) / \
, ... , arg n
\ / \
arg 1 , ...
\
arg 1
*/
if( ! TypeDefined( type ) ) {
PTreeErrorExpr( expr, ERR_CANT_NEW_UNDEFD );
return( expr );
}
PTreeExtractLocn( expr, &err_locn );
/* extract the components of the new-expression and free the CO_NEW* parts */
new_parms1 = expr->u.subtree[1];
placement = NodeReverseArgs( &count_placement, new_parms1->u.subtree[0] );
new_parms1->u.subtree[0] = NULL;
new_parms2 = new_parms1->u.subtree[1];
initial = new_parms2->u.subtree[1];
new_parms2->u.subtree[1] = NULL;
array_number = new_parms2->u.subtree[0];
new_parms2->u.subtree[0] = NULL;
cgop = expr->cgop;
NodeFreeDupedExpr( expr );
/* 'type', 'placement', 'array_number', and 'initial' are set now */
new_expr_type = figureOutNewType( &array_number, &type );
elem_size = NodeOffset( CgTypeSize( type ) );
offset_type = elem_size->type;
base_type = ArrayBaseType( type );
class_type = StructType( type );
//
// verify CTORING is ok
//
ctor_overload = checkNewCtor( class_type
, base_type
, &sym_ctor
, &initial
, &err_locn );
if( ctor_overload != CNV_OK ) {
NodeFreeDupedExpr( placement );
NodeFreeDupedExpr( elem_size );
NodeFreeDupedExpr( array_number );
NodeFreeDupedExpr( initial );
return( PTreeErrorNode( NULL ) );
}
//
// optimize away CTORing if possible
//
if( sym_ctor != NULL ) {
if( initial == NULL && ! TypeReallyDefCtorable( class_type ) ) {
sym_ctor = NULL;
}
}
flag.needs_count = FALSE;
flag.needs_dtor = FALSE;
flag.really_dtorable = FALSE;
flag.free_array_no = FALSE;
if( TypeRequiresDtoring( class_type ) ) {
flag.needs_dtor = TRUE;
// the structure of the allocation can't be influenced by 'really_dtorable'
// since the alloc and delete may not agree on 'really_dtorable'
// the flag is currently not used in the new but could be used to
// influence the choice of run-time routines for array news in the
// face of exceptions
//if( TypeReallyDtorable( class_type ) ) {
//flag.really_dtorable = TRUE;
//}
}
op_dlt = accessDelete( array_number == NULL ? CO_DELETE : CO_DELETE_ARRAY
, scopeLookup( class_type )
, &num_args
, &result_dlt );
addr_op_del = ClassFunMakeAddressable( op_dlt );
//
// compute size
//
if( array_number != NULL ) {
if( flag.needs_dtor || num_args == 2 ) {
flag.needs_count = TRUE;
}
array_number = NodeRvalue( array_number );
if( IntegralType( array_number->type ) == NULL ) {
PTreeErrorExpr( array_number, ERR_NEW_ARRAY_EXPRESSION );
ScopeFreeResult( result_dlt );
NodeFreeDupedExpr( placement );
NodeFreeDupedExpr( elem_size );
NodeFreeDupedExpr( array_number );
NodeFreeDupedExpr( initial );
return( PTreeErrorNode( NULL ) );
}
if( initial != NULL ) {
PTreeErrorExpr( initial, ERR_CANT_INIT_NEW_ARRAY );
ScopeFreeResult( result_dlt );
NodeFreeDupedExpr( placement );
NodeFreeDupedExpr( elem_size );
NodeFreeDupedExpr( array_number );
NodeFreeDupedExpr( initial );
return( PTreeErrorNode( NULL ) );
}
/* calculate "nelem * sizeof( elem )" */
dup = array_number;
if( sym_ctor != NULL || flag.needs_count ) {
array_number = NodeDupExpr( &dup );
flag.free_array_no = TRUE;
}
node = NodeBinary( CO_TIMES, dup, elem_size );
node->type = offset_type;
node = FoldBinary( node );
if( flag.needs_count ) {
node = NodeBinary( CO_PLUS, node, sizeOfUInt() );
node->type = offset_type;
node = FoldBinary( node );
}
} else {
node = elem_size;
}
//
// build call to appropriate operator new
//
node->locn = err_locn;
node = NodeArgument( placement, node );
++count_placement;
node = buildNewCall( node
, opNewSearchScope( class_type, cgop )
, new_expr_type
, count_placement
, &err_locn
, array_number == NULL ? CO_NEW : CO_NEW_ARRAY );
if( node->op == PT_ERROR ) {
ScopeFreeResult( result_dlt );
NodeFreeDupedExpr( node );
if( flag.free_array_no ) {
NodeFreeDupedExpr( array_number );
}
NodeFreeDupedExpr( initial );
return( PTreeErrorNode( NULL ) );
}
//
// CTOR the new'ed memory and set up ARRAY_STORAGE, if required
//
if( array_number != NULL ) {
if( sym_ctor != NULL ) {
unsigned rt_code; // - run-time function code
PTREE args; // - run-time call arguments
TYPE_SIG *sig; // - type signature for class
boolean errors; // - TRUE ==> errors
TYPE_SIG_ACCESS acc; // - rtn.s to be accessed
if( flag.needs_dtor ) {
acc = TSA_DTOR | TSA_DEFAULT_CTOR;
} else {
acc = TSA_DEFAULT_CTOR;
}
sig = TypeSigFind( acc, class_type, &err_locn, &errors );
if( errors ) {
ScopeFreeResult( result_dlt );
NodeFreeDupedExpr( node );
if( flag.free_array_no ) {
NodeFreeDupedExpr( array_number );
}
NodeFreeDupedExpr( initial );
return( PTreeErrorNode( NULL ) );
}
TypeSigReferenced( sig );
op_dlt = checkDeleteResult( op_dlt
, result_dlt
, &err_locn
, FALSE );
if( op_dlt == NULL ) {
NodeFreeDupedExpr( node );
if( flag.free_array_no ) {
NodeFreeDupedExpr( array_number );
}
NodeFreeDupedExpr( initial );
return( PTreeErrorNode( NULL ) );
}
if( num_args == 1 ) {
if( ScopeId( SymScope( op_dlt ) ) == SCOPE_FILE
&& addr_op_del == op_dlt ) {
if( flag.needs_count ) {
rt_code = RTF_CTAS_GS;
} else {
rt_code = RTF_CTAS_GM;
}
args = NULL;
} else {
if( flag.needs_count ) {
rt_code = RTF_CTAS_1S;
} else {
rt_code = RTF_CTAS_1M;
}
args = NodeArg( MakeNodeSymbol( addr_op_del ) );
args = PtdScopeCall( args, op_dlt );
}
} else {
DbgVerify( flag.needs_count
, "AnalyseNew -- flags mismatch" );
rt_code = RTF_CTAS_2S;
args = NodeArg( MakeNodeSymbol( addr_op_del ) );
args = PtdScopeCall( args, op_dlt );
}
args = NodeArgument( args, NodeTypeSig( sig ) );
args = NodeArgument( args, array_number );
args = NodeArgument( args, node );
node = RunTimeCall( args, new_expr_type, rt_code );
if( placement != NULL ) {
dup = node;
node = NodeDupExpr( &dup );
node = newCheckForNULL( dup, node );
}
} else {
ScopeFreeResult( result_dlt );
/* no constructor req'd */
if( flag.needs_count ) {
dup = node;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?