decl.c

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

C
1,062
字号
            *control |= DC_REDEFINED;
            return( TRUE );
        }
    }
    scope = SymScope( prev );
    if( ScopeType( scope, SCOPE_FILE ) ) {
        switch( prev->id ) {
        case SC_EXTERN:
            switch( curr->id ) {
            case SC_NULL:
                if( SymIsInitialized( prev ) ) {
                    *control |= DC_REDEFINED;
                }
                /* fall through */
            case SC_EXTERN:
                prev->id = curr->id;
                return( TRUE );
            }
            break;
        case SC_PUBLIC:
            switch( curr->id ) {
            case SC_NULL:
                *control |= DC_REDEFINED;
                /* fall through */
            case SC_EXTERN:
                return( TRUE );
            }
            break;
        case SC_STATIC:
            if( curr->id == SC_EXTERN ) {
                // p.98 ARM (7.1.1)
                return( TRUE );
            }
            break;
        }
    }
    return( FALSE );
}

static fn_stg_class_status checkFnStorageClass( SYMBOL prev, SYMBOL curr, decl_check *control )
{
    if( SymIsAlias( prev ) ) {
        if( SymIsAlias( curr ) ) {
            if( prev->u.alias == curr->u.alias ) {
                return( FSCS_SAME_FN );
            }
            return( FSCS_DIFF_FN );
        }
        CErr2p( ERR_PREV_USING_DECL, prev );
        return( FSCS_NULL );
    }
    if( SymIsAlias( curr ) ) {
        CErr2p( ERR_CURR_USING_DECL, prev );
        return( FSCS_NULL );
    }
    /* check storage class specifiers for two identical functions */
    if( commonCheck( prev, curr, control ) ) {
        return( FSCS_SAME_FN );
    }
    if( curr->id == SC_DEFAULT ) {
        if( prev->id == SC_DEFAULT ) {
            if( SymDefaultBase( curr ) == SymDefaultBase( prev ) ) {
                return( FSCS_SAME_FN );
            }
        }
        return( FSCS_DIFF_FN );
    }
    if( prev->id == SC_DEFAULT ) {
        CErr2p( WARN_FN_HITS_ANOTHER_ARG, prev );
        return( FSCS_DIFF_FN );
    }
    switch( curr->id ) {
    case SC_NULL:
        break;
    case SC_EXTERN:
        if( prev->id == SC_NULL ) {
            prev->id = SC_EXTERN;
        } else if( prev->id != SC_EXTERN ) {
            CErr2p( ERR_CONFLICTING_STORAGE_CLASSES, prev );
            return( FSCS_NULL );
        }
        break;
    case SC_STATIC:
        if( prev->id == SC_NULL && CompFlags.extensions_enabled ) {
            prev->id = SC_STATIC;
        } else if( prev->id != SC_STATIC ) {
            CErr2p( ERR_CONFLICTING_STORAGE_CLASSES, prev );
            return( FSCS_NULL );
        }
        break;
    default:
        switch( prev->id ) {
        case SC_DEFAULT:
            DbgUseless();
            return( FSCS_DIFF_FN );
        default:
            if( prev->id != curr->id ) {
                CErr2p( ERR_CONFLICTING_STORAGE_CLASSES, prev );
                return( FSCS_NULL );
            }
        }
    }
    return( FSCS_SAME_FN );
}

static boolean checkVarStorageClass( SYMBOL prev, SYMBOL curr, decl_check *control )
{
    /* check storage class specifiers for two identical variables */
    if( commonCheck( prev, curr, control ) ) {
        return( TRUE );
    }
    *control |= DC_REDEFINED;
    switch( curr->id ) {
    case SC_NULL:
    case SC_ENUM:
        break;
    default:
        switch( prev->id ) {
        case SC_ENUM:
            break;
        default:
            if( prev->id != curr->id ) {
                CErr2p( ERR_CONFLICTING_STORAGE_CLASSES, prev );
            }
        }
    }
    return( FALSE );
}

static SYMBOL combineVariables( SYMBOL prev, SYMBOL curr, prev_sym_adjust control, type_flag new_flags )
{
    TYPE sym_type;

    if( !SymIsInitialized( prev ) ) {
        /* transfer symbol location if previous version wasn't initialized */
        SymLocnCopy( prev, curr );
    }
    sym_type = prev->sym_type;
    if( control & PSA_USE_CURR_MODS ) {
        sym_type = TypeOverrideModifiers( sym_type, curr->sym_type );
    }
    if( new_flags != TF1_NULL ) {
        sym_type = MakeModifiedType( sym_type, new_flags );
    }
    prev->sym_type = sym_type;
    return( prev );
}

static boolean memModelModifiersOK( type_flag prev_flags, type_flag curr_flags,
                                    prev_sym_adjust *adjust )
{
    // MSC allows:
    //          extern int __far x;
    //          int __based(__segname("_DATA")) x = 2;
    // or:
    //          extern int __based(__segname("_DATA")) y;
    //          int __far y = 3;

    prev_flags &= TF1_MEM_MODEL;
    curr_flags &= TF1_MEM_MODEL;
    if( curr_flags == prev_flags ) {
        // identical is OK
        return( TRUE );
    }
    switch( prev_flags ) {
    case TF1_FAR:
        if( curr_flags == TF1_BASED_STRING ) {
            // use new modifiers
            *adjust |= PSA_USE_CURR_MODS;
            return( TRUE );
        }
        break;
    case TF1_BASED_STRING:
        if( curr_flags == TF1_FAR ) {
            // keep old modifiers
            return( TRUE );
        }
        break;
    }
    // memory model modifiers are different
    return( FALSE );
}

static type_flag cannotChangeFlags( type_flag prev, type_flag curr,
                                    boolean ignore_mem_model )
{
    /* truth table:

        pc oa r  (p^c) & ~((c & a) | (p & o))
        00 00 0a   0   0 x
        00 01 0a   0   0 x
        00 10 0a   0   0 x
        00 11 0a   0   0 x
        01 00 1d   1   1 1    0    0    0
        01 01 0b   1   0 0    1    1    0
        01 10 1d   1   1 1    0    0    0
        01 11 0b   1   0 0    1    1    0
        10 00 1d   1   1 1    0    0    0
        10 01 1d   1   1 1    0    0    0
        10 10 0c   1   0 0    0    1    1
        10 11 0c   1   0 0    0    1    1
        11 00 0a   0   0 x
        11 01 0a   0   0 x
        11 10 0a   0   0 x
        11 11 0a   0   0 x
                       ^r

        Code equivalent:

            if p == c
                return 0        // modifiers are identical (case a)
            if p == 0 && c == 1 && a == 1
                return 0        // this modifier can be added (case b)
            if p == 1 && c == 0 && o == 1
                return 0        // this modifier can be omitted (case c)
            // p != c here
            return 1            // this modifier can't change (case d)
    */
    type_flag result;

    prev &= ~TF1_MOD_IGNORE;
    curr &= ~TF1_MOD_IGNORE;
    if( ignore_mem_model ) {
        prev &= ~TF1_MEM_MODEL;
        curr &= ~TF1_MEM_MODEL;
    }
    result = ( prev ^ curr );
    result &= ~(( curr & TF1_MOD_ADD_LATER ) | ( prev & TF1_MOD_OMIT_LATER ));
    return( result );
}

static void prevCurrErr( unsigned msg, SYMBOL prev, SYMBOL curr )
{
    if( CErr2p( msg, prev ) & MS_PRINTED ) {
        CErr2p( INF_CURR_DECL_TYPE, curr->sym_type );
    }
}

static boolean combinableSyms( SYMBOL prev, SYMBOL curr, prev_sym_adjust *adjust, type_flag *new_flags )
{
    TYPE prev_type;
    TYPE curr_type;
    TYPE prev_unmod;
    TYPE curr_unmod;
    type_flag prev_flags;
    type_flag curr_flags;
    void *prev_base;
    void *curr_base;
    target_size_t curr_size;
    boolean ret;
    struct {
        unsigned file_scope : 1;
    } flag;

    *adjust = PSA_NULL;
    *new_flags = TF1_NULL;
    ret = TRUE;
    flag.file_scope = FALSE;
    if( ScopeType( SymScope( curr ), SCOPE_FILE ) ) {
        flag.file_scope = TRUE;
        if( LinkageSpecified() && ! LinkageIsCurr( prev ) ) {
            CErr2p( ERR_CONFLICTING_LINKAGE_SPEC, prev );
            ret = FALSE;
        }
    }
    prev_type = prev->sym_type;
    curr_type = curr->sym_type;
    if( TypesIdentical( prev_type, curr_type ) ) {
        return( ret );
    }
    prev_unmod = TypeModFlagsBaseEC( prev_type, &prev_flags, &prev_base );
    curr_unmod = TypeModFlagsBaseEC( curr_type, &curr_flags, &curr_base );
    if(( prev_flags ^ curr_flags ) & ~TF1_MOD_IGNORE ) {
        if( memModelModifiersOK( prev_flags, curr_flags, adjust ) ) {
            if( cannotChangeFlags( prev_flags, curr_flags, TRUE ) != TF1_NULL ) {
                prevCurrErr( ERR_CONFLICTING_MODIFIERS, prev, curr );
                ret = FALSE;
            }
        } else {
            prevCurrErr( ERR_CONFLICTING_MODIFIERS, prev, curr );
            ret = FALSE;
        }
    }
    if( ret && ( prev_flags & TF1_BASED ) != TF1_NULL ) {
        if((( prev_flags ^ curr_flags ) & TF1_BASED ) == TF1_NULL ) {
            if( ! TypeBasesEqual( prev_flags, prev_base, curr_base ) ) {
                prevCurrErr( ERR_CONFLICTING_MODIFIERS, prev, curr );
                ret = FALSE;
            }
        }
    }
    if( ret ) {
        *new_flags = ( curr_flags & ~prev_flags ) & TF1_MOD_ADD_LATER;
    }
    if( TypesIdentical( prev_unmod, curr_unmod ) ) {
        return( ret );
    }
    if( prev_unmod->id == TYP_ARRAY && curr_unmod->id == TYP_ARRAY ) {
        curr_size = curr_unmod->u.a.array_size;
        if( prev_unmod->u.a.array_size == 0 ) {
            if( curr_size != 0 ) {
                if( TypesIdentical( prev_unmod->of, curr_unmod->of ) ) {
                    prev_type = DupArrayTypeForArray( prev_type, curr_size );
                    prev->sym_type = prev_type;
                    return( ret );
                }
            }
        } else {
            /* (this is accepted practice)
                struct S {
                    static int a[10];
                };
                int S::a[];

                extern char buff[256];
                char buff[] = { 'a' };
            */
            if( SymIsStaticMember( prev ) || flag.file_scope ) {
                if( curr_size == 0 ) {
                    if( TypesIdentical( prev_unmod->of, curr_unmod->of ) ) {
                        return( ret );
                    }
                }
            }
        }
    }
    return( FALSE );
}

static SYMBOL combineFunctions( SYMBOL prev_fn, SYMBOL curr_fn )
{
    void        *prev_base;
    void        *curr_base;
    AUX_INFO    *prev_pragma;
    AUX_INFO    *curr_pragma;
    type_flag   new_flags;
    type_flag   prev_flags;
    type_flag   curr_flags;
    type_flag   prev_fn_flags;
    type_flag   curr_fn_flags;
    TYPE        prev_type;
    TYPE        curr_type;
    TYPE        unmod_prev_type;
    TYPE        unmod_curr_type;
    arg_list    *prev_args;
    arg_list    *curr_args;
    struct {
        unsigned check_bases : 1;
    } flag;

    if( prev_fn->id == SC_DEFAULT || curr_fn->id == SC_DEFAULT ) {
        return( prev_fn );
    }
    prev_type = prev_fn->sym_type;

⌨️ 快捷键说明

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