analclss.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,883 行 · 第 1/5 页
C
1,883 行
/****************************************************************************
*
* 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: Expression support for classes.
*
****************************************************************************/
/*
WATCOM C++ uses two constructors to accomplish the task of turning raw memory
into a valid object. They are called the "exact" constructor and the
"component" constructor. The "exact" constructor is the constructor used
by C++ programmers. The "component" constructor is used internally by the
C++ compiler to build up sub-objects for the final "exact" constructor.
The current implementation (V1.0) uses an extra bit flag parm to change its
behaviour from "exact" to "component".
Here are the tasks assigned to each type of constructor:
Exact constructor
=================
(EC1) initialize all virtual base pointers
(EC2) call component constructor for all virtual bases (may use ctor-init)
(EC3) execute my component constructor
Component constructor
=====================
(CC1) call direct non-virtual component constructors (may use ctor-init)
(CC2) construct members (may use ctor-init)
(CC3) - calculate ctor-disp for all known virtual bases
- initialize virtual function pointers
- execute user-specified constructor code
A constructor will return 'this' as its return value. The equivalent
sequence for destructors is: (notice everything is reversed!)
Exact destructor
================
(ED1) execute my component destructor
(ED2) call component destructor for all virtual bases (in reverse order)
(ED3) initialize all virtual base pointers (IGNORE for destructor)
Component destructor
====================
(CD1) - calculate ctor-disp for all known virtual bases
- initialize virtual function pointers
- execute user-specified destructor code
(CD2) destruct members (in reverse order)
(CD3) call direct non-virtual component destructors (in reverse order)
A destructor will return 'this' as its return value.
*/
#include "plusplus.h"
#include "cgfront.h"
#include "cgsegid.h"
#include "codegen.h"
#include "errdefns.h"
#include "name.h"
#include "fnbody.h"
#include "fnovload.h"
#include "ring.h"
#include "vstk.h"
#include "rtfuncod.h"
#include "class.h"
#include "defarg.h"
#include "ctexcept.h"
#include "context.h"
#include "cdopt.h"
#include "vfun.h"
#include "rtngen.h"
#include "objmodel.h"
#include "datadtor.h"
#include "rtti.h"
#include "calldiag.h"
typedef enum {
CI_EXACT = 0x01, // - constructing an exact copy of a class
CI_MEM_INIT = 0x02, // - init expression is not analysed yet
CI_INLINED = 0x04, // - init'ing inlined componentry
CI_VIRTUAL = 0x08, // - init'ing virtual base
CI_NULL = 0x00
} ctor_init;
typedef struct ctor_prologue ctor_prologue;
struct ctor_prologue {
PTREE member_init; // - list of data member initializations
PTREE base_init; // - list of base class initializations
SCOPE scope; // - 'C' in C( C & x )
CDOPT_ITER* optiter; // - next input ctor for CD optimization
PTREE comp_expr; // - initialization for component
TYPE comp_type; // - type for component
TYPE this_type; // - type of 'this' cache
CGFILE_INS sect_locn; // - location of IC_SECT_BEG
target_offset_t orig_offset;// - original offset of base/member
target_offset_t comp_offset;// - offset for component
ctor_init comp_options; // - options
unsigned cdopt :1; // - CD optimization active
unsigned dtor_reqd :1; // - TRUE ==> a DTOR was required (in section)
unsigned gen_copy :1; // - a compiler generated copy ctor
unsigned excepts :1; // - TRUE ==> exceptions enabled
unsigned obj_dtor :1; // - TRUE ==> object requires DTOR
unsigned have_cdopt:1; // - TRUE ==> have CDOPT component
unsigned done_cdopt:1; // - TRUE ==> processed all CDOPT components
};
typedef struct assign_prologue assign_prologue;
struct assign_prologue {
SCOPE start;
type_flag qualifier;
};
static type_flag cvFlags( // GET CV FLAGS FOR AN OPERAND
PTREE expr ) // - class (reference) operand
{
type_flag flags; // - flags for expression
TypeModFlags( TypeReferenced( expr->type ), &flags );
return flags & TF1_CV_MASK;
}
static SYMBOL getVBTableSym( SCOPE, target_offset_t );
static void returnThis( // RETURN "this" value
SYMBOL rtn ) // - routine being compiled
{
PTREE expr;
expr = PTreeThis();
if( ! SymIsDtor( rtn ) ) {
expr = PTreeUnary( CO_INDIRECT, expr );
}
expr = AnalyseReturnExpr( rtn , expr );
IcEmitExpr( expr );
CgFrontReturnSymbol( SymFunctionReturn() );
}
static PTREE addOffset( PTREE node, target_offset_t offset, TYPE type )
{
node = NodeBinary( CO_DOT, node, NodeOffset( offset ) );
node->type = type;
node->flags |= PTF_LVALUE;
return( node );
}
static PTREE addOffsetToThis( target_offset_t offset, TYPE type )
{
return( addOffset( NodeThis(), offset, type ) );
}
static PTREE nodeFirstParm( // GET FIRST PARM AS A NODE
void )
{
return NodeFetchReference( MakeNodeSymbol( ScopeFuncParm( 0 ) ) );
}
static PTREE addOffsetToFirstParm( target_offset_t offset, TYPE type )
{
PTREE expr;
expr = nodeFirstParm();
type = TypeMergeForMember( expr->type, type );
return addOffset( expr, offset, type );
}
static PTREE addVBOffsetToExpr( // ADD VB-OFFSET TO EXPRESSION
SCOPE scope, // - scope for vbase
BASE_CLASS *base, // - base class to be accessed
TYPE type, // - type of symbol
PTREE expr ) // - expression
{
CLASSINFO *info;
TYPE class_type;
class_type = ScopeClass( scope );
info = class_type->u.c.info;
type = TypeMergeForMember( expr->type, type );
expr = NodeConvertVirtualPtr( expr, type, info->vb_offset, base->vb_index );
expr->flags |= PTF_LVALUE;
return expr;
}
static PTREE addVBOffsetToFirstParm(
SCOPE scope,
BASE_CLASS *base,
TYPE type )
{
return addVBOffsetToExpr( scope, base, type, nodeFirstParm() );
}
static PTREE addVBOffsetToThis(
SCOPE scope,
BASE_CLASS *base,
TYPE type )
{
return addVBOffsetToExpr( scope, base, type, NodeThis() );
}
static PTREE accessSourceBase( SCOPE scope, BASE_CLASS *base )
{
TYPE type;
PTREE src;
type = base->type;
if( _IsVirtualBase( base ) ) {
src = addVBOffsetToFirstParm( scope, base, type );
} else {
src = addOffsetToFirstParm( base->delta, type );
}
return src;
}
static PTREE accessThisBase( SCOPE scope, BASE_CLASS *base )
{
TYPE type;
PTREE src;
type = base->type;
if( _IsVirtualBase( base ) ) {
src = addVBOffsetToThis( scope, base, type );
} else {
src = addOffsetToThis( base->delta, type );
}
return src;
}
static PTREE getRefSymFromFirstParm( SYMBOL sym, target_offset_t cl_offset )
{
TYPE sym_type;
PTREE first_parm_ref;
sym_type = sym->sym_type;
first_parm_ref = addOffsetToFirstParm( sym->u.offset + cl_offset
, sym_type );
sym_type = TypedefModifierRemove( sym_type );
if( sym_type->id == TYP_BITFIELD ) {
first_parm_ref = NodeUnaryCopy( CO_BITFLD_CONVERT, first_parm_ref );
first_parm_ref->type = sym_type->of;
}
return( first_parm_ref );
}
static PTREE setThisFromOffset( // SET "THIS" BACK BY AN OFFSET
PTREE expr, // - DTOR, CTOR call
TYPE type, // - type of component accessed by 'this'
TYPE this_type, // - type of 'this'
target_size_t offset ) // - the offset
{
PTREE offset_node;
if( expr == NULL ) {
/* no expr to adjust */
return( expr );
}
if( expr->op == PT_ERROR ) {
return expr;
}
if( expr->type->id == TYP_VOID ) {
/* no return value to adjust */
return( expr );
}
if( TypedefModifierRemove( type )->id == TYP_BITFIELD ) {
/* bit-fields do not have l-values that can be adjusted */
return( expr );
}
offset_node = NodeOffset( offset );
offset_node->cgop = CO_IGNORE;
expr = NodeBinary( CO_RESET_THIS, expr, offset_node );
expr->type = this_type;
return( expr );
}
static void initClassFunction( // START GENERATION OF CLASS FUNCTION
SYMBOL fun, // - symbol for function
FUNCTION_DATA *fn_data, // - function data storage
error_state_t *check, // - error state at beginning of func
boolean fun_is_copy ) // - function is a copy ctor or op=
{
TYPE fn_type; // - type for function
arg_list *alist; // - prototype for function
SYMBOL arg; // - function argument
CtxFunction( fun );
CErrCheckpoint( check );
SetCurrScope(SymScope( fun ));
ScopeBeginFunction( fun );
fn_type = FunctionDeclarationType( fun->sym_type );
if( fun_is_copy ) {
if( ! TypeHasNumArgs( fn_type, 0 ) ) {
/* copy constructor or op= */
alist = fn_type->u.f.args;
arg = AllocTypedSymbol( alist->type_list[0] );
arg->id = SC_AUTO;
arg->flag |= SF_REFERENCED;
// this special parm name is used by CtorPrologue to identify the
// special case of compiler-generated copy constructors
// (this is the only case in a constructor where copy ctors are used
// for all of the base classes instead of normal constructors)
arg = ScopeInsert( GetCurrScope(), arg, CppSpecialName(SPECIAL_COPY_ARG) );
}
}
FunctionBodyStartup( fun, fn_data, FUNC_NULL );
}
static void finiClassFunction( // COMPLETE GENERATION OF CLASS FUNCTION
SYMBOL fun, // - symbol for function
FUNCTION_DATA *fn_data, // - function data storage
error_state_t *check ) // - error state at beginning of func
{
FunctionBodyShutdown( fun, fn_data );
ScopeEnd( SCOPE_FUNCTION );
if( CErrOccurred( check ) ) {
CErr2p( ERR_DURING_GEN, fun );
}
}
static SEARCH_RESULT *classResult( // GET SEARCH RESULT FOR A TYPE
TYPE type, // - the type
SYMBOL *sym_ok, // - addr( good symbol )
char *name, // - name to search for
SCOPE access ) // - derived access scope
{
SCOPE scope; // - scope to search in
SEARCH_RESULT *result; // - result of lookup
SEARCH_RESULT *retn; // - NULL ==> no symbol
SYMBOL sym; // - current symbol
arg_list *alist; // - argument list for function
scope = TypeScope( type );
result = ScopeContainsMember( scope, name );
retn = NULL;
*sym_ok = NULL;
if( result != NULL ) {
RingIterBeg( result->sym_name->name_syms, sym ) {
alist = SymFuncArgList( sym );
if( ( alist != NULL )
&&( TypeHasNumArgs( sym->sym_type, 1 ) )
&&( type == ClassTypeForType( alist->type_list[0] ) ) ) {
*sym_ok = sym;
if( access != NULL ) {
ScopeFreeResult( result );
retn = ScopeFindBaseMember( scope, name );
} else {
retn = result;
}
break;
}
} RingIterEnd( sym )
if( retn == NULL ) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?