Beispiel #1
0
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();
}
Beispiel #2
0
static void ChkUseful( void )
{
    if( CompFlags.useful_side_effect ) {
        CWarn1( WARN_USEFUL_SIDE_EFFECT, ERR_USEFUL_SIDE_EFFECT );
    } else {
        CWarn1( WARN_MEANINGLESS, ERR_MEANINGLESS );
    }
}
Beispiel #3
0
static void AssRangeChk( TYPEPTR typ1, TREEPTR opnd2 )
{
    unsigned       long high;
    if( opnd2->op.opr == OPR_PUSHINT ) {
        switch( typ1->decl_type ) {
        case TYPE_FIELD:
        case TYPE_UFIELD:
            high = 0xfffffffful >> (MAXSIZE - (typ1->u.f.field_width));
            if( opnd2->op.ulong_value > high ) {
                if( (opnd2->op.ulong_value | (high >> 1)) != ~0UL ) {
                    CWarn1( WARN_CONSTANT_TOO_BIG, ERR_CONSTANT_TOO_BIG );
                }
            }
            break;
        case TYPE_CHAR:
            if( opnd2->op.long_value > 127 ||
                opnd2->op.long_value < -128 ) {
                CWarn1( WARN_CONSTANT_TOO_BIG, ERR_CONSTANT_TOO_BIG );
            }
            break;
        case TYPE_UCHAR:
            if( opnd2->op.ulong_value > 0xff) {
                if( (opnd2->op.ulong_value | (0xff >> 1)) != ~0UL ) {
                    CWarn1( WARN_CONSTANT_TOO_BIG, ERR_CONSTANT_TOO_BIG );
                }
            }
            break;
        case TYPE_UINT:
            if( sizeof( target_uint ) > 2 ) {
                break;
            }
            // fall throught
        case TYPE_USHORT:
            if( opnd2->op.ulong_value > 0xffff ) {
                if( (opnd2->op.ulong_value | (0xffff >> 1)) != ~0UL ) {
                    CWarn1( WARN_CONSTANT_TOO_BIG, ERR_CONSTANT_TOO_BIG );
                }
            }
            break;
        case TYPE_INT:
            if( sizeof( target_uint ) > 2 ) {
                break;
            }
            // fall throught
        case TYPE_SHORT:
            if( opnd2->op.long_value > 32767 ||
                opnd2->op.long_value < -32768L ) {
                CWarn1( WARN_CONSTANT_TOO_BIG, ERR_CONSTANT_TOO_BIG );
            }
            break;
        default:
            break;
        }
    } else if( opnd2->op.opr == OPR_PUSHFLOAT ) {
Beispiel #4
0
local void InitCharArray( TYPEPTR typ )
{
    unsigned            len;
    STRING_LITERAL      *str_lit;
    unsigned long       size;
    DATA_QUAD           dq;

/*      This function handles the initialization of statements like:  */
/*              char  name[4] = "abcd";  */

    str_lit = GetLiteral();
    if( CompFlags.wide_char_string )
        CErr1( ERR_TYPE_MISMATCH );
    len = str_lit->length;
    if( typ->u.array->unspecified_dim )  typ->u.array->dimension = len;
    size = typ->u.array->dimension;
    if( len > size ) {
        if( (len - size) > 1 ) {
            CWarn1( WARN_LIT_TOO_LONG, ERR_LIT_TOO_LONG );
        }
        str_lit->length = len = size; /* chop the string */
    }
    dq.type = QDT_CONST;
    dq.flags = Q_DATA;
    dq.u.string_leaf = str_lit;
    GenDataQuad( &dq, len );
    if( size > len ) {                  /* if array > len of literal */
        ZeroBytes( size - len );
    }
    CompFlags.non_zero_data = 1;
}
Beispiel #5
0
local void ChkConstant( unsigned long value, unsigned long max_value )
{
    if( value > max_value ) {                   /* 13-sep-91 */
        if( (value | (max_value >> 1)) != ~0UL ) {
            CWarn1( WARN_CONSTANT_TOO_BIG, ERR_CONSTANT_TOO_BIG );
        }
    }
}
Beispiel #6
0
local void WantEOL( void )
{
    if( CompFlags.extensions_enabled ) {
        if( CurToken != T_NULL && CurToken != T_EOF ) {
            if( NestLevel == SkipLevel ) {
                CWarn1( WARN_JUNK_FOLLOWS_DIRECTIVE, ERR_JUNK_FOLLOWS_DIRECTIVE );
            }
        }
    } else {
        ChkEOL();
    }
}
Beispiel #7
0
static int tryBackSlashNewLine( void )
{
    int nc;

    // CurrChar is '\\' and SrcFile->column is up to date
    Blank1Count = 0;
    Blank2Count = 0;
    Tab1Count = 0;
    nc = getTestCharFromFile();
    if( CompFlags.extensions_enabled ) {
        while( nc == ' ' ) {
            ++Blank1Count;
            nc = getTestCharFromFile();
        }
        while( nc == '\t' ) {
            ++Tab1Count;
            nc = getTestCharFromFile();
        }
        while( nc == ' ' ) {
            ++Blank2Count;
            nc = getTestCharFromFile();
        }
    }
    if( nc == '\r' ) {
        nc = getTestCharFromFile();
    }
    if( nc == '\n' ) {
        if( CompFlags.scanning_cpp_comment && NestLevel == SkipLevel ) {
            CWarn1( WARN_SPLICE_IN_CPP_COMMENT, ERR_SPLICE_IN_CPP_COMMENT );
        }
        if( CompFlags.cpp_output ) {            /* 30-may-95 */
            if( CompFlags.in_pragma ) {
                CppPrtChar( '\\' );
                CppPrtChar( '\n' );
            } else if( CompFlags.cpp_line_wanted ) {
                CppPrtChar( '\n' );
            }
        }
        SrcFile->src_line_cnt++;
        SrcFile->src_loc.line++;
        SrcFileLoc = SrcFile->src_loc;
//      SrcFile->column = 0;
        return( GetNextChar() );
    }
    LastChar = nc;
    NextChar = getCharAfterBackSlash;
    return( '\\' );
}
Beispiel #8
0
static void CompareParms( TYPEPTR *master, TREEPTR parms, bool reverse )
{
    TYPEPTR     typ1;
    int         parmno;
    TREEPTR     parm;

    if( reverse ) {
        parms = reverse_parms_tree( parms );
    }
    typ1 = *master++;
    if( typ1 != NULL ) {
        if( typ1->decl_type == TYPE_VOID ) { /* type func(void);  */
            typ1 = NULL;                     /* indicate no parms */
        }
    }
    for( parmno = 1, parm = parms; ( typ1 != NULL ) && ( parm != NULL ); parm = parm->left, ++parmno ) {
        SKIP_TYPEDEFS( typ1 );
        // TODO is crap needed or has it been done
        if( typ1->decl_type == TYPE_FUNCTION ) {
            typ1 = PtrNode( typ1, FLAG_NONE, SEG_CODE );
        } else if( typ1->decl_type == TYPE_ARRAY ) {
            typ1 = PtrNode( typ1->object, FLAG_WAS_ARRAY, SEG_DATA );
        }
        /* check compatibility of parms */
        ParmAsgnCheck( typ1, parm, parmno, false );
        typ1 = *master++;
        if( typ1 != NULL && typ1->decl_type == TYPE_DOT_DOT_DOT ) {
            typ1 = NULL;
            parm = NULL;
            break;
        }
    }
    if( typ1 != NULL || parm != NULL ) {     /* should both be NULL now */
#if _CPU == 386
        /* can allow wrong number of parms with -3s option */
        if( !CompFlags.register_conventions ) {
            CWarn1( WARN_PARM_COUNT_MISMATCH, ERR_PARM_COUNT_WARNING );
        } else {
            CErr1( ERR_PARM_COUNT_MISMATCH );
        }
#else
        CErr1( ERR_PARM_COUNT_MISMATCH );
#endif
    }
    if( reverse ) {
        reverse_parms_tree( parms );
    }
}
Beispiel #9
0
local void InitWCharArray( TYPEPTR typ )
{
    unsigned            len;
    unsigned            i;
    STRING_LITERAL      *str_lit;
    unsigned            value;
    unsigned short      *pwc;
    unsigned long       size;
    DATA_QUAD           dq;

    dq.type = QDT_SHORT;
    dq.flags = Q_DATA;

/*      This function handles the initialization of statements like:  */
/*              wchar_t  name[5] = L"abcd";  */

    str_lit = GetLiteral();
    if( !CompFlags.wide_char_string )
        CErr1( ERR_TYPE_MISMATCH );
    len = str_lit->length / sizeof(unsigned short);
    if( typ->u.array->unspecified_dim ) {
        typ->u.array->dimension = len;
    }
    size = typ->u.array->dimension;
    if( len > size ) {
        if( (len - size) > 1 ) {
            CWarn1( WARN_LIT_TOO_LONG, ERR_LIT_TOO_LONG );
        }
        len = size;
    }
    pwc = (unsigned short *)str_lit->literal;
    i = 0;
    while( i < len ) {
        value = *pwc++;
        if( value != 0 ) CompFlags.non_zero_data = 1;
        dq.u.long_values[0] = value;
        GenDataQuad( &dq, sizeof( target_short ) );
        ++i;
    }
    if( i < size ) {
        ZeroBytes( (size - i) * sizeof(unsigned short) );
    }
    FreeLiteral( str_lit );
 }
Beispiel #10
0
/* 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 );
    }
}
Beispiel #11
0
static void DeadMsg( void )
/*************************/
{
    CWarn1( WARN_DEAD_CODE, ERR_DEAD_CODE );
    DeadCode = 2;   /* so we don't get more messages */
}
Beispiel #12
0
void Statement( void )
{
    LABEL_INDEX         end_of_func_label;
    SYM_HANDLE          func_result;
    TREEPTR             tree;
    bool                return_at_outer_level;
    bool                skip_to_next_token;
    bool                declaration_allowed;
    struct return_info  return_info;
    SYM_ENTRY           sym;

#ifndef NDEBUG
    if( DebugFlag >= 1 ) {
        printf( "***** line %u, func=%s\n", TokenLoc.line, CurFunc->name );
        PrintStats();
    }
#endif
    ++FuncCount;
    return_info.with = RETURN_WITH_NONE; /* indicate no return statements */
    return_info.with_expr = FALSE;
    CompFlags.label_dropped = 0;
    CompFlags.addr_of_auto_taken = 0;           /* 23-oct-91 */
    end_of_func_label = 0;
    return_at_outer_level = FALSE;              /* 28-feb-92 */
    declaration_allowed   = FALSE;
    DeadCode = 0;
    LoopDepth = 0;
    LabelIndex = 0;
    BlockStack = NULL;
    LoopStack = NULL;
    SwitchStack = NULL;
#ifdef __SEH__
    TryCount = -1;
    TryScope = -1;
#endif
    StartNewBlock();
    NextToken();                        // skip over {
    ++SymLevel;
    tree = LeafNode( OPR_LABELCOUNT );
    AddStmt( tree );
    if( GrabLabels() == 0 ) {                           /* 29-nov-94 */
        GetLocalVarDecls();
    }
    func_result = MakeNewSym( &sym, 'R', CurFunc->sym_type->object, SC_AUTO );
    sym.flags |= SYM_FUNC_RETURN_VAR;   /* 25-oct-91 */
    SymReplace( &sym, func_result );
    for( ;; ) {
        CompFlags.pending_dead_code = 0;
        if( GrabLabels() == 0 && declaration_allowed && IsDeclarator( CurToken ) ) {
            GetLocalVarDecls();
        }
        if( CompFlags.c99_extensions ) {
            declaration_allowed = TRUE;
        }
        skip_to_next_token = FALSE;
        switch( CurToken ) {
        case T_IF:
            StartNewBlock();
            NextToken();
            BlockStack->break_label = NextLabel();
            JumpFalse( BracketExpr(), BlockStack->break_label );
            /* 23-dec-88, only issue msg if ';' is on same line as 'if' */
            if( CurToken == T_SEMI_COLON  &&  SrcLoc.line == TokenLoc.line && SrcLoc.fno == TokenLoc.fno ) {
                SetErrLoc( &TokenLoc );
                NextToken();    /* look ahead for else keyword */
                if( CurToken != T_ELSE ) {              /* 02-apr-91 */
                    ChkUseful();                        /* 08-dec-88 */
                }
                InitErrLoc();
                break;
            }
            declaration_allowed = FALSE;
            continue;
        case T_WHILE:
            NewLoop();
            NextToken();
            BlockStack->break_label = NextLabel();
            if( !JumpFalse( BracketExpr(), BlockStack->break_label ) ) {
                BlockStack->break_label = 0;            /* 09-sep-92 */
            }
            if( CurToken == T_SEMI_COLON ) {            /* 08-dec-88 */
                if( ! CompFlags.useful_side_effect ) {
                    CWarn1( WARN_MEANINGLESS, ERR_MEANINGLESS );
                }
            }
            declaration_allowed = FALSE;
            continue;
        case T_DO:
            NewLoop();
            NextToken();
            if( CurToken == T_RIGHT_BRACE ) {
                CErr1( ERR_STMT_REQUIRED_AFTER_DO );
                break;
            }
            declaration_allowed = FALSE;
            continue;
        case T_FOR:
            ForStmt();
            declaration_allowed = FALSE;
            continue;
        case T_SWITCH:
            SwitchStmt();
            DeadCode = 1;
            declaration_allowed = FALSE;
            continue;
        case T_CASE:
            DeadCode = 0;
            CaseStmt();
            declaration_allowed = FALSE;
            continue;
        case T_DEFAULT:
            DefaultStmt();
            declaration_allowed = FALSE;
            continue;
        case T_BREAK:
            BreakStmt();
            DeadCode = 1;
            if( BlockStack->block_type != T_LEFT_BRACE ) break;
            continue;
        case T_CONTINUE:
            ContinueStmt();
            DeadCode = 1;
            if( BlockStack->block_type != T_LEFT_BRACE ) break;
            continue;
#ifdef __SEH__
        case T__LEAVE:
        case T___LEAVE:
            LeaveStmt();
            DeadCode = 1;
            if( BlockStack->block_type != T_LEFT_BRACE ) break;
            continue;
#endif
        case T_RETURN:
            ReturnStmt( func_result, &return_info );
            if( BlockStack->prev_block == NULL ) {      /* 28-feb-92 */
                return_at_outer_level = TRUE;
            }
            MustRecog( T_SEMI_COLON );
            if( SymLevel != 1  ||  CurToken != T_RIGHT_BRACE  ||
                    BlockStack->block_type != T_LEFT_BRACE ) {
                if( end_of_func_label == 0 ) {
                    end_of_func_label = NextLabel();
                }
                Jump( end_of_func_label );
            }
            if( BlockStack->block_type != T_LEFT_BRACE ) break;
            continue;
        case T_GOTO:
            GotoStmt();
            if( BlockStack->block_type != T_LEFT_BRACE ) break;
            continue;
        case T_SEMI_COLON:
            NextToken();
            if( BlockStack->block_type != T_LEFT_BRACE ) {
                if( CurToken == T_ELSE ) {
                    declaration_allowed = FALSE;
                }
                break;
            }
            continue;
        case T_LEFT_BRACE:
            LeftBrace();
            continue;
        case T_RIGHT_BRACE:
            if( BlockStack->block_type != T_LEFT_BRACE ) {
                CErr1( ERR_MISPLACED_RIGHT_BRACE );
            }
            if( BlockStack->prev_block == NULL ) {
                skip_to_next_token = TRUE;
            } else {
                NextToken();
            }
            break;
        case T_EXTERN:
        case T_STATIC:
        case T_AUTO:
        case T_REGISTER:
        case T_VOID:
        case T_CHAR:
        case T_SHORT:
        case T_INT:
        case T_LONG:
        case T_FLOAT:
        case T_DOUBLE:
        case T_SIGNED:
        case T_UNSIGNED:
            if( CompFlags.c99_extensions )
                CErr1( ERR_UNEXPECTED_DECLARATION );
            else
                CErr1( ERR_MISSING_RIGHT_BRACE );
            break;
        case T_EOF:
            CErr1( ERR_MISSING_RIGHT_BRACE );
            break;
#ifdef __SEH__
        case T__TRY:
        case T___TRY:
            TryStmt();
            continue;
#endif
        case T___ASM:
            AsmStmt();
            continue;
        default:
            if( DeadCode == 1 ) {
                DeadMsg();
            }
            StmtExpr();
            if( BlockStack->block_type != T_LEFT_BRACE ) break;
            continue;
        }
        EndOfStmt();
        if( BlockStack == NULL ) break;
        if( skip_to_next_token ) {
            NextToken();
        }
    }
    /* C99 has special semantics for return value of main() */
    if( CompFlags.c99_extensions && !strcmp( CurFunc->name, "main" ) ) {
        if( !return_at_outer_level ) {
            FixupC99MainReturn( func_result, &return_info );
            return_at_outer_level = TRUE;
        }
    }
    if( !return_info.with_expr ) {   /* no return values present */
        if( !DeadCode && !CurFunc->naked ) {
            ChkRetValue();
        }
    } else if( ! return_at_outer_level ) {              /* 28-feb-92 */
        if( ! DeadCode && !CurFunc->naked ) {
            CWarn( WARN_MISSING_RETURN_VALUE,
                   ERR_MISSING_RETURN_VALUE, CurFunc->name );
        }
    }
    if( end_of_func_label != 0 ) {
        DropLabel( end_of_func_label );
    }
    DeadCode = 0;
    tree->op.label_count = LabelIndex;
    tree = LeafNode( OPR_FUNCEND );
    if( !return_info.with_expr ) {
        tree->expr_type = NULL;
        tree->op.sym_handle = 0;
    } else {
        tree->op.sym_handle = func_result;
        SetFuncReturnNode( tree );
    }
    AddStmt( tree );
    AddSymList( CurFunc->u.func.locals );
    SrcLoc = TokenLoc;
    FreeLabels();
    if( skip_to_next_token ) {
        NextToken();
    }
    if( CompFlags.generate_prototypes ) {
        if( DefFile == NULL ) {
            OpenDefFile();
        }
        if( DefFile != NULL && CurFunc->stg_class == SC_NULL ) {
            /* function exported */
            DumpFuncDefn();
        }
    }

    if( Toggles & TOGGLE_INLINE ) {
        if( Inline_Threshold < NodeCount ) {
            CurFuncNode->op.func.flags &= ~FUNC_OK_TO_INLINE;
        }
    }
    if( VarParm( CurFunc ) ) {
        CurFuncNode->op.func.flags &= ~FUNC_OK_TO_INLINE;
    }
    NodeCount = 0;
    if( CompFlags.addr_of_auto_taken ) {                /* 23-oct-91 */
        CurFunc->flags &= ~ SYM_OK_TO_RECURSE;
    }
}
Beispiel #13
0
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 */
    }
}
Beispiel #14
0
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 enum 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_ARRAY && typ2->decl_type == TYPE_ARRAY ) {
            /* See C99, 6.7.5.2p5 */
            if( typ1->u.array->dimension && typ2->u.array->dimension ) {
                if( typ1->u.array->dimension != typ2->u.array->dimension ) {
                    ret_val = PM;
                }
            }
        }
        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 ** (but warn about it)
            if( top_level==1 || !CompFlags.strict_ANSI ) {
                if( voidptr_cmp == VC_WARN || (top_level > 1) ) {
                    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->u.fn.decl_flags;
            typ2_flags = typ2->u.fn.decl_flags;
            if( !ChkCompatibleLanguage( typ1_flags, typ2_flags ) ) {
                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! */
            if( ( typ1 != typ2 ) ) {
                // Types are not the same
                // if extensions are enabled, then we can do a compatible struct test
                if( CompFlags.extensions_enabled ) {
                    if( CompatibleStructs( typ1->u.tag, typ2->u.tag ) != OK) {
                        if( top_level > 0 ) {
                            if( ret_val != PW ) {
                                ret_val = PM;
                            } else {
                                ret_val = NO;
                            }
                        } else {
                            ret_val = NO;
                        }
                    }
                } else {
                    ret_val = NO;
                }
            }
        } else if( (TYPE_FIELD == typ1->decl_type) || (TYPE_UFIELD == typ1->decl_type) ) { /* CarlYoung 31-Oct-03 */
            if( typ2->u.f.field_width > typ1->u.f.field_width ) {
                ret_val = AC;
            }
        }
    } else if( typ1->decl_type == TYPE_UNION && top_level > 0 ) {
        if( InUnion( typ1, typ2, 0 ) != OK ) {
            ret_val = NO;
        } else {
            ret_val = PM;
        }
    } else if( typ2->decl_type == TYPE_UNION && top_level > 0 ) {
        if( InUnion( typ2, typ1, 1 )!= OK ) {
            ret_val = NO;
        } else {
            ret_val = PM;
        }
    } else if( typ1->decl_type == TYPE_ARRAY ) {
        TYPEPTR     typ = typ1->object;

        if( !IdenticalType( typ, typ2 ) ) {
            ret_val = NO;
            while( typ->decl_type == TYPE_ARRAY ) {
                typ = typ->object;
            }
            if( IdenticalType( typ, typ2 ) ) {
                ret_val = PM;
            }
        }
    } else if( typ2->decl_type == TYPE_ARRAY ) {
        TYPEPTR     typ = typ2->object;

        if( !IdenticalType( typ, typ1 ) ) {
            ret_val = NO;
            while( typ->decl_type == TYPE_ARRAY ) {
                typ = typ->object;
            }
            if( IdenticalType( typ, typ1 ) ) {
                ret_val = PM;
            }
        }
    } else if( typ1->decl_type >= TYPE_LAST_ENTRY  ||
            typ2->decl_type >= TYPE_LAST_ENTRY ) {
        ret_val = NO;
    } else if( top_level == 0 ) {
        ret_val = CompTable[ typ1->decl_type ][ typ2->decl_type ];
    } else {
        ret_val = NO;
        switch( typ1->decl_type ) {
        case TYPE_CHAR:
        case TYPE_SHORT:
        case TYPE_INT:
        case TYPE_LONG:
        case TYPE_LONG64:
            if( typ2->decl_type == typ1->decl_type+1 ) {
                ret_val = PS;
            } else if( TypeSize( typ1 ) ==   TypeSize( typ2 ) ) {
                ret_val = PM;
            }
            break;
        case TYPE_UCHAR:
        case TYPE_USHORT:
        case TYPE_UINT:
        case TYPE_ULONG:
        case TYPE_ULONG64:
            if( typ2->decl_type+1 == typ1->decl_type ) {
                ret_val = PS;
            } else if( TypeSize( typ1 ) ==   TypeSize( typ2 ) ) {
                ret_val = PM;
            }
            break;
        default:
            break;
        }
    }
    return( ret_val );
}