analctor.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 676 行 · 第 1/2 页

C
676
字号
//   list
//      - the ctor SYMBOL is found
//
// - the initializer list is converted to a parse tree which can be used
//   by EffectCtor
//
// - an error can be detected by examining the returned initializer list to
//   see if it starts with a PT_ERROR node
//
static CNV_RETN analyseTypeCtorDiag( // ANALYSE CONSTRUCTOR FOR A TYPE
    SCOPE scope,                // - start scope for component ctors (NULLable)
    TYPE type,                  // - type for CTOR
    unsigned conversion,        // - type of conversion reqd
    SYMBOL *ctor,               // - ctor to be filled in
    PTREE *initial,             // - initialization arguments (modified)
    FNOV_DIAG *fnov_diag )      // - diagnosis information
{
    PTREE expr;                 // - original args
    TYPE base_type;             // - base type
    CNV_RETN retn;              // - return: CNV_...

    *ctor = NULL;
    expr = *initial;
    base_type = TypedefModifierRemoveOnly( type );
    switch( base_type->id ) {
      default :
        retn = CNV_IMPOSSIBLE;
        break;
      case TYP_ERROR:
        /* we've already diagnosed something somewhere */
        retn = CNV_ERR;
        break;
      case TYP_BITFIELD :
        return analyseTypeCtorDiag( scope
                                  , base_type->of
                                  , conversion
                                  , ctor
                                  , initial
                                  , fnov_diag );
        break;
      case TYP_FUNCTION :
      case TYP_VOID :
        if( NULL == *initial ) {
            retn = CNV_IMPOSSIBLE;
            break;
        }
        // drops thru
      case TYP_BOOL :
      case TYP_CHAR :
      case TYP_SCHAR :
      case TYP_UCHAR :
      case TYP_WCHAR :
      case TYP_SSHORT :
      case TYP_USHORT :
      case TYP_SINT :
      case TYP_UINT :
      case TYP_SLONG :
      case TYP_ULONG :
      case TYP_SLONG64 :
      case TYP_ULONG64 :
      case TYP_FLOAT :
      case TYP_DOUBLE :
      case TYP_LONG_DOUBLE :
      case TYP_ENUM :
      case TYP_POINTER :
      case TYP_MEMBER_POINTER :
        retn = single_arg( initial );
        if( retn == CNV_ERR ) break;
        if( *initial == NULL ) break;
        *initial = CastImplicit( *initial, base_type, CNV_INIT, &diagCtor );
        if( PT_ERROR == (*initial)->op ) {
            retn = CNV_ERR;
        } else {
            retn = CNV_OK;
        }
        break;
      case TYP_CLASS :
        retn = analyseCtorClassDiag( base_type, scope, ctor, expr, initial, fnov_diag );
        break;
      case TYP_ARRAY :
        if( expr != NULL ) {
            PTreeErrorExpr( expr, ERR_CANT_INIT_NEW_ARRAY );
            retn = CNV_IMPOSSIBLE;
        } else {
            retn = AnalyseCtorDiag( ArrayBaseType( type ), ctor, initial, NULL );
        }
        break;
    }
    return retn;
}

CNV_RETN AnalyseTypeCtor(       // ANALYSE CONSTRUCTOR FOR A TYPE
    SCOPE scope,                // - start scope for component ctors (NULLable)
    TYPE type,                  // - type for CTOR
    unsigned conversion,        // - type of conversion reqd
    SYMBOL *ctor,               // - ctor to be filled in
    PTREE *initial )            // - initialization arguments (modified)
{
    return analyseTypeCtorDiag( scope
                              , type
                              , conversion
                              , ctor
                              , initial
                              , NULL );
}


CNV_RETN AnalyseCtorDiag(       // ANALYSE CONSTRUCTOR
    TYPE type,                  // - type for CTOR
    SYMBOL *ctor,               // - ctor to be filled in
    PTREE *initial,             // - initialization arguments (modified)
    FNOV_DIAG *fnov_diag ) // Don't know how to implement LMW
{
    TYPE class_type;
    PTREE expr;

    class_type = StructType( type );
    fnov_diag = FnovInitDiag( fnov_diag );
    if( class_type != NULL ) {
        *ctor = NULL;
        expr = *initial;
        if( ! TypeDefedNonAbstract( class_type
                                  , expr
                                  , ERR_CONSTRUCT_AN_ABSTRACT_TYPE
                                  , ERR_CONSTRUCT_AN_UNDEFD_TYPE ) ) {
            return( CNV_ERR );
        }
    }
    return analyseTypeCtorDiag( NULL
                              , type
                              , CNV_CAST
                              , ctor
                              , initial
                              , fnov_diag );
}


static PTREE bareArg(           // STRIP LIST NODE FROM ARGUMENT
    PTREE arg )                 // - CO_LIST node
{
    PTREE retn;                 // - target node

    DbgVerify( NodeIsBinaryOp( arg, CO_LIST ), "bareArg -- impossible" );
    retn = arg->u.subtree[1];
    PTreeFree( arg );
    return retn;
}


PTREE EffectCtor(               // EFFECT A CONSTRUCTION
    PTREE initial,              // - initialization list
    SYMBOL ctor,                // - constructor
    TYPE base_type,             // - type being constructed
    PTREE this_node,            // - NULL, or node for "this"
    TOKEN_LOCN *err_locn,       // - error location
    unsigned control )          // - control mask
{
    PTREE node;                 // - resultant node
    CNV_RETN retn;              // - conversion return

    /*
        if the caller depends on a non-NULL 'this_node' being the final
        value of the expression returned by EffectCtor, see the code in
        AnalyseNew()
    */
    switch( base_type->id ) {
      case TYP_BOOL :
      case TYP_CHAR :
      case TYP_SCHAR :
      case TYP_UCHAR :
      case TYP_WCHAR :
      case TYP_SSHORT :
      case TYP_USHORT :
      case TYP_SINT :
      case TYP_UINT :
      case TYP_SLONG :
      case TYP_ULONG :
      case TYP_SLONG64 :
      case TYP_ULONG64 :
      case TYP_FLOAT :
      case TYP_DOUBLE :
      case TYP_LONG_DOUBLE :
      case TYP_ENUM :
      case TYP_BITFIELD :
      case TYP_FUNCTION :
      case TYP_POINTER :
      case TYP_MEMBER_POINTER :
        if( initial == NULL ) {
            initial = NodeZero();
        }
        if( this_node == NULL ) {
            node = NodeConvert( base_type, initial );
        } else {
            if( base_type->id == TYP_MEMBER_POINTER ) {
                node = NodeBinary( CO_INIT, this_node, initial );
                node->type = this_node->type;
                retn = MembPtrAssign( &node );
                /* value of expression is 'this_node' */
                ConversionDiagnose( retn, node, &diagCtor );
            } else {
                PTREE dup;

                dup = NULL;
                if( control & EFFECT_VALUE_THIS ) {
                    dup = NodeDupExpr( &this_node );
                }
                if( base_type->id == TYP_BITFIELD ) {
                    this_node = NodeUnaryCopy( CO_BITFLD_CONVERT, this_node );
                    this_node->type = base_type->of;
                }
                node = NodeBinary( NULL == TypeReference( base_type )
                                   ? CO_INIT : CO_INIT_REF
                                 , this_node
                                 , initial );
                node->type = this_node->type;
                if( dup != NULL ) {
                    node = NodeComma( node, dup );
                }
            }
        }
        break;
      case TYP_CLASS :
        if( ctor == NULL ) {
            node = ClassDefaultCopy( this_node, bareArg( initial ) );
        } else {
            boolean check_dtoring;  // - TRUE ==> need to check DTORing
            TYPE this_type;         // - type of this arg
            CALL_OPT opt;           // - type of optimization
            PTREE bare;             // - bare source operand
            PTREE co_dtor;          // - CO_DTOR operand
            if( this_node == NULL ) {
                this_node = NodeTemporary( base_type );
                this_node = PTreeSetLocn( this_node, err_locn );
                check_dtoring = TRUE;
            } else {
                check_dtoring = FALSE;
            }
            if( initial != NULL
             && initial->u.subtree[0] == NULL
             && base_type == ClassTypeForType( initial->type ) ) {
                opt = AnalyseCallOpts( base_type
                                     , initial->u.subtree[1]
                                     , &co_dtor
                                     , &bare );
                if( opt != CALL_OPT_NONE ) {
                    initial = bareArg( initial );
                }
            } else {
                opt = CALL_OPT_NONE;
            }
            if( opt == CALL_OPT_NONE ) {
                arg_list *args;     // - function arguments
                if( control & EFFECT_EXACT ) {
                    this_node->flags |= PTF_MEMORY_EXACT;
                }
                args = SymFuncArgList( ctor );
                this_type = base_type;
                if( args->qualifier != 0 ) {
                    this_type = MakeModifiedType( this_type
                                                , args->qualifier );
                }
                if( NULL == PointerTypeEquivalent( this_node->type ) ) {
                    this_type = MakeReferenceTo( this_type );
                } else {
                    this_type = MakePointerTo( this_type );
                }
                this_node = CastImplicit( this_node
                                        , this_type
                                        , CNV_FUNC_CD_THIS
                                        , &diagCtor );
                if( PT_ERROR == this_node ) {
                    NodeFreeDupedExpr( initial );
                    node = PTreeErrorNode( this_node );
                    break;
                }
                node = NodeMakeCall( ctor
                                   , SymFuncReturnType( ctor )
                                   , initial );
                node->flags |= PTF_LVALUE;
                node = PTreeSetLocn( node, err_locn );
                if( AddDefaultArgs( ctor, node ) ) {
                    node = CallArgsArrange( ctor->sym_type
                                          , node
                                          , node->u.subtree[1]
                                          , NodeArg( this_node )
                                          , CallArgumentExactCtor
                                              ( base_type
                                              , ( control & EFFECT_EXACT ) != 0 )
                                          , NULL );
                }
            } else {
                node = CopyOptimize( bare
                                   , initial
                                   , this_node
                                   , co_dtor
                                   , opt );
                control &= ~ EFFECT_CTOR_DECOR;
            }
            if( node->op == PT_ERROR ) break;
            if( check_dtoring ) {
                node = NodeDtorExpr( node, this_node->u.symcg.symbol );
                if( node->op == PT_ERROR ) break;
            }
            if( control & EFFECT_EXACT ) {
                node->flags |= PTF_MEMORY_EXACT;
            }
            if( control & EFFECT_CTOR_DECOR ) {
                if( control & EFFECT_DECOR_COMP ) {
                    unsigned kind;
                    node = PtdScopeCall( node, ctor );
                    if( control & EFFECT_EXACT ) {
                        kind = DTC_COMP_MEMB;
                    } else if( control & EFFECT_VIRTUAL ) {
                        kind = DTC_COMP_VBASE;
                    } else {
                        kind = DTC_COMP_DBASE;
                    }
                    node = PtdDtorKind( node, kind );
                    node = PtdCtoredComponent( node, base_type );
                } else if( control & EFFECT_DECOR_TEMP ) {
                    node = PtdCtoredExprType( node, ctor, base_type );
                } else {
                    node = PtdCtoredScopeType( node, ctor, base_type );
                }
            }
        }
        break;
      case TYP_VOID :
        node = NodeUnary( CO_TRASH_EXPR, node );
        node->type = base_type;
        break;
      default :
        node = this_node;
        break;
    }
    return node;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?