?? ccheck.c
字號:
/****************************************************************************
*
* 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: Type checking routines.
*
****************************************************************************/
#include "cvars.h"
#include "cgswitch.h"
/* return types from TypeCheck */
enum {
TC_OK, /* types are OK */
TC_TYPE_MISMATCH, /* types mismatch */
TC_PARM_COUNT_MISMATCH, /* different # of parms */
TC_TYPE2_HAS_MORE_INFO, /* OK, but type2 has more information */
TC_PARM_TYPE_MISMATCH /* parms have different types */
};
typedef enum {
NO, /* not compatible */
PW, /* pointers with inconsistent levels of indirection */
PM, /* pointers point to different objects (Mismatch) 16-may-91 */
PC, /* might be compatible if integer value is 0 */
OK, /* compatible */
PQ, /* pointers to different qualified types */
PT, /* pointer truncated */
PX, /* pointer expanded */
PS, /* pointer to different signed types */
AC, /* assignment compatible */
} cmp_type;
typedef enum {
VC_CONVERT, /* "promote" void * to the type it is compared with */
VC_WARN /* warn for mismatching void * in function pointer argument lists */
} voidptr_cmp_type;
#define __ NO
local cmp_type const __FAR CompTable[TYPE_LAST_ENTRY][TYPE_LAST_ENTRY] = {
/* CH,UC,SH,US,IN,UI,LO,UL,DL,DU,FL,DB,PO,AR,ST,UN,FU,FI,VO,EN,TY,UF,DD,PC,WC,LD,FC,DC,LC,FI,FI,LI,B */
/* CHAR */ { OK,OK,OK,OK,OK,OK,AC,AC,AC,AC,AC,AC,PC,__,__,__,__,OK,__,OK,__,OK,__,__,__,AC,__,__,__,__,__,__,AC },
/* UCHAR */ { OK,OK,OK,OK,OK,OK,AC,AC,AC,AC,AC,AC,PC,__,__,__,__,OK,__,OK,__,OK,__,__,__,AC,__,__,__,__,__,__,AC },
/* SHORT */ { OK,OK,OK,OK,OK,OK,AC,AC,AC,AC,AC,AC,PC,__,__,__,__,OK,__,OK,__,OK,__,__,__,AC,__,__,__,__,__,__,AC },
/* USHORT */ { OK,OK,OK,OK,OK,OK,AC,AC,AC,AC,AC,AC,PC,__,__,__,__,OK,__,OK,__,OK,__,__,__,AC,__,__,__,__,__,__,AC },
/* INT */ { OK,OK,OK,OK,OK,OK,AC,AC,AC,AC,AC,AC,PC,__,__,__,__,OK,__,OK,__,OK,__,__,__,AC,__,__,__,__,__,__,AC },
/* UINT */ { OK,OK,OK,OK,OK,OK,AC,AC,AC,AC,AC,AC,PC,__,__,__,__,OK,__,OK,__,OK,__,__,__,AC,__,__,__,__,__,__,AC },
/* LONG */ { AC,AC,AC,AC,AC,AC,OK,OK,OK,OK,AC,AC,PC,__,__,__,__,OK,__,OK,__,OK,__,__,__,AC,__,__,__,__,__,__,AC },
/* ULONG */ { AC,AC,AC,AC,AC,AC,OK,OK,OK,OK,AC,AC,PC,__,__,__,__,OK,__,OK,__,OK,__,__,__,AC,__,__,__,__,__,__,AC },
/* LONG64 */ { AC,AC,AC,AC,AC,AC,OK,OK,OK,OK,AC,AC,PC,__,__,__,__,OK,__,OK,__,OK,__,__,__,AC,__,__,__,__,__,__,AC },
/* ULONG64 */ { AC,AC,AC,AC,AC,AC,OK,OK,OK,OK,AC,AC,PC,__,__,__,__,OK,__,OK,__,OK,__,__,__,AC,__,__,__,__,__,__,AC },
/* FLOAT */ { AC,AC,AC,AC,AC,AC,AC,AC,AC,AC,OK,AC,__,__,__,__,__,AC,__,AC,__,AC,__,__,__,AC,AC,AC,AC,AC,AC,AC,AC },
/* DOUBLE */ { AC,AC,AC,AC,AC,AC,AC,AC,AC,AC,AC,OK,__,__,__,__,__,AC,__,AC,__,AC,__,__,__,AC,AC,AC,AC,AC,AC,AC,AC },
/* POINTER */ { PC,PC,PC,PC,PC,PC,PC,PC,PC,PC,__,__,OK,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__ },
/* ARRAY */ { __,__,__,__,__,__,__,__,__,__,__,__,__,OK,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__ },
/* STRUCT */ { __,__,__,__,__,__,__,__,__,__,__,__,__,__,OK,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__ },
/* UNION */ { __,__,__,__,__,__,__,__,__,__,__,__,__,__,__,OK,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__ },
/* FUNCTION */ { __,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,OK,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__ },
/* FIELD */ { OK,OK,OK,OK,OK,OK,OK,OK,OK,OK,AC,AC,__,__,__,__,__,OK,__,__,__,OK,__,__,__,__,__,__,__,__,__,__,__ },
/* VOID */ { __,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__ },
/* ENUM */ { OK,OK,OK,OK,OK,OK,OK,OK,OK,OK,AC,AC,__,__,__,__,__,__,__,OK,__,__,__,__,__,__,__,__,__,__,__,__,__ },
/* TYPEDEF */ { __,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,OK,__,__,__,__,__,__,__,__,__,__,__,__ },
/* UFIELD */ { OK,OK,OK,OK,OK,OK,OK,OK,OK,OK,AC,AC,__,__,__,__,__,OK,__,__,__,OK,__,__,__,__,__,__,__,__,__,__,__ },
/* DOTDOTDOT*/ { __,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__ },
/* PLAIN CHAR*/{ __,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__ },
/* WCHAR */ { __,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__ },
/* LDOUBLE */ { AC,AC,AC,AC,AC,AC,AC,AC,AC,AC,AC,AC,__,__,__,__,__,__,__,__,__,__,__,__,__,OK,AC,AC,AC,AC,AC,AC,AC },
/* FCOMPLEX */ { __,__,__,__,__,__,__,__,__,__,AC,AC,__,__,__,__,__,__,__,__,__,__,__,__,__,AC,OK,AC,AC,AC,AC,AC,__ },
/* DCOMPLEX */ { __,__,__,__,__,__,__,__,__,__,AC,AC,__,__,__,__,__,__,__,__,__,__,__,__,__,AC,AC,OK,AC,AC,AC,AC,__ },
/* LDCOMPLEX*/ { __,__,__,__,__,__,__,__,__,__,AC,AC,__,__,__,__,__,__,__,__,__,__,__,__,__,AC,AC,AC,OK,AC,AC,AC,__ },
/* FIMAG */ { __,__,__,__,__,__,__,__,__,__,AC,AC,__,__,__,__,__,__,__,__,__,__,__,__,__,AC,AC,AC,AC,OK,AC,AC,__ },
/* DIMAG */ { __,__,__,__,__,__,__,__,__,__,AC,AC,__,__,__,__,__,__,__,__,__,__,__,__,__,AC,AC,AC,AC,AC,OK,AC,__ },
/* LDIMAG */ { __,__,__,__,__,__,__,__,__,__,AC,AC,__,__,__,__,__,__,__,__,__,__,__,__,__,AC,AC,AC,AC,AC,AC,OK,__ },
/* BOOL */ { AC,AC,AC,AC,AC,AC,AC,AC,AC,AC,AC,AC,__,__,__,__,__,__,__,__,__,__,__,__,__,AC,__,__,__,__,__,__,OK },
};
static cmp_type CompatibleType( TYPEPTR typ1, TYPEPTR typ2, int assignment );
static cmp_type DoCompatibleType( TYPEPTR typ1, TYPEPTR typ2, int top_level,
voidptr_cmp_type voidptr_cmp );
local int TypeCheck( TYPEPTR typ1, TYPEPTR typ2 );
static cmp_type InUnion( TYPEPTR typ1, TYPEPTR typ2, int reversed )
{
FIELDPTR field;
/* typ1->decl_type == TYPE_UNION */
if( typ2->decl_type == TYPE_UNION ) return( NO );
field = typ1->u.tag->u.field_list;
while( field != NULL ) {
if( reversed ) {
if( IdenticalType( typ2, field->field_type ) ) return( OK );
} else {
if( IdenticalType( field->field_type, typ2 ) ) return( OK );
}
field = field->next_field;
}
return( NO );
}
static int ChkParmPromotion( TYPEPTR *plist, int topLevelCheck ) /* 25-nov-94 */
{
TYPEPTR typ;
int parm_count;
parm_count = 1;
for( ;; ) {
typ = *plist++;
if( typ == NULL ) break;
while( typ->decl_type == TYPE_TYPEDEF ) typ = typ->object;
switch( typ->decl_type ) {
case TYPE_CHAR:
case TYPE_UCHAR:
case TYPE_SHORT:
if( CompFlags.strict_ANSI ) {
if ( topLevelCheck ) {
CErr2( ERR_PARM_TYPE_MISMATCH, parm_count );
}
return( TC_TYPE_MISMATCH );
}
break;
case TYPE_USHORT:
#if TARGET_SHORT != TARGET_INT
if( CompFlags.strict_ANSI ) {
if ( topLevelCheck ) {
CErr2( ERR_PARM_TYPE_MISMATCH, parm_count );
}
return( TC_TYPE_MISMATCH );
}
#endif
break;
case TYPE_FLOAT:
if ( topLevelCheck ) {
CErr2( ERR_PARM_TYPE_MISMATCH, parm_count );
}
return( TC_TYPE_MISMATCH );
default:
break;
}
}
return TC_OK;
}
TYPEPTR SkipTypeFluff( TYPEPTR typ )
{
while( typ->decl_type == TYPE_TYPEDEF ) {
typ = typ->object;
}
if( typ->decl_type == TYPE_ENUM ) typ = typ->object;
return( typ );
}
static cmp_type CompatibleStructs( TAGPTR tag1, TAGPTR tag2 )
{
FIELDPTR field1;
FIELDPTR field2;
TYPEPTR typ1;
TYPEPTR typ2;
if( tag1 == tag2 ) return( OK );
if( tag1->size != tag2->size ) return( NO );
field1 = tag1->u.field_list;
field2 = tag2->u.field_list;
/* if either struct is undefined, let's be conservative */
if( (field1 == NULL) || (field2 == NULL) ) return( NO );
for( ;; ) {
if( field1 == NULL ) break;
if( field2 == NULL ) break;
typ1 = field1->field_type;
while( typ1->decl_type == TYPE_TYPEDEF ) typ1 = typ1->object;
typ2 = field2->field_type;
while( typ2->decl_type == TYPE_TYPEDEF ) typ2 = typ2->object;
if( ! IdenticalType( typ1, typ2 ) ) {
if( (typ1->decl_type == TYPE_STRUCT &&
typ2->decl_type == TYPE_STRUCT ) ||
(typ1->decl_type == TYPE_UNION &&
typ2->decl_type == TYPE_UNION ) ) {
if( CompatibleStructs( typ1->u.tag, typ2->u.tag )
!= OK ) {
return( NO );
}
} else { /* 11-jul-90 */
return( NO );
}
}
field1 = field1->next_field;
field2 = field2->next_field;
}
/* one list longer than other (possible with -zp4) */
if( field1 != NULL || field2 != NULL ) return( NO );
return( OK );
}
int ChkCompatibleFunction( TYPEPTR typ1, TYPEPTR typ2, int topLevelCheck )
{
TYPEPTR *plist1;
TYPEPTR *plist2;
int parm_count;
plist1 = typ1->u.parms;
plist2 = typ2->u.parms;
if( plist1 != plist2 ) {
if( plist1 == NULL ) {
return ChkParmPromotion( plist2, topLevelCheck );
} else if( plist2 == NULL ) {
return ChkParmPromotion( plist1, topLevelCheck );
}
parm_count = 1;
for( ;; ) {
if( *plist1 == NULL && *plist2 == NULL ) break;
if( *plist1 == NULL || *plist2 == NULL ) {
if ( topLevelCheck ) {
CErr1( ERR_PARM_COUNT_MISMATCH );
}
return( TC_PARM_COUNT_MISMATCH );
}
if( ! IdenticalType( *plist1, *plist2 ) ) {
if ( topLevelCheck ) {
SetDiagType2( *plist1, *plist2 );
CErr2( ERR_PARM_TYPE_MISMATCH, parm_count );
SetDiagPop();
}
return( TC_PARM_TYPE_MISMATCH + parm_count );
}
++plist1;
++plist2;
++parm_count;
}
}
return( TC_OK ); /* indicate functions are compatible */
}
#define PTR_FLAGS (FLAG_MEM_MODEL|QUAL_FLAGS)
#define QUAL_FLAGS (FLAG_CONST|FLAG_VOLATILE|FLAG_UNALIGNED)
static cmp_type DoCompatibleType( TYPEPTR typ1, TYPEPTR typ2, int top_level,
voidptr_cmp_type voidptr_cmp )
{
cmp_type ret_val;
type_modifiers typ1_flags, typ2_flags;
typ1_flags = FLAG_NONE;
typ2_flags = FLAG_NONE;
ret_val = OK;
for( ;; ) { // * [] loop
typ1 = SkipTypeFluff( typ1 ); // skip typedefs go into enums base
typ2 = SkipTypeFluff( typ2 );
if( typ1 == typ2 )break;
if( typ1->decl_type != typ2->decl_type )break;
if( typ1->decl_type != TYPE_ARRAY && typ1->decl_type != TYPE_POINTER )break;
if( typ1->decl_type==TYPE_POINTER ) {
typ1_flags = typ1->u.p.decl_flags;
typ2_flags = typ2->u.p.decl_flags;
if( (typ1_flags & QUAL_FLAGS)!=(typ2_flags & QUAL_FLAGS) ) {
if( ret_val == OK ) { //PT is a worse case
ret_val = PQ;
}
}
if( (typ1_flags & FLAG_MEM_MODEL) != (typ2_flags & FLAG_MEM_MODEL) ) {
if( ((typ1_flags & FLAG_MEM_MODEL) != FLAG_NONE // if same as mem model ok
&& (typ2_flags & FLAG_MEM_MODEL) != FLAG_NONE)
|| TypeSize( typ1 ) != TypeSize( typ2 ) ) {
return( NO );
}
}
++top_level;
}
typ1 = typ1->object;
typ2 = typ2->object;
}
if( typ1 != typ2 ) { // if not equal see if diff by pointers
if( typ1->decl_type == TYPE_VOID || typ2->decl_type == TYPE_VOID ) {
// allow void ** with any **
if( top_level==1 || !CompFlags.strict_ANSI ) {
if ( voidptr_cmp == VC_WARN ||
(top_level > 1 && !CompFlags.extensions_enabled) ) {
CWarn1( WARN_PCTYPE_MISMATCH, ERR_PCTYPE_MISMATCH );
}
return( ret_val ); // void * and anything *
}
}
if( top_level > 0 ) { //for PW both types must start as pointers
if( typ1->decl_type == TYPE_POINTER
&& typ2->decl_type != TYPE_ARRAY ) {
ret_val = PW;
while( typ1->decl_type == TYPE_POINTER ) {
typ1 = typ1->object;
typ1 = SkipTypeFluff( typ1 );
++top_level;
}
} else if( typ2->decl_type == TYPE_POINTER
&& typ1->decl_type != TYPE_ARRAY ) {
ret_val = PW;
while( typ2->decl_type == TYPE_POINTER ) {
typ2 = typ2->object;
typ2 = SkipTypeFluff( typ2 );
++top_level;
}
}
}
}
if( typ1->decl_type==typ2->decl_type ) {
if( typ1->decl_type == TYPE_FUNCTION ) {
typ1_flags = typ1->type_flags;
typ2_flags = typ2->type_flags;
if( (typ1_flags & FLAG_LANGUAGES) != (typ2_flags & FLAG_LANGUAGES) ) {
ret_val = NO;
} else {
/* check to see if the two functions have identical parameters
and return types */
if( ChkCompatibleFunction( typ1, typ2, 0 ) != TC_OK ||
!IdenticalType( typ1->object, typ2->object ) ) {
CWarn1( WARN_PCTYPE_MISMATCH, ERR_PCTYPE_MISMATCH );
}
}
} else if( typ1->decl_type == TYPE_STRUCT || typ1->decl_type == TYPE_UNION ) {
/* 11-jul-90: allow pointers to different structs */
/* 29-oct-03: stop this for ANSI! */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -