cdecl2.c

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

C
1,744
字号
/****************************************************************************
*
*                            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:  C declarator processing.
*
****************************************************************************/


#include "cvars.h"
#include "cgswitch.h"
#include "i64.h"

extern  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( void )
{
    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( void )
{
    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;
    SKIP_TYPEDEFS( type_new );
    type_old = old_sym->sym_type;
    SKIP_TYPEDEFS( type_old );

    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
        SKIP_TYPEDEFS( ret_new );
        SKIP_TYPEDEFS( ret_old );
        /* 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;
    SYM_ENTRY           old_sym;
    struct enum_info    ei;
    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.fn.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;
                }
            }
            // check lang flags to make sure no one saw an incompatible prototype; if
            // previous prototype specified calling convention and later definition does
            // not, propagate the convention from the prototype
            if( (sym->attrib & FLAG_LANGUAGES) && !ChkCompatibleLanguage( sym->attrib, old_sym.attrib ) ) {
                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:
                    /* Allow the following:     void foo( void ); void _Export foo( void );
                     * IBM's compiler allows this, so does our C++ compiler; and it's real useful!
                     */
                    if( old_sym.declspec == DECLSPEC_DLLIMPORT || old_sym.declspec == DECLSPEC_NONE ) {
                        old_sym.declspec = DECLSPEC_DLLEXPORT;
                    } else {
                        CErr2p( ERR_MODIFIERS_DISAGREE, sym->name );
                    }
                    break;
                }
            }
            old_sym.naked |= sym->naked;
            if( stg_class == SC_STATIC && old_sym.stg_class == SC_EXTERN ) {
                /* can't redeclare extern function as static */
                /* NB: We may want to handle SC_FORWARD functions too! */
                CWarn( WARN_FUNCTION_STG_CLASS_REDECLARED,
                       ERR_FUNCTION_STG_CLASS_REDECLARED, sym->name );
            }
            CMemFree( sym->name );
            if( stg_class == SC_NULL && old_sym.stg_class != SC_FORWARD ) {     /* 05-jul-89 */
                stg_class = old_sym.stg_class;
            }
            if( old_sym.sym_type->decl_type == TYPE_FUNCTION ) {
                old_sym.sym_type = FuncNode( old_sym.sym_type->object,
                    old_sym.attrib, old_sym.sym_type->u.fn.parms );
            }
            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 );
            }

⌨️ 快捷键说明

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