cdecl2.c

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

C
1,744
字号
            /*
            // Local variables in stack will be far when SS != DS (/zu)
            // (applies only to auto vars, functions params are handled
            // NOT here but in "cexpr.c" [OPR_PUSHADDR])
            */
            if( TargetSwitches & FLOATING_SS ) {
                sym->attrib |= FLAG_FAR;
            }
        }
        /*
        // static class variables can be thread local also
        */
        if( (stg_class == SC_STATIC) && (sym->declspec == DECLSPEC_THREAD) ) {          /* 06-JAN-03 */
            if( !CompFlags.thread_data_present ) {
                ThreadSeg = DefThreadSeg();
                CompFlags.thread_data_present = 1;
            }
            sym->u.var.segment = ThreadSeg;
        }
    }
    if( (Toggles & TOGGLE_UNREFERENCED) == 0 ) {
        sym->flags |= SYM_IGNORE_UNREFERENCE;   /* 25-apr-91 */
    }
    old_sym_handle = SymLook( sym->info.hash_value, sym->name );
    if( old_sym_handle != 0 ) {                         /* 28-feb-94 */
        SymGet( &old_sym, old_sym_handle );
        if( old_sym.level == SymLevel ) {
            SetDiagSymbol( &old_sym, old_sym_handle );
            if( old_sym.stg_class == SC_EXTERN  &&  stg_class == SC_EXTERN ) {
                if( ! IdenticalType( old_sym.sym_type, sym->sym_type ) ) {
                    CErr2p( ERR_TYPE_DOES_NOT_AGREE, sym->name );
                }
            } else if( old_sym.stg_class == SC_TYPEDEF ) {
                CErr2p( ERR_SYM_ALREADY_DEFINED, sym->name );
            }
            SetDiagPop();
        }
    }
    if( stg_class == SC_EXTERN ) {              /* 27-oct-88 */
        old_sym_handle = Sym0Look( sym->info.hash_value, sym->name );
    }
    if( old_sym_handle != 0 ) {
        SymGet( &old_sym, old_sym_handle );
        SetDiagSymbol( &old_sym, old_sym_handle );
        if( old_sym.level == SymLevel           /* 28-mar-88 */
        ||      stg_class == SC_EXTERN ) {              /* 12-dec-88 */
            if( (sym->attrib & ATTRIB_MASK) !=
                (old_sym.attrib & ATTRIB_MASK) ) {
                 CErr2p( ERR_MODIFIERS_DISAGREE, sym->name );
            }
            if( (sym->attrib & FLAG_LANGUAGES) != (old_sym.attrib & FLAG_LANGUAGES) ) {
                // just inherit old lang flags
                // if new != 0 then it's possible someone saw a different prototype
                if( (sym->attrib & FLAG_LANGUAGES) != 0 ) {
                     CErr2p( ERR_MODIFIERS_DISAGREE, sym->name );
                }
            }
            if( sym->declspec != old_sym.declspec ) {
                switch( sym->declspec ) {
                case DECLSPEC_DLLIMPORT:
                case DECLSPEC_THREAD:
                    CErr2p( ERR_MODIFIERS_DISAGREE, sym->name );
                    break;
                case DECLSPEC_DLLEXPORT:
                    if( old_sym.declspec == DECLSPEC_DLLIMPORT ) {
                        old_sym.declspec = DECLSPEC_DLLEXPORT;
                    } else {
                        CErr2p( ERR_MODIFIERS_DISAGREE, sym->name );
                    }
                    break;
                }
            }
        }
        SetDiagPop();
    }
    if( (old_sym_handle != 0)  &&
        (stg_class == SC_NULL || stg_class == SC_EXTERN ||
          (stg_class == SC_STATIC && SymLevel == 0)) ) {

        /* make sure sym->sym_type same type as old_sym->sym_type */

        SetDiagSymbol( &old_sym, old_sym_handle );
        which = VerifyType( sym->sym_type, old_sym.sym_type, sym );
        SetDiagPop();
        if( which == 0 && old_sym.level == SymLevel ) { /* 06-jul-88 AFS */
            /* new symbol's type supersedes old type */
            old_sym.sym_type = sym->sym_type;
            if( (old_sym.flags & SYM_FUNCTION) ) {
                old_sym = *sym;  // ditch old sym
            }
            SymReplace( &old_sym, old_sym_handle );
        }
        if( stg_class == SC_EXTERN  &&  SymLevel != 0 ) goto new_var;
        CMemFree( sym->name );
        memcpy( sym, &old_sym, sizeof( SYM_ENTRY ) );
        sym_handle = old_sym_handle;
        SetDiagSymbol( &old_sym, old_sym_handle );
        /* verify that newly specified storage class doesn't conflict */
        if( (stg_class == SC_NULL) || (stg_class == SC_STATIC) ) {
            if( sym->stg_class == SC_EXTERN ) {
                /* was extern, OK to change to none */
                if( stg_class == SC_NULL ) {
                    sym->stg_class = stg_class;     /* 03-oct-88 */
                } else {
                    /* was extern, not OK to make static */
                    CErrSymName( ERR_STG_CLASS_DISAGREES, sym, sym_handle );
                }
            } else if( sym->stg_class == SC_STATIC && stg_class == SC_NULL ) {
                /* was static, not OK to redefine */
                CErrSymName( ERR_STG_CLASS_DISAGREES, sym, sym_handle );
            } else if( sym->stg_class == SC_NULL && stg_class == SC_STATIC ) {
                /* was extern linkage, not OK to to make static */
                CErrSymName( ERR_STG_CLASS_DISAGREES, sym, sym_handle );
            }
        }
        SetDiagPop();
    } else {
        if( stg_class == SC_EXTERN  &&  SymLevel != 0 ) {
            ; /* do nothing  29-jan-93 */
        } else {
            VfyNewSym( sym->info.hash_value, sym->name );
        }
new_var:
        old_sym_handle = 0;
        sym->flags |= SYM_DEFINED;
        typ = SkipDummyTypedef( sym->sym_type );        /* 25-nov-94 */
        if( typ->decl_type == TYPE_TYPEDEF ) {          /* 12-mar-92 */
            SymGet( &sym2, typ->u.typedefn );
            if( sym->u.var.segment == 0  &&  sym2.u.var.segment != 0 ) {
                sym->u.var.segment = sym2.u.var.segment;
            }
            SKIP_TYPEDEFS( typ );
        }
        if( typ->decl_type == TYPE_VOID ) {
            CErr2p( ERR_VAR_CANT_BE_VOID, sym->name );
            sym->sym_type = TypeDefault();
        }
        sym->stg_class = stg_class;
        sym_handle = SymAdd( sym->info.hash_value, sym );
    }
    if( sym->u.var.segment == 0  &&     /* 22-oct-92 */
     (stg_class == SC_STATIC ||
      stg_class == SC_NULL   ||
      stg_class == SC_EXTERN) ) {
        if( DefDataSegment != 0 ) {
            sym->u.var.segment = DefDataSegment;
            SymReplace( sym, sym_handle );
        }
    }
    if( CurToken == T_EQUAL ) {
        if( stg_class == SC_EXTERN ) {
            stg_class = SC_STATIC;
            if( SymLevel == 0 ) {
                CompFlags.external_defn_found = 1;
                stg_class = SC_NULL;
            } else {
                CErr1( ERR_CANT_INITIALIZE_EXTERN_VAR );
            }
        }
        sym->stg_class = stg_class;
        NextToken();
        VarDeclEquals( sym, sym_handle );
        sym->flags |=  SYM_ASSIGNED;
    }
    SymReplace( sym, sym_handle );                      /* 06-jul-88 */
    if( old_sym_handle != 0 ) {
        sym_handle = 0;
    }
    return( sym_handle );
}

local void AdjSymTypeNode( SYMPTR sym, type_modifiers decl_mod )
{
    TYPEPTR     typ;

    if( decl_mod ) {
        typ = sym->sym_type;
        if( typ->decl_type == TYPE_FUNCTION ) {
            if( (sym->attrib & FLAG_LANGUAGES) != decl_mod ) {
                if( sym->attrib & FLAG_LANGUAGES ) {
                    CErr1( ERR_INVALID_DECLSPEC );
                } else {
                    sym->attrib |= decl_mod;
                    if( (typ->u.fn.decl_flags & FLAG_LANGUAGES) != decl_mod ) {
                        if( typ->u.fn.decl_flags & FLAG_LANGUAGES ) {
                            CErr1( ERR_INVALID_DECLSPEC );
                        } else {
                            sym->sym_type = FuncNode( typ->object, typ->u.fn.decl_flags | decl_mod, typ->u.fn.parms );
                        }
                    }
                }
            }
        } else {
            TYPEPTR     *xtyp;

            xtyp = &sym->sym_type;
            while( ( typ->object != NULL ) && ( typ->decl_type == TYPE_POINTER ) ) {
                xtyp = &typ->object;
                typ = typ->object;
            }
            if( typ->decl_type == TYPE_FUNCTION ) {
                if( (typ->u.fn.decl_flags & FLAG_LANGUAGES) != decl_mod ) {
                    if( typ->u.fn.decl_flags & FLAG_LANGUAGES ) {
                        CErr1( ERR_INVALID_DECLSPEC );
                    } else {
                        *xtyp = FuncNode( typ->object, typ->u.fn.decl_flags | decl_mod, typ->u.fn.parms );
                    }
                }
            } else {
                if( sym->attrib & FLAG_LANGUAGES ) {
                    CErr1( ERR_INVALID_DECLSPEC );
                } else {
                    sym->attrib |= decl_mod;
                }
            }
        }
    }
}

static SYM_HANDLE InitDeclarator( SYMPTR sym, decl_info const * const info, decl_state *state )
{
    SYM_HANDLE      sym_handle;
    SYM_HANDLE      old_sym_handle;
    type_modifiers  flags;
    TYPEPTR         typ;
    TYPEPTR         otyp;
    SYM_ENTRY       old_sym;

    if( ParmList != NULL ) {
        FreeParmList();
    }
    memset( sym, 0, sizeof( SYM_ENTRY ) );              /* 02-apr-91 */
    sym->name = "";
    flags = TypeQualifier();                            /* 08-nov-94 */
    if( flags & info->mod ) {
       CErr1( ERR_INV_TYPE );
    }
    flags |= info->mod;
    if( info->decl == DECLSPEC_DLLEXPORT ) {
        flags |= FLAG_EXPORT; //need to get rid of this
    }
    Declarator( sym, flags, info->typ, *state );
    if( sym->name[0] == '\0' ) {
        InvDecl();
        return( 0 );
    }
    typ = sym->sym_type;
    /* skip over typedef's  29-aug-89 */
    SKIP_TYPEDEFS( typ );
    if( info->stg == SC_TYPEDEF ) {
        if( CompFlags.extensions_enabled ) {            /* 24-mar-91 */
            old_sym_handle = SymLook( sym->info.hash_value, sym->name );
            if( old_sym_handle != 0 ) {
                SymGet( &old_sym, old_sym_handle );
                otyp = old_sym.sym_type;        /* skip typedefs 25-sep-92 */
                SKIP_TYPEDEFS( otyp );
                if( old_sym.stg_class == SC_TYPEDEF &&
                    old_sym.level == SymLevel &&
                    IdenticalType( typ, otyp ) ) {
                    return( 0 );        /* indicate already in symbol tab */
                }
            }
        }
        VfyNewSym( sym->info.hash_value, sym->name );
        sym->stg_class = info->stg;
        AdjSymTypeNode( sym, info->decl_mod );
        sym_handle = SymAdd( sym->info.hash_value, sym );
    } else {
        sym->declspec = info->decl;
        sym->naked = info->naked;
        if( sym->declspec == DECLSPEC_DLLEXPORT ) { //sync up flags
            sym->attrib |= FLAG_EXPORT; //need to get rid of this
        } else if( sym->attrib & FLAG_EXPORT ) {
            if( sym->declspec == DECLSPEC_NONE ) {
                sym->declspec = DECLSPEC_DLLEXPORT;
            } else if( sym->declspec  != DECLSPEC_DLLEXPORT ) {
                 CErr1( ERR_INVALID_DECLSPEC );
            }
        }
        AdjSymTypeNode( sym, info->decl_mod );
        if( typ->decl_type == TYPE_FUNCTION ) {
            sym_handle = FuncDecl( sym, info->stg, state );
        } else {
            sym_handle = VarDecl( sym, info->stg, state );
        }
    }
    return( sym_handle );
}

int DeclList( SYM_HANDLE *sym_head )
{
    decl_state          state;
    SYM_HANDLE          sym_handle;
    SYM_HANDLE          prevsym_handle;
    unsigned            line_num;
    auto SYM_ENTRY      sym;
    auto SYM_ENTRY      prevsym;
    decl_info           info;

    ParmList = NULL;
    prevsym_handle = 0;
    *sym_head = 0;
    for( ;; ) {
        for( ;; ) {
            for( ;; ) {
                while( CurToken == T_SEMI_COLON ) {
                    if( SymLevel == 0 ) {
                        if( !CompFlags.extensions_enabled ) {  /* 28-nov-94 */
                            CErr2p( ERR_EXPECTING_DECL_BUT_FOUND, ";" );
                        }
                    }
                    NextToken();
                }
                if( CurToken == T_EOF ) return( 0 );
                line_num = TokenLine;
                FullDeclSpecifier( &info );
                if( info.stg != SC_NULL  ||  info.typ != NULL ) break;
                if( SymLevel != 0 ) return( 0 );
                break;
            }
            state = DECL_STATE_NONE;
            if( info.typ == NULL ) {
                state |= DECL_STATE_NOTYPE;
                info.typ = TypeDefault();
            }
            if( info.stg == SC_NULL  && (state & DECL_STATE_NOTYPE) ) {
                if( TokenClass[ CurToken ] == TC_MODIFIER ) {
                } else {
                    switch( CurToken ) {
                    case T_ID:
                    case T_LEFT_PAREN:
                    case T_TIMES:
                        break;
                    case T_IF:
                    case T_FOR:
                    case T_WHILE:
                    case T_DO:
                    case T_SWITCH:
                    case T_BREAK:
                    case T_CONTINUE:
                    case T_CASE:
                    case T_DEFAULT:
                    case T_ELSE:
                    case T_GOTO:
                    case T_RETURN:
                        FlushBadCode();
                        continue;
                    default:
                        CErr2p( ERR_EXPECTING_DECL_BUT_FOUND, Tokens[CurToken] );

⌨️ 快捷键说明

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