⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cdecl2.c

📁 Open Watcom 的 C 编译器源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/****************************************************************************
*
*                            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:  WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
*               DESCRIBE IT HERE!
*
****************************************************************************/


#include "cvars.h"
#include "toggle.h"
#include "pragdefn.h"
#include "cgswitch.h"


TYPEPTR *MakeParmList( struct parm_list *, int, int );
struct parm_list *NewParm( TYPEPTR, struct parm_list * );
static TYPEPTR DeclPart2( TYPEPTR typ, type_modifiers mod );
static TYPEPTR DeclPart3( TYPEPTR typ, type_modifiers mod );
static void AbsDecl( SYMPTR sym, type_modifiers mod, TYPEPTR typ );

local void FreeParmList( void );
local void GetFuncParmList( void );

static int ThreadSeg;



void Chk_Struct_Union_Enum( TYPEPTR typ )
{
    while( typ->decl_type == TYPE_TYPEDEF ) {           /* 24-nov-94 */
        if( !(typ->type_flags & TF2_DUMMY_TYPEDEF) ) break;
        typ = typ->object;
    }
    switch( typ->decl_type ) {
    case TYPE_STRUCT:
    case TYPE_UNION:
        if( typ->u.tag->name[0] == '\0' ) {
            InvDecl();
        }
        break;
    case TYPE_ENUM:
        break;
    default:
        InvDecl();
    }
}


local void FlushBadCode()
{
    int         count;

    CErr1( ERR_STMT_MUST_BE_INSIDE_FUNCTION );
    count = 0;
    for(;;) {
        NextToken();
        if( CurToken == T_EOF ) return;
        if( CurToken == T_LEFT_BRACE ) ++count;
        if( CurToken == T_RIGHT_BRACE ) {
            if( count == 0 ) break;
            --count;
        }
    }
    NextToken();
}


static int SCSpecifier()
{
    stg_classes stg_class;

    stg_class = SC_NULL;        /* assume no storage class specified */
    if( TokenClass[ CurToken ] == TC_STG_CLASS ) {
        switch( CurToken ) {
        case T_EXTERN:  stg_class = SC_EXTERN;  break;
        case T_STATIC:  stg_class = SC_STATIC;  break;
        case T_TYPEDEF: stg_class = SC_TYPEDEF; break;
        case T_AUTO:    stg_class = SC_AUTO;    break;
        case T_REGISTER:stg_class = SC_REGISTER;break;
        default:
            break;
        }
        NextToken();
    }
    return( stg_class );
}


void InvDecl( void )
{
    CErr1( ERR_INVALID_DECLARATOR );
}

#define FUNC_MASK     (~(FLAG_INLINE | FLAG_LOADDS | FLAG_EXPORT | FLAG_LANGUAGES))
local void CmpFuncDecls( SYMPTR new_sym, SYMPTR old_sym )
{
    TYPEPTR     type_new, type_old;

    if( (new_sym->attrib & FUNC_MASK) != (old_sym->attrib & FUNC_MASK)){
        CErr2p( ERR_MODIFIERS_DISAGREE, new_sym->name );
    }

/*      check for conflicting information */
/*      skip over TYPEDEF's   29-aug-89   */
    type_new = new_sym->sym_type;
    while( type_new->decl_type == TYPE_TYPEDEF ) type_new = type_new->object;
    type_old = old_sym->sym_type;
    while( type_old->decl_type == TYPE_TYPEDEF ) type_old = type_old->object;

    SetDiagType2( type_new->object, type_old->object );
    if( ! IdenticalType( type_new->object, type_old->object ) ) {
        TYPEPTR     ret_new, ret_old;

        ret_new = type_new->object;                    /* save return types */
        ret_old = type_old->object;
        // skip over typedef's 18-may-95
        while( ret_new->decl_type == TYPE_TYPEDEF ) ret_new = ret_new->object;
        while( ret_old->decl_type == TYPE_TYPEDEF ) ret_old = ret_old->object;
        /* don't reorder this expression */
        if( old_sym->stg_class != SC_FORWARD ){
            CErr2p( ERR_INCONSISTENT_TYPE, new_sym->name );
        }else if( ret_new->decl_type != TYPE_VOID
               || (old_sym->flags & SYM_TYPE_GIVEN ) ){ //return value used in forward
            CErr2p( ERR_INCONSISTENT_TYPE, new_sym->name );
        }
    }
    SetDiagPop();

    /* check types of parms, including promotion */
    ChkCompatibleFunction(type_new, type_old, 1);
}

local SYM_HANDLE FuncDecl( SYMPTR sym, stg_classes stg_class, decl_state *state )
{
    SYM_HANDLE  sym_handle;
    SYM_HANDLE  old_sym_handle;
    auto SYM_ENTRY old_sym;
    auto struct enum_info ei;
    auto SYM_ENTRY sym_typedef;
    TYPEPTR     old_typ;
    SYM_NAMEPTR sym_name;
    char        *name;
    int         sym_len;

    PrevProtoType = NULL;                               /* 12-may-91 */
    // Warn if assuming 'int' return type - should be an error in strict C99 mode
    if( *state & DECL_STATE_NOTYPE ) {
        CWarn( WARN_NO_RET_TYPE_GIVEN, ERR_NO_RET_TYPE_GIVEN, sym->name );
    }
    sym->rent = FALSE;   //Assume not override aka re-entrant
    if( CompFlags.rent && (sym->declspec == DECLSPEC_DLLIMPORT) ){
        sym->rent = TRUE;
    }
    if( stg_class == SC_REGISTER  ||
        stg_class == SC_AUTO  ||
        stg_class == SC_TYPEDEF ) {
            CErr1( ERR_INVALID_STG_CLASS_FOR_FUNC );
            stg_class = SC_NULL;
    }
    old_sym_handle = SymLook( sym->info.hash_value, sym->name );
    if( old_sym_handle == 0 ) {
        EnumLookup( sym->info.hash_value, sym->name, &ei );/* 22-dec-88 */
        if( ei.level >= 0 ) {       /* if enum was found */
            CErr2p( ERR_SYM_ALREADY_DEFINED, sym->name );
        }
        sym_handle = SymAddL0( sym->info.hash_value, sym );
    } else {
        SymGet( &old_sym, old_sym_handle );
        SetDiagSymbol( &old_sym, old_sym_handle );
        if( (old_sym.flags & SYM_FUNCTION) == 0 ) {
            CErr2p( ERR_SYM_ALREADY_DEFINED_AS_VAR, sym->name );
            //02-jun-89 sym_handle = old_sym_handle;                /* 05-apr-89 */
            sym_handle = SymAddL0( sym->info.hash_value, sym );/* 02-jun-89 */
        } else {
            CmpFuncDecls( sym, &old_sym );
            PrevProtoType = old_sym.sym_type;               /* 12-may-91 */
            if( (old_sym.flags & SYM_DEFINED) == 0 ) {
                if( sym->sym_type->u.parms != NULL  ||      /* 11-jul-89 */
                   ( CurToken != T_COMMA &&                    /* 18-jul-89 */
                    CurToken != T_SEMI_COLON ) ) {
                    old_typ = old_sym.sym_type;
                    if( old_typ->decl_type == TYPE_TYPEDEF &&
                       old_typ->object->decl_type == TYPE_FUNCTION ) {
                        SymGet( &sym_typedef, old_typ->u.typedefn );
                        sym_name = SymName( &sym_typedef,
                                           old_typ->u.typedefn );
                        sym_len = far_strlen_plus1( sym_name );
                        name = CMemAlloc( sym_len );
                        far_memcpy( name, sym_name, sym_len );
                        XferPragInfo( name, sym->name );
                        CMemFree( name );
                    }
                    old_sym.sym_type = sym->sym_type;
                    old_sym.d.defn_line = sym->d.defn_line;
                    old_sym.defn_file_index = sym->defn_file_index;
                }
            }
            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->attrib & FLAG_INLINE) != (old_sym.attrib & FLAG_INLINE) ){
                old_sym.attrib |= FLAG_INLINE; //either is inline
            }
            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;
                }
            }
            CMemFree( sym->name );
            if( stg_class == SC_NULL && old_sym.stg_class != SC_FORWARD ){   /* 05-jul-89 */
                stg_class = old_sym.stg_class;
            }
            memcpy( sym, &old_sym, sizeof( SYM_ENTRY ) );
            sym_handle = old_sym_handle;
        }
        SetDiagPop();
    }
    sym->flags |= SYM_FUNCTION;
    if( (sym->flags & SYM_DEFINED) == 0 ) {
        if( sym->attrib & FLAG_INLINE ){
            sym->flags |= SYM_IGNORE_UNREFERENCE;
            stg_class = SC_STATIC;
        }else if( stg_class == SC_NULL ){
            stg_class = SC_EXTERN;  /* SC_FORWARD; */
        }
        sym->stg_class = stg_class;
    }
    return( sym_handle );
}

TYPEPTR SkipDummyTypedef( TYPEPTR typ )                 /* 25-nov-94 */
{
    while( typ->decl_type == TYPE_TYPEDEF &&
           (typ->type_flags & TF2_DUMMY_TYPEDEF) ) {
        typ = typ->object;
    }
    return( typ );
}

#define QUAL_FLAGS (FLAG_CONST|FLAG_VOLATILE|FLAG_UNALIGNED)
#define ATTRIB_MASK     (~(FLAG_INLINE | FLAG_LOADDS | FLAG_EXPORT | FLAG_LANGUAGES))
local SYM_HANDLE VarDecl( SYMPTR sym, stg_classes stg_class, decl_state *state )
{
    int         which;
    TYPEPTR     typ;
    SYM_HANDLE  sym_handle;
    SYM_HANDLE  old_sym_handle;
    SYM_ENTRY   old_sym;
    SYM_ENTRY   sym2;

    // Warn if neither type nor storage class were given; this should probably be
    // an error in strict C89 (and naturally C99) mode
    if( (stg_class == SC_NULL) && (*state & DECL_STATE_NOTYPE) && !(*state & DECL_STATE_NOSTWRN) ) {
        CWarn( WARN_NO_STG_OR_TYPE, ERR_NO_STG_OR_TYPE );
        *state |= DECL_STATE_NOSTWRN;   // Only warn once for each declarator list
    }

    // Additionally warn if assuming 'int' type - should be an error in strict C99 mode
    if( *state & DECL_STATE_NOTYPE ) {
        CWarn( WARN_NO_DATA_TYPE_GIVEN, ERR_NO_DATA_TYPE_GIVEN, sym->name );
    }
    if( CompFlags.rent ) {
        sym->rent = TRUE; //Assume instance data
    } else {
        sym->rent = FALSE;//Assume non instance data
    }
    if( sym->naked ) {         /* 25-jul-95 */
        CErr1( ERR_INVALID_DECLSPEC );
    }

    if( SymLevel == 0 )
    {
        /*
        //  SymLevel == 0 is global scope (SymLevel is the count of nested {'s)
        */
        if( stg_class == SC_AUTO  ||  stg_class == SC_REGISTER ) {
            CErr1( ERR_INV_STG_CLASS_FOR_GLOBAL );
            stg_class = SC_STATIC;
        } else if( stg_class == SC_NULL ) {
            CompFlags.external_defn_found = 1;
        }
        if( sym->declspec == DECLSPEC_THREAD ) {          /* 25-jul-95 */
            if( !CompFlags.thread_data_present ){
                ThreadSeg = DefThreadSeg();
                CompFlags.thread_data_present = 1;
            }
            sym->u.var.segment = ThreadSeg;
        }
    }
    else
    {
        /*
        //  SymLevel != 0 is function scoped (SymLevel is the count of nested {'s)
        */
        if( stg_class == SC_NULL ) {
            stg_class = SC_AUTO;
        }
        if( stg_class == SC_AUTO  ||  stg_class == SC_REGISTER ) {
            if( sym->attrib & FLAG_LANGUAGES ){
                CErr1( ERR_INVALID_DECLARATOR );
            }
            if( sym->declspec != DECLSPEC_NONE ) {          /* 25-jul-95 */
                CErr1( ERR_INVALID_DECLSPEC );
            }
            /*
            // Local variables in stack will be far when SS != DS (/zu)
            // (applies only to auto vars, functions params are handled
            // NOT here but in "cexpr2.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 ) {
            if( old_sym.stg_class == SC_EXTERN  &&  stg_class == SC_EXTERN ) {
                SetDiagSymbol( &old_sym, old_sym_handle );
                if( ! IdenticalType( old_sym.sym_type, sym->sym_type ) ) {
                    CErr2p( ERR_TYPE_DOES_NOT_AGREE, 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 ){

⌨️ 快捷键说明

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