type.c

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

C
2,314
字号
        CFatal( "unknown type being compared" );
#else
        return( FALSE );
#endif
    }
    return( TRUE );
}

void TypedefReset( SYMBOL sym, TYPE type )
/****************************************/
{
    TYPE typedef_type;

    /* we are tweaking the type of a typedef that we want permanently changed */
    typedef_type = sym->sym_type;
    DbgAssert( typedef_type->id == TYP_TYPEDEF );
    /* typedef types are not dupCompare()'d */
    typedef_type->of = type;
}

void CheckUniqueType( TYPE newtype )
/**********************************/
{
    #ifdef XTRA_RPT
        ExtraRptTabIncr( ctr_type_ids, newtype->id, 0 );
        ExtraRptTabIncr( ctr_type_ids, TYP_MAX-1, 0 );
        if( newtype->id == TYP_FUNCTION ) {
            unsigned num_args = newtype->u.f.args->num_args;
            if( num_args > ARGS_MAX ) {
                num_args = ARGS_MAX;
            }
            ExtraRptTabIncr( ctr_fn_args, num_args, 0 );
            ExtraRptTabIncr( ctr_fn_args, ARGS_MAX+1, 0 );
        }
    #endif
    RingPush( &uniqueTypes, newtype );
}


static TYPE typeDuplicated(     // GET DUPLICATED TYPE
    TYPE newtype,               // - new type
    TYPE* head )                // - list head
{
    TYPE check;
    TYPE newtype_of;
    TYPE prev;
    type_flag newtype_flag;

    prev = NULL;
    newtype_of = newtype->of;
    newtype_flag = newtype->flag;
    ExtraRptZeroCtr( ctr_lookup );
    RingIterBeg( *head, check ) {
        ExtraRptIncrementCtr( ctr_lookup );
        if( check->of == newtype_of ) {
            if( check->flag == newtype_flag ) {
                if( dupCompare( check, newtype ) ) {
                    ExtraRptAddtoCtr( ctr_dup_succ_probes, ctr_lookup );
                    ExtraRptIncrementCtr( ctr_dup_succ );
                    typeFree( newtype );
                    newtype = RingPromote( head, check, prev );
                    return newtype;
                }
            }
        }
        prev = check;
    } RingIterEnd( check )
    #ifdef XTRA_RPT
        if( CompFlags.codegen_active ) {
            ExtraRptIncrementCtr( ctr_cg_dups_fail );
        }
        ExtraRptTabIncr( ctr_type_ids, newtype->id, 0 );
        ExtraRptTabIncr( ctr_type_ids, TYP_MAX-1, 0 );
        if( newtype->id == TYP_FUNCTION ) {
            unsigned num_args = newtype->u.f.args->num_args;
            if( num_args > ARGS_MAX ) {
                num_args = ARGS_MAX;
            }
            ExtraRptTabIncr( ctr_fn_args, num_args, 0 );
            ExtraRptTabIncr( ctr_fn_args, ARGS_MAX+1, 0 );
        }
    #endif
    ExtraRptAddtoCtr( ctr_dup_fail_probes, ctr_lookup );
    ExtraRptIncrementCtr( ctr_dup_fail );
    newtype = RingPush( head, newtype );
    return newtype;
}

#define typeHashVal( t ) ((t)->of->dbg.handle & TYPE_HASH_MASK )

static TYPE checkMaybeDupType( TYPE type )
{
    if( type->next != NULL ) {
        return( type );
    }
    if( type->next == NULL ) {
        TYPE class_type = StructType( type );
        if( class_type != NULL && ! TypeDefined( class_type ) ) {
            return( type );
        }
    }
    type = CheckDupType( type );
    return( type );
}

TYPE CheckDupType( TYPE newtype )
/*******************************/
{
    unsigned num_args;
    type_id id;
    TYPE *head;

    DbgAssert( newtype->next == NULL );
    id = newtype->id;
    ExtraRptIncrementCtr( ctr_dups );
    #ifdef XTRA_RPT
        if( CompFlags.codegen_active ) {
            ExtraRptIncrementCtr( ctr_cg_dups );
        }
    #endif
#ifndef NDEBUG
    if( id == TYP_MODIFIER ) {
        if( newtype->flag == TF1_NULL ) {
            if( newtype->u.m.base == NULL ) {
                if( newtype->u.m.pragma == NULL ) {
                    CFatal( "empty modifier created" );
                }
            }
        }
    }
#endif
    head = typeHashTables[ id ];
    if( head == NULL ) {
        switch( id ) {
        case TYP_FUNCTION:
            DbgVerify( newtype->of != NULL
                     , "type: attempt to set base type to NULL" );
            num_args = newtype->u.f.args->num_args;
            if( num_args < ARGS_HASH ) {
                ExtraRptIncrementCtr( ctr_dup_fns );
                head = &fnHashTable[ num_args ][ typeHashVal( newtype ) ];
            } else if( num_args < ARGS_MAX ) {
                ExtraRptIncrementCtr( ctr_dup_fns );
                head = &fnTable[ num_args - ARGS_HASH ];
            } else {
                ExtraRptIncrementCtr( ctr_dup_fns_big );
                head = &typeTable[ id ];
            }
            newtype = typeDuplicated( newtype, head );
            break;
        case TYP_MEMBER_POINTER:
        case TYP_GENERIC:
            newtype = typeDuplicated( newtype, &typeTable[ id ] );
            break;
        default:
            #ifdef XTRA_RPT
                if( CompFlags.codegen_active ) {
                    ExtraRptIncrementCtr( ctr_cg_dups_fail );
                }
                ExtraRptTabIncr( ctr_type_ids, id, 0 );
                ExtraRptTabIncr( ctr_type_ids, TYP_MAX-1, 0 );
                if( id == TYP_FUNCTION ) {
                    unsigned num_args = newtype->u.f.args->num_args;
                    if( num_args > ARGS_MAX ) {
                        num_args = ARGS_MAX;
                    }
                    ExtraRptTabIncr( ctr_fn_args, num_args, 0 );
                    ExtraRptTabIncr( ctr_fn_args, ARGS_MAX+1, 0 );
                }
            #endif
            newtype = RingPush( &typeTable[ id ], newtype );
        }
    } else {
        if( head == arrayHashTable ) {
            if( newtype->u.a.array_size == 0 ) {
                /* lets us change the size without worrying about duplicates */
                return( newtype );
            }
        }
        DbgVerify( newtype->of != NULL
                 , "type: attempt to set base type to NULL" );
        newtype = typeDuplicated( newtype
                                , &head[ typeHashVal( newtype ) ] );
    }
    return newtype;
}


static void traverseTypeRing(   // TRAVERSE RING OF TYPES
    TYPE ring,                  // - the ring
    void (*rtn)( TYPE, void* ), // - the routine
    void* data )                // - data for the routine
{
    TYPE curr;

    RingIterBeg( ring, curr ) {
        (*rtn)( curr, data );
    } RingIterEnd( curr )
}


static void traverseTypeHashed( // TRAVERSE VECTOR OF HASHED TYPE RINGS
    TYPE* vector,               // - the vector
    void (*rtn)( TYPE, void* ), // - the routine
    void* data )                // - data for the routine
{
    int idx;                    // - index

    for( idx = 0; idx < TYPE_HASH_MODULUS; ++ idx ) {
        traverseTypeRing( *vector, rtn, data );
        ++ vector;
    }
}


void TypeTraverse( type_id id, void (*rtn)( TYPE, void *), void *data )
/*********************************************************************/
{
    unsigned num_args;

    switch( id ) {
      case TYP_POINTER :
        traverseTypeHashed( pointerHashTable, rtn, data );
        break;
      case TYP_BITFIELD :
        traverseTypeHashed( bitfieldHashTable, rtn, data );
        break;
      case TYP_ARRAY :
        traverseTypeHashed( arrayHashTable, rtn, data );
        break;
      case TYP_MODIFIER :
        traverseTypeHashed( modifierHashTable, rtn, data );
        break;
      case TYP_FUNCTION :
        traverseTypeRing( typeTable[id], rtn, data );
        for( num_args = 0; num_args < ARGS_HASH; ++num_args ) {
            traverseTypeHashed( fnHashTable[ num_args ], rtn, data );
        }
        for( ; num_args < ARGS_MAX; ++num_args ) {
            traverseTypeRing( fnTable[ num_args - ARGS_HASH ], rtn, data );
        }
        break;
      default :
        traverseTypeRing( typeTable[id], rtn, data );
        break;
    }
}

TYPE TypeUserConversion( DECL_SPEC *dspec, DECL_INFO *dinfo )
/***********************************************************/
{
    TYPE cnv_id_type;

    if( dinfo == NULL ) {
        dinfo = makeDeclInfo( NULL );
    }
    dinfo = FinishDeclarator( dspec, dinfo );
    cnv_id_type = dinfo->type;
    FreeDeclInfo( dinfo );
    return( cnv_id_type );
}

static DECL_INFO *prependTypeToDeclarator( DECL_INFO *dinfo, TYPE type )
{
    TYPE end;

    if( type != NULL ) {
        end = type;
        for(;;) {
            if( end->of == NULL ) break;
            end = end->of;
        }
        end->of = dinfo->list;
        dinfo->list = type;
    }
    return( dinfo );
}

DECL_INFO *MakeNewDeclarator( DECL_SPEC *dspec,DECL_INFO *ptrs,DECL_INFO*arrays)
/******************************************************************************/
{
    if( arrays == NULL ) {
        arrays = makeDeclInfo( NULL );
    }
    if( ptrs != NULL ) {
        arrays = prependTypeToDeclarator( arrays, ptrs->list );
        /* we've detached the list of types */
        ptrs->list = NULL;
        FreeDeclInfo( ptrs );
    }
    arrays = FinishDeclarator( dspec, arrays );
#ifndef NDEBUG
    if( PragDbgToggle.dump_types ) {
        DumpFullType( arrays->type );
    }
#endif
    return( arrays );
}

DECL_INFO *MakeNewPointer( specifier_t cv_spec, DECL_INFO *dinfo, PTREE member )
/******************************************************************************/
{
    TYPE ptr_type;
    TYPE class_type;

    if( dinfo == NULL ) {
        dinfo = makeDeclInfo( NULL );
    }
    if( member != NULL ) {
        class_type = extractMemberType( member );
        ptr_type = makeMemberPointerType( class_type, cv_spec );
    } else {
        ptr_type = MakePointerType( TF1_NULL, cv_spec );
    }
    return( prependTypeToDeclarator( dinfo, ptr_type ) );
}

DECL_INFO *MakeNewDynamicArray( PTREE nelem )
/*******************************************/
{
    DECL_INFO *dinfo;

    dinfo = makeDeclInfo( NULL );
    dinfo->defarg_expr = nelem;
    return( dinfo );
}

DECL_INFO *AddArrayDeclarator( DECL_INFO *dinfo, PTREE size )
/***********************************************************/
{
    TYPE array_type;

    if( size != NULL ) {
        CheckDimension( size );
        array_type = MakeArrayType( size->u.uint_constant );
        PTreeFree( size );
    } else {
        array_type = MakeArrayType( 0 );
    }
    return( prependTypeToDeclarator( dinfo, array_type ) );
}

static void freeDeclList( DECL_INFO **arg_decls )
{
    DECL_INFO *curr;

    RingIterBegSafe( *arg_decls, curr ) {
        FreeDeclInfo( curr );
    } RingIterEndSafe( curr )
    *arg_decls = NULL;
}

static void stripDefArg( DECL_INFO *dinfo )
{
    PTREE expr;
    REWRITE *rewrite;

    if( dinfo->has_defarg ) {
        expr = dinfo->defarg_expr;
        if( expr != NULL ) {
            PTreeFreeSubtrees( expr );
            dinfo->defarg_expr = NULL;
        }
        rewrite = dinfo->defarg_rewrite;
        if( rewrite != NULL ) {
            RewriteFree( rewrite );
            dinfo->defarg_rewrite = NULL;
        }
        dinfo->has_defarg = FALSE;
    }
}

static void removeDefaultArgs( DECL_INFO *dinfo )
{
    DECL_INFO *curr;

    RingIterBeg( dinfo, curr ) {
        stripDefArg( curr );
    } RingIterEnd( curr )
}

static boolean cantHaveDefaultArgs( int err_msg, DECL_INFO *dinfo )
{
    DECL_INFO *curr;

    RingIterBeg( dinfo, curr ) {
        if( curr->has_defarg ) {
            CErr1( err_msg );
            return( TRUE );
        }
    } RingIterEnd( curr )
    return( FALSE );
}

/*
//  cantHaveDefaultArgGaps
//      Supposedly checks for gaps in default arguments. Don't think it works!
//  called from:
//      ForceNoDefaultArgs  (called from FinishDeclarator)
//      FreeArgs            (only called from template.c (not any more!))
//      checkUsefulParms    (called from FinishDeclarator)
*/
static boolean cantHaveDefaultArgGaps( DECL_INFO *dinfo )
{
    boolean transition_detected;
    DECL_INFO *prev_init;
    DECL_INFO *curr;

    transition_detected = FALSE;
    prev_init = NULL;
    RingIterBeg( dinfo, curr ) {
        if( curr->has_defarg ) {
            if( prev_init == NULL ) {
                if( transition_detected ) {
                    CErr1( ERR_DEFAULT_ARGS_MISSING );
                    return( TRUE );
                }
                transition_detected = TRUE;
            }
            prev_init = curr;
        } else {
            prev_init = NULL;
        }
    } RingIterEnd( curr )
    return( FALSE );
}

/*
 * see 14.1 p11:
 * If a template-parameter has a default template-argument, all
 * subsequent template-parameters shall have a default
 * template-argument supplied.
 *
 * only called from: FreeArgsDefaultsOK  (only called from template.c)
 */
static boolean checkForMissingDefaultArgs( DECL_INFO *dinfo )
{
    boolean prev_defarg;
    DECL_INFO *curr;

    prev_defarg = FALSE;
    RingIterBeg( dinfo, curr ) {
        if( curr->has_defarg ) {
            prev_defarg = ( curr != NULL );
        } else if( prev_defarg ) {
            /* previous parameter had a default argument, but this one
             * hasn't => error */
            if( curr->generic_sym ) {
                SetErrLoc( &curr->generic_sym->locn->tl);
            } else {
                SetErrLoc( &curr->sym->locn->tl);
            }
            CErr1( ERR_DEFAULT_ARGS_MISSING );
            return( TRUE );
        }
    } RingIterEnd( curr )
    return( FALSE );
}

void ForceNoDefaultArgs( DECL_INFO *dinfo, int err_msg )
/******************************************************/
{
    DECL_INFO *parms;

⌨️ 快捷键说明

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