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 + -
显示快捷键?