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