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