SYMBOL DefaultCtorFind( // GET SYMBOL FOR DEFAULT CTOR TYPE type, // - class type TOKEN_LOCN* err_locn, // - error location boolean optional ) // - TRUE ==> is optional { unsigned retn; // - return from attempt to find SYMBOL ctor; // - constructor retn = ClassDefaultCtorFind( type, &ctor, err_locn ); switch( retn ) { case CNV_OK : break; case CNV_IMPOSSIBLE : if( optional ) break; SetErrLoc( err_locn ); CErr2p( ERR_NO_DEFAULT_INIT_CTOR, type ); ctor = NULL; break; case CNV_AMBIGUOUS : if( optional ) break; SetErrLoc( err_locn ); CErr2p( ERR_NO_UNIQUE_DEFAULT_CTOR, type ); ctor = NULL; break; case CNV_ERR : ctor = NULL; break; #ifndef NDEBUG default : CFatal( "DefaultCtorFind -- impossible return" ); #endif } return ctor; }
/* 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; } }
void CppStackFini( void ) { struct cpp_info *cpp; while( (cpp = CppStack) != NULL ) { SetErrLoc( &cpp->src_loc ); CErr1( ERR_MISSING_CENDIF ); InitErrLoc(); CppStack = cpp->prev_cpp; CMemFree( cpp ); } CppStack = NULL; }
void SetFarHuge( SYMPTR sym, bool report ) { TYPEPTR typ; type_modifiers attrib; target_size size; #if _CPU != 8086 /* unused parameters */ (void)report; #endif #if _CPU == 8086 if( sym->attribs.declspec == DECLSPEC_DLLIMPORT || sym->attribs.declspec == DECLSPEC_DLLEXPORT ) { sym->mods |= FLAG_FAR; } else if( sym->mods & FLAG_EXPORT ) { sym->mods |= FLAG_FAR; } #endif size = SizeOfArg( sym->sym_type ); if( TargetSwitches & BIG_DATA ) { attrib = sym->mods; if( (attrib & MASK_ALL_MEM_MODELS) == 0 ) { if( size == 0 ) { /* unspecified array size */ if( sym->attribs.stg_class == SC_EXTERN ) { typ = sym->sym_type; if( typ->decl_type == TYPE_ARRAY ) { attrib |= FLAG_FAR; } } } else if( size > DataThreshold ) { attrib |= FLAG_FAR; } else if( CompFlags.strings_in_code_segment && ( sym->mods & FLAG_CONST ) ) { attrib |= FLAG_FAR; } #if _CPU == 8086 if( (attrib & FLAG_FAR) && size > 0x10000 ) { attrib &= ~FLAG_FAR; attrib |= FLAG_HUGE; } #endif sym->mods = attrib; } } #if _CPU == 8086 if( report && size > 0x10000 && (sym->mods & FLAG_HUGE) == 0 ) { SetErrLoc( &sym->src_loc ); CErr1( ERR_VAR_TOO_LARGE ); InitErrLoc(); } #endif }
void SetFarHuge( SYMPTR sym, int report ) { TYPEPTR typ; type_modifiers attrib; unsigned long size; report = report; /* in case not used */ #if _CPU == 8086 if( sym->declspec == DECLSPEC_DLLIMPORT || sym->declspec == DECLSPEC_DLLEXPORT ) { /* 16-dec-94 */ sym->attrib |= FLAG_FAR; } else if( sym->attrib & FLAG_EXPORT ) { sym->attrib |= FLAG_FAR; } #endif size = SizeOfArg( sym->sym_type ); if( TargetSwitches & BIG_DATA ) { attrib = sym->attrib; if( (attrib & MASK_ALL_MEM_MODELS) == 0 ) { if( size == 0 ) { /* unspecified array size */ if( sym->stg_class == SC_EXTERN ) { typ = sym->sym_type; if( typ->decl_type == TYPE_ARRAY ) { attrib |= FLAG_FAR; } } } else if( size > DataThreshold ) { attrib |= FLAG_FAR; } else if( CompFlags.strings_in_code_segment && ( sym->attrib & FLAG_CONST ) ) { attrib |= FLAG_FAR; } #if _CPU == 8086 if( (attrib & FLAG_FAR) && size > 0x10000 ) { attrib &= ~FLAG_FAR; attrib |= FLAG_HUGE; } #endif sym->attrib = attrib; } } #if _CPU == 8086 if( report && size > 0x10000 && !(sym->attrib & FLAG_HUGE) ) { SetErrLoc( &sym->src_loc ); CErr1( ERR_VAR_TOO_LARGE ); InitErrLoc(); } #endif }
/* 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 ); } }
TYPEPTR EnumDecl( int flags ) { TYPEPTR typ; TAGPTR tag; flags = flags; NextToken(); if( CurToken == T_ID ) { /* could be: (1) "enum" <id> ";" (2) "enum" <id> <variable_name> ";" (3) "enum" <id> "{" <enum_const_decl> ... "}" */ tag = TagLookup(); NextToken(); if( CurToken != T_LEFT_BRACE ) { typ = tag->sym_type; if( typ == NULL ) { CErr1( ERR_INCOMPLETE_ENUM_DECL ); typ = TypeDefault(); } else { if( typ->decl_type != TYPE_ENUM ) { /* 18-jan-89 */ CErr2p( ERR_DUPLICATE_TAG, tag->name ); } typ->u.tag = tag; } return( typ ); } tag = VfyNewTag( tag, TYPE_ENUM ); } else { tag = NullTag(); } typ = TypeNode( TYPE_ENUM, GetType( TYPE_INT ) ); typ->u.tag = tag; tag->sym_type = typ; tag->size = TARGET_INT; tag->u.enum_list = NULL; if( CurToken == T_LEFT_BRACE ) { const_val val; enum enum_rng index; enum enum_rng const_index; enum enum_rng start_index; enum enum_rng step; enum enum_rng error; uint64 n; uint64 Inc; bool minus; bool has_sign; ENUMPTR *prev_lnk; ENUMPTR esym; source_loc error_loc; char buff[50]; if( CompFlags.make_enums_an_int ) { start_index = ENUM_INT; } else { start_index = ENUM_S8; } const_index = ENUM_UNDEF; NextToken(); if( CurToken == T_RIGHT_BRACE ) { CErr1( ERR_EMPTY_ENUM_LIST ); } U32ToU64( 1, &Inc ); U64Clear( n ); minus = FALSE; has_sign = FALSE; step = 1; prev_lnk = &esym; esym = NULL; while( CurToken == T_ID ) { esym = EnumLkAdd( tag ); *prev_lnk = esym; prev_lnk = &esym->thread; error_loc = TokenLoc; NextToken(); if( CurToken == T_EQUAL ) { NextToken(); error_loc = TokenLoc; ConstExprAndType( &val ); switch( val.type ){ case TYPE_ULONG: case TYPE_UINT: case TYPE_ULONG64: minus = FALSE; break; default: if( val.value.u.sign.v ) { minus = TRUE; step = 2; } else { minus = FALSE; } break; } n = val.value; } else if( has_sign ) { if( n.u.sign.v ) { minus = TRUE; } else { minus = FALSE; } } for( index = start_index; index < ENUM_SIZE; index += step ) { if( minus ) { if( I64Cmp( &n, &( RangeTable[ index ][LOW] ) ) >= 0 ) break; } else { if( U64Cmp( &n, &( RangeTable[ index ][HIGH]) ) <= 0 ) break; } } error = ENUM_UNDEF; if( !CompFlags.extensions_enabled && ( index > ENUM_INT )) { error = ENUM_INT; } if( index >= ENUM_SIZE ) { // overflow signed maximum range if( error == ENUM_UNDEF ) { error = const_index; } } else if(( const_index == ENUM_SIZE - 1 ) && minus ) { // overflow unsigned maximum range by any negative signed value if( error == ENUM_UNDEF ) error = const_index; step = 1; } else { if( !has_sign && minus) { has_sign = TRUE; if( index < const_index ) { // round up to signed index = ( const_index + 1 ) & ~1; } } if( index > const_index ) { const_index = index; typ->object = GetType( ItypeTable[const_index].decl_type ); tag->size = ItypeTable[const_index].size; } } if( error != ENUM_UNDEF ) { SetErrLoc( &error_loc ); get_msg_range( buff, error ); CErr2p( ERR_ENUM_CONSTANT_OUT_OF_RANGE, buff ); InitErrLoc(); } esym->value = n; EnumTable[ esym->hash ] = esym; /* 08-nov-94 */ if( CurToken == T_RIGHT_BRACE ) break; U64Add( &n, &Inc, &n ); MustRecog( T_COMMA ); if( !CompFlags.extensions_enabled && !CompFlags.c99_extensions && ( CurToken == T_RIGHT_BRACE )) { ExpectIdentifier(); /* 13-may-91 */ } } MustRecog( T_RIGHT_BRACE ); } return( typ ); }
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; } }
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 */ } }