void CompatiblePtrType( TYPEPTR typ1, TYPEPTR typ2, TOKEN opr ) { SetDiagType3( typ1, typ2, opr ); /* Called with source, target. */ switch( CompatibleType( typ1, typ2, false, false ) ) { case PT: case PX: break; case PQ: if( !CompFlags.no_check_qualifiers ) { // else f**k em CWarn1( WARN_QUALIFIER_MISMATCH, ERR_QUALIFIER_MISMATCH ); } break; case PM: case NO: CWarn1( WARN_POINTER_TYPE_MISMATCH, ERR_POINTER_TYPE_MISMATCH ); break; case PS: CWarn1( WARN_SIGN_MISMATCH, ERR_SIGN_MISMATCH ); break; case PW: CWarn1( WARN_INCONSISTENT_INDIRECTION_LEVEL, ERR_INCONSISTENT_INDIRECTION_LEVEL ); break; case PC: CWarn1( WARN_PCTYPE_MISMATCH, ERR_PCTYPE_MISMATCH ); break; case OK: case AC: break; } SetDiagPop(); }
static typecheck_err ChkCompatibleFunctionParms( TYPEPTR typ1, TYPEPTR typ2, bool topLevelCheck ) { TYPEPTR *plist1; TYPEPTR *plist2; TYPEPTR p1; TYPEPTR p2; int parmno; typecheck_err rc; rc = TCE_OK; /* indicate functions are compatible */ plist1 = typ1->u.fn.parms; plist2 = typ2->u.fn.parms; if( plist1 != plist2 ) { if( plist1 == NULL ) { plist1 = plist2; plist2 = NULL; } if( plist2 == NULL ) { for( parmno = 1; (p1 = *plist1++) != NULL; ++parmno ) { if( p1->decl_type == TYPE_DOT_DOT_DOT ) { break; } if( !ChkParmPromotion( p1 ) ) { if( topLevelCheck ) { CErr2( ERR_PARM_TYPE_MISMATCH, parmno ); } rc = TCE_TYPE_MISMATCH; } } } else { p1 = *plist1++; p2 = *plist2++; for( parmno = 1; p1 != NULL && p2 != NULL; ++parmno ) { if( p1->decl_type == TYPE_DOT_DOT_DOT || p2->decl_type == TYPE_DOT_DOT_DOT ) { break; } if( !IdenticalType( p1, p2 ) ) { if( topLevelCheck ) { SetDiagType2( p1, p2 ); CErr2( ERR_PARM_TYPE_MISMATCH, parmno ); SetDiagPop(); } rc = TCE_TYPE_MISMATCH; } p1 = *plist1++; p2 = *plist2++; } if( p1 != NULL && p1->decl_type == TYPE_DOT_DOT_DOT || p2 != NULL && p2->decl_type == TYPE_DOT_DOT_DOT ) { p1 = NULL; p2 = NULL; } if( p1 != NULL || p2 != NULL ) { if( topLevelCheck ) { CErr1( ERR_PARM_COUNT_MISMATCH ); } rc = TCE_PARM_COUNT_MISMATCH; } } } return( rc ); }
/* Check parameters of function that were called before a prototype was seen */ extern void ChkCallParms( void ) { call_list *nextcall; nextcall = CallNodeList; while( nextcall != NULL ) { call_list *next; TREEPTR callnode; TREEPTR callsite; SYM_ENTRY sym; TYPEPTR typ; callnode = nextcall->callnode; if( callnode != NULL ) { callsite = callnode->left; // point to OPR_FUNCNAME node SymGet( &sym, callsite->op.sym_handle ); typ = sym.sym_type; SKIP_TYPEDEFS( typ ); if( !(sym.flags & SYM_TEMP) ) SetDiagSymbol( &sym, callsite->op.sym_handle ); if( typ->u.fn.parms != NULL ) { TREEPTR parms; bool reverse; parms = callnode->right; reverse = ( ParmsToBeReversed( sym.attrib, NULL ) && ( parms != NULL ) ); if( reverse ) { parms = reverse_parms_tree( parms ); } CompareParms( typ->u.fn.parms, parms, &nextcall->src_loc ); if( reverse ) { reverse_parms_tree( parms ); } } else { // Unprototyped function called. Note that for indirect calls, there // is no symbol associated with the function and diagnostic information // is hence limited. SetErrLoc( &nextcall->src_loc ); if( sym.flags & SYM_TEMP ) { CWarn( WARN_NONPROTO_FUNC_CALLED_INDIRECT, ERR_NONPROTO_FUNC_CALLED_INDIRECT ); } else { CWarn( WARN_NONPROTO_FUNC_CALLED, ERR_NONPROTO_FUNC_CALLED, SymName( &sym, callsite->op.sym_handle ) ); } } if( !(sym.flags & SYM_TEMP) ) { SetDiagPop(); } } next = nextcall->next; CMemFree( nextcall ); nextcall = next; } }
/* Check parameters of function that were called before a prototype was seen */ extern void ChkCallParms( void ) { call_list *nextcall; call_list *next; for( nextcall = CallNodeList; nextcall != NULL; nextcall = next ) { TREEPTR callnode; TREEPTR callsite; SYM_ENTRY sym; TYPEPTR typ; next = nextcall->next; callnode = nextcall->callnode; if( callnode != NULL ) { callsite = callnode->left; // point to OPR_FUNCNAME node SymGet( &sym, callsite->op.u2.sym_handle ); typ = sym.sym_type; SKIP_TYPEDEFS( typ ); if( (sym.flags & SYM_TEMP) == 0 ) SetDiagSymbol( &sym, callsite->op.u2.sym_handle ); SetErrLoc( &nextcall->src_loc ); if( typ->u.fn.parms != NULL ) { CompareParms( typ->u.fn.parms, callnode->right, ParmsToBeReversed( sym.mods, NULL ) ); } else { // Unprototyped function called. Note that for indirect calls, there // is no symbol associated with the function and diagnostic information // is hence limited. if( sym.flags & SYM_TEMP ) { CWarn1( WARN_NONPROTO_FUNC_CALLED_INDIRECT, ERR_NONPROTO_FUNC_CALLED_INDIRECT ); } else { CWarn2p( WARN_NONPROTO_FUNC_CALLED, ERR_NONPROTO_FUNC_CALLED, SymName( &sym, callsite->op.u2.sym_handle ) ); } } InitErrLoc(); if( (sym.flags & SYM_TEMP) == 0 ) { SetDiagPop(); } } CMemFree( nextcall ); } }
int ChkCompatibleFunction( TYPEPTR typ1, TYPEPTR typ2, int topLevelCheck ) { TYPEPTR *plist1; TYPEPTR *plist2; int parm_count; plist1 = typ1->u.fn.parms; plist2 = typ2->u.fn.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 */ }
static void CompareParms( TYPEPTR *master, TREEPTR parm, source_loc *src_loc ) { TYPEPTR typ; TYPEPTR typ2; int parm_num; cmp_type cmp; typ = *master++; if( typ != NULL ) { /* 27-feb-90 */ if( typ->decl_type == TYPE_VOID ) { /* type func(void); */ typ = NULL; /* indicate no parms */ } } parm_num = 1; while( ( typ != NULL ) && ( parm != NULL ) ) { SKIP_TYPEDEFS( typ ); // TODO is crap needed or has it been done if( typ->decl_type == TYPE_FUNCTION ) { typ = PtrNode( typ, FLAG_NONE, SEG_CODE ); } else if( typ->decl_type == TYPE_ARRAY ) { typ = PtrNode( typ->object, FLAG_WAS_ARRAY, SEG_DATA ); } typ2 = parm->expr_type; // typ2 will be NULL if parm is OPR_ERROR in which case an error // has already been generated if( typ2 != NULL ) { /* check compatibility of parms */ SetErrLoc( src_loc ); SetDiagType2 ( typ2, typ ); cmp = CompatibleType( typ, typ2, TRUE, IsNullConst( parm ) ); switch( cmp ) { case NO: case PT: case PX: case AC: CErr2( ERR_PARM_TYPE_MISMATCH, parm_num ); break; case PQ: if( !CompFlags.no_check_qualifiers ) { // else f**k em CWarn2( WARN_QUALIFIER_MISMATCH, ERR_PARM_QUALIFIER_MISMATCH, parm_num ); } break; case PM: /* 16-may-91 */ CWarn2( WARN_POINTER_TYPE_MISMATCH, ERR_PARM_POINTER_TYPE_MISMATCH, parm_num ); break; case PS: CWarn2( WARN_SIGN_MISMATCH, ERR_PARM_SIGN_MISMATCH, parm_num ); break; case PW: CWarn2( WARN_PARM_INCONSISTENT_INDIRECTION_LEVEL, ERR_PARM_INCONSISTENT_INDIRECTION_LEVEL, parm_num ); break; case PC: /* Allow only "void *p = int 0"; */ if( IsPointer( typ ) && parm->right->op.opr == OPR_PUSHINT ) { if( TypeSize(typ) != TypeSize(typ2) ) { CErr2( ERR_PARM_TYPE_MISMATCH, parm_num ); } else if( parm->right->op.ulong_value != 0 ) { CWarn1( WARN_NONPORTABLE_PTR_CONV, ERR_NONPORTABLE_PTR_CONV ); } } else { if( TypeSize(typ->object) == TypeSize(typ2->object) ) { CWarn2( WARN_POINTER_TYPE_MISMATCH, ERR_PARM_POINTER_TYPE_MISMATCH, parm_num ); } else { CErr2( ERR_PARM_TYPE_MISMATCH, parm_num ); } } break; case OK: break; } SetDiagPop(); InitErrLoc(); } typ = *master++; if( typ != NULL && typ->decl_type == TYPE_DOT_DOT_DOT ) return; parm = parm->left; ++parm_num; } if( typ != NULL || parm != NULL ) { /* should both be NULL now */ SetErrLoc( src_loc ); #if _CPU == 386 /* can allow wrong number of parms with -3s option; 06-dec-91 */ if( !CompFlags.register_conventions ) { CWarn1( WARN_PARM_COUNT_MISMATCH, ERR_PARM_COUNT_WARNING ); return; } #endif CErr1( ERR_PARM_COUNT_MISMATCH ); /* 18-feb-90 */ } }