analretn.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 234 行
C
234 行
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
* DESCRIBE IT HERE!
*
****************************************************************************/
#include "plusplus.h"
#include "cgfront.h"
#include "cast.h"
#include "errdefns.h"
#include "defarg.h"
#include "class.h"
static CNV_DIAG diagDefarg = // diagnosis for def. argument conversion
{ ERR_DEFARG_IMPOSSIBLE
, ERR_DEFARG_AMBIGUOUS
, ERR_CALL_WATCOM
, ERR_DEFARG_PRIVATE
, ERR_DEFARG_PROTECTED
};
static CNV_DIAG diagReturn = // diagnosis for return conversion
{ ERR_RETURN_IMPOSSIBLE
, ERR_RETURN_AMBIGUOUS
, ERR_CALL_WATCOM
, ERR_RETURN_PRIVATE
, ERR_RETURN_PROTECTED
};
static PTREE getReturnSym // MAKE NODE FOR RETURN SYMBOL
( void )
{
SYMBOL sym; // - return symbol
PTREE node; // - node for above
sym = SymFunctionReturn();
sym->flag |= SF_REFERENCED;
node = MakeNodeSymbol( sym );
return node;
}
static PTREE removeReturnNode // REMOVE RETURN NODE
( PTREE expr ) // - original expression
{
PTREE old; // - old expression
old = expr;
expr = old->u.subtree[1];
old->u.subtree[1] = NULL;
PTreeFreeSubtrees( old );
return expr;
}
static void checkAutoReturn( // CHECK IF AUTOMATIC BEING RETURNED
PTREE node, // - node to be checked
TYPE ret_type ) // - return type
{
TYPE func_ret; // - type of function return
SYMBOL func; // - function called
SYMBOL comped; // - function being compiled
PTREE expr; // - node for error
TYPE refed; // - NULL ==> not reference
comped = ScopeFunctionInProgress();
if( SymIsGenedFunc( comped ) ) {
return;
}
expr = node;
refed = TypeReference( ret_type );
for( ; ; ) {
node = NodeRemoveCastsCommas( node );
if( ( node->op == PT_SYMBOL )
&&( SymIsAutomatic( node->u.symcg.symbol ) ) ) {
if( NULL == refed ) {
PTreeWarnExpr( expr, WARN_RET_ADDR_OF_AUTO );
} else {
PTreeErrorExpr( expr, ERR_RET_AUTO_REF );
}
break;
} else if( NodeIsBinaryOp( node, CO_DOT )
|| NodeIsBinaryOp( node, CO_DOT_STAR ) ) {
node = PTreeOpLeft( node );
} else if( NodeIsUnaryOp( node, CO_ADDR_OF ) ) {
node = PTreeOpLeft( node );
} else if( NULL != refed ) {
if( NodeIsBinaryOp( node, CO_DTOR ) ) {
node = PTreeOpRight( node );
} else if( NodeIsBinaryOp( node, CO_CALL_EXEC ) ) {
node = PTreeOpLeft( PTreeOpLeft( node ) );
if( node->op == PT_SYMBOL ) {
func = node->u.symcg.symbol;
if( SymIsCtor( func ) ) {
PTreeErrorExpr( expr, ERR_RET_AUTO_REF );
} else {
func_ret = SymFuncReturnType( func );
if( NULL != StructType( func_ret ) ) {
PTreeErrorExpr( expr, ERR_RET_AUTO_REF );
}
}
}
break;
} else if( NodeIsBinaryOp( node, CO_CALL_EXEC_IND ) ) {
func_ret = TypeFunctionCalled( NodeFuncForCall( node )->type );
func_ret = func_ret->of;
if( NULL != StructType( func_ret ) ) {
PTreeErrorExpr( expr, ERR_RET_AUTO_REF );
}
break;
} else {
break;
}
} else {
break;
}
}
}
PTREE AnalyseReturnClassVal // RETURN CLASS VALUE
( PTREE expr ) // - expression for return
{
TYPE retn_type; // - return type
TYPE retn_class; // - class for return
PTREE tgt; // - target expression
CNV_DIAG* diag; // - diagnosis
retn_type = expr->u.subtree[0]->type;
retn_class = StructType( retn_type );
DbgVerify( retn_class != NULL, "AnalyseReturnClassVal -- not class" );
if( ClassCorrupted( retn_class ) ) {
PTreeErrorNode( expr );
} else if( TypeAbstract( retn_class ) ) {
PTreeErrorExprType( expr, ERR_CONVERT_TO_ABSTRACT_TYPE, retn_class );
ScopeNotePureFunctions( retn_class );
} else {
diag = DefargBeingCompiled() ? &diagDefarg : &diagReturn;
tgt = NodeFetchReference( getReturnSym() );
expr = removeReturnNode( expr );
expr = CopyClassRetnVal( expr, tgt, retn_type, diag );
if( expr->op != PT_ERROR ) {
if( NodeIsBinaryOp( expr, CO_DTOR ) ) {
PTREE node = expr->u.subtree[0];
if( SymFunctionReturn() == node->u.symcg.symbol ) {
PTreeFree( node );
node = expr;
expr = expr->u.subtree[1];
PTreeFree( node );
}
}
}
#if 0
// this is just so we can do some checking
expr = CastImplicit( expr
, retn_type
, CNV_EXPR
, DefargBeingCompiled()
? &diagDefarg : &diagReturn );
}
#endif
}
return expr;
}
PTREE AnalyseReturnSimpleVal // RETURN A SIMPLE VALUE
( PTREE expr ) // - expression for return
{
TYPE retn_type; // - return type
unsigned cnv_type; // - type of conversion
CNV_DIAG *diag; // - diagnosis to be used
retn_type = expr->u.subtree[0]->type;
if( DefargBeingCompiled() ) {
cnv_type = CNV_FUNC_DARG;
diag = &diagDefarg;
} else {
cnv_type = CNV_FUNC_RET;
diag = &diagReturn;
}
expr = CastImplicit( removeReturnNode( expr )
, retn_type
, cnv_type
, diag );
if( expr->op != PT_ERROR ) {
if( NULL != PointerTypeEquivalent( retn_type ) ) {
checkAutoReturn( expr, retn_type );
}
if( expr->op != PT_ERROR ) {
PTREE tgt = getReturnSym();
if( NULL == TypeReference( retn_type ) ) {
expr = NodeRvalue( expr );
expr = NodeAssign( tgt, expr );
if( NULL != MemberPtrType( retn_type ) ) {
PTREE new_expr = expr;
MembPtrAssign( &new_expr );
expr = new_expr;
}
} else {
expr = NodeAssignRef( tgt, expr );
}
}
}
return expr;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?