#include "compiler/CFunc.h" #include "compiler/CABI.h" #include "compiler/CClass.h" #include "compiler/CDecl.h" #include "compiler/CError.h" #include "compiler/CException.h" #include "compiler/CExpr.h" #include "compiler/CInit.h" #include "compiler/CInline.h" #include "compiler/CInt64.h" #include "compiler/CMachine.h" #include "compiler/CMangler.h" #include "compiler/CParser.h" #include "compiler/CPrepTokenizer.h" #include "compiler/CSOM.h" #include "compiler/CTemplateTools.h" #include "compiler/CodeGen.h" #include "compiler/CompilerTools.h" #include "compiler/Exceptions.h" #include "compiler/FuncLevelAsmPPC.h" #include "compiler/InlineAsmPPC.h" #include "compiler/ObjGenMachO.h" #include "compiler/Switch.h" #include "compiler/objects.h" #include "compiler/scopes.h" #include "compiler/types.h" #ifdef __MWERKS__ #pragma options align=mac68k #endif struct CFuncSave { CScopeSave scope; ObjectList *arguments; ObjectList *locals; CLabel *labels; Statement *curstmt; DeclBlock *firstblock; DeclBlock *currentblock; ExceptionAction *cexcept_dobjstack; CLabel *sinit_label; ENode *ainit_expr; CtorChain *ctor_chain; ParserTryBlock *trychain; TempNodeCB cinit_tempnodefunc; HashNameNode *tkidentifier; Object *sinit_first_object; FileOffsetInfo cparser_fileoffset; TStreamElement symdecltoken; SInt32 functionbodyoffset; HashNameNode *functionbodypath; SInt32 symdecloffset; SInt32 symdeclend; SInt32 sourceoffset; HashNameNode *sourcefilepath; SInt32 curstmtvalue; NameObjCheckCB name_obj_check; FuncArg *check_arglist; short blockcount; short localcount; short tk; AccessType global_access; Boolean cexcept_hasdobjects; Boolean ainit_only_one; Boolean cfunc_is_extern_c; Boolean temp_reference_init; }; #ifdef __MWERKS__ #pragma options align=reset #endif FuncArg elipsis; FuncArg oldstyle; ObjectList *arguments; ObjectList *locals; short localcount; SInt32 curstmtvalue; SInt32 sourceoffset; HashNameNode *sourcefilepath; SInt32 functionbodyoffset; HashNameNode *functionbodypath; InitExpr *init_expressions; CLabel *Labels; CtorChain *ctor_chain; Statement *curstmt; static short temp_destructor_object_regmem; static short temp_destructor_objects; static short temp_expression_has_conditionals; static DeclBlock *firstblock; static DeclBlock *currentblock; static short blockcount; static Object *sinit_first_object; static CLabel *sinit_label; static Boolean ainit_only_one; static ENode *ainit_expr; static FuncArg *check_arglist; static Boolean cfunc_is_extern_c; static short cfunc_staticvarcount; static void *destroyobjects; static Boolean cfunc_hasdtortemp; // forward decls static void statement(DeclThing *thing); static void CFunc_LoopIncrement(void) { if (curstmtvalue >= 0x1000) { if (curstmtvalue >= 0xF000) curstmtvalue++; else curstmtvalue += 0x1000; } else { curstmtvalue <<= 3; } } static void CFunc_LoopDecrement(void) { if (curstmtvalue > 0x1000) { if (curstmtvalue > 0xF000) curstmtvalue--; else curstmtvalue -= 0x1000; } else { curstmtvalue >>= 3; } if (curstmtvalue < 1) curstmtvalue = 1; } DeclBlock *CFunc_NewDeclBlock(void) { DeclBlock *block; NameSpace *nspace; block = lalloc(sizeof(DeclBlock)); if (firstblock) { currentblock->next = block; currentblock = block; } else { firstblock = block; currentblock = block; } block->index = blockcount++; block->parent_nspace = cscope_current; block->dobjstack = cexcept_dobjstack; nspace = CScope_NewListNameSpace(NULL, 0); nspace->parent = cscope_current; cscope_current = nspace; return block; } void CFunc_RestoreBlock(DeclBlock *block) { if (curstmt && curstmt->dobjstack != cexcept_dobjstack) { Statement *stmt = CFunc_AppendStatement(ST_EXPRESSION); stmt->expr = nullnode(); } cscope_current = block->parent_nspace; cexcept_dobjstack = block->dobjstack; } void CFunc_SetupLocalVarInfo(Object *obj) { obj->u.var.info = CodeGen_GetNewVarInfo(); obj->u.var.info->func = cscope_currentfunc; if (obj->sclass == TK_REGISTER) { if (!copts.optimize_for_size) obj->u.var.info->usage = 100; else obj->u.var.info->usage = 5; } if (obj->type && is_volatile_object(obj)) obj->u.var.info->noregister = 1; } static void adjustargumenttype(DeclInfo *declinfo) { switch (declinfo->thetype->type) { case TYPECLASS: if (TYPE_CLASS(declinfo->thetype)->sominfo) { CError_Error(CErrorStr284); declinfo->thetype = TYPE(&stsignedint); } break; case TYPEFUNC: makethetypepointer(declinfo, 0); return; case TYPEARRAY: declinfo->thetype = CDecl_NewPointerType(TPTR_TARGET(declinfo->thetype)); return; case TYPETEMPLATE: if (TYPE_TEMPLATE(declinfo->thetype)->dtype == TEMPLDEP_ARRAY) declinfo->thetype = CDecl_NewPointerType(TYPE_TEMPLATE(declinfo->thetype)->u.array.type); return; } if (!CanCreateObject(declinfo->thetype)) declinfo->thetype = TYPE(&stsignedint); } static FuncArg *CFunc_IsInArgList(FuncArg *list, HashNameNode *name) { while (list) { if (name == list->name) return list; list = list->next; } return NULL; } static Object *CFunc_IsInObjList(ObjectList *list, HashNameNode *name) { while (list) { if (name == list->object->name) return list->object; list = list->next; } return NULL; } static void CFunc_AppendArg(FuncArg **list, FuncArg *arg) { FuncArg *tail; if ((tail = *list)) { while (tail->next) tail = tail->next; tail->next = arg; } else { *list = arg; } } static void identifier_list(DeclInfo *declinfo) { FuncArg *arg; declinfo->x45 = 1; while (1) { if (tk != TK_IDENTIFIER) { CError_Error(CErrorStr121); } else { if (CFunc_IsInArgList(declinfo->x18, tkidentifier)) CError_Error(CErrorStr122, tkidentifier->name); arg = CParser_NewFuncArg(); arg->name = tkidentifier; CFunc_AppendArg(&declinfo->x18, arg); declinfo->x44 = 1; } if ((tk = lex()) != ',') break; tk = lex(); } } static Boolean defarg_name_obj_check(HashNameNode *name, Object *obj) { FuncArg *arg; if (name) { for (arg = check_arglist; arg; arg = arg->next) { if (arg->name == name) { CError_Error(CErrorStr205); return 0; } } } if (obj && obj->datatype == DLOCAL) { CError_Error(CErrorStr205); return 0; } return 1; } ENode *CFunc_DefaultArg(Type *type, UInt32 qual, FuncArg *args) { TStreamElement *element; ENode *expr; ENode *templdepexpr; name_obj_check = defarg_name_obj_check; check_arglist = args; expr = conv_assignment_expression(); name_obj_check = NULL; if ( !CTemplTool_IsTemplateArgumentDependentExpression(expr) && !CTemplTool_IsTemplateArgumentDependentType(type) ) { expr = argumentpromotion(expr, type, qual, 1); } else { element = CPrep_CurStreamElement(); if (element && element->tokenfile) { templdepexpr = CExpr_NewTemplDepENode(TDE_SOURCEREF); templdepexpr->data.templdep.u.sourceref.expr = expr; templdepexpr->data.templdep.u.sourceref.token = galloc(sizeof(TStreamElement)); *templdepexpr->data.templdep.u.sourceref.token = *element; expr = templdepexpr; } } return CInline_CopyExpression(expr, CopyMode1); } static FuncArg *parameter_list(DeclInfo *declinfo) { Boolean flag26; FuncArg *args; FuncArg *arg; DeclInfo my_di; Boolean isArray; args = NULL; flag26 = 1; while (1) { if (tk == TK_ELLIPSIS) { if (flag26) { if (!copts.cplusplus && copts.ANSI_strict) CError_Warning(CErrorStr127); args = &elipsis; } else { CFunc_AppendArg(&args, &elipsis); } tk = lex(); return args; } memclrw(&my_di, sizeof(my_di)); CParser_GetDeclSpecs(&my_di, 0); if (my_di.x48) CError_Error(CErrorStr127); if ( my_di.storageclass && my_di.storageclass != TK_REGISTER && (!copts.cplusplus || my_di.storageclass != TK_AUTO) ) { CError_Error(CErrorStr127); my_di.storageclass = 0; } my_di.name = NULL; scandeclarator(&my_di); if (flag26) { flag26 = 0; if (my_di.thetype == &stvoid) { if (my_di.storageclass || my_di.qual || my_di.name) CError_Error(CErrorStr127); return NULL; } } isArray = IS_TYPE_ARRAY(my_di.thetype); adjustargumenttype(&my_di); if (my_di.name) { if (args && CFunc_IsInArgList(args, my_di.name)) CError_Error(CErrorStr122, my_di.name->name); } else { my_di.name = no_name_node; } if (my_di.thetype == &stvoid) CError_Error(CErrorStr126); arg = CParser_NewFuncArg(); arg->name = my_di.name; arg->type = my_di.thetype; arg->qual = my_di.qual; arg->sclass = my_di.storageclass; arg->is_array = isArray; CFunc_AppendArg(&args, arg); if (copts.cplusplus && tk == '=') { tk = lex(); arg->dexpr = CFunc_DefaultArg(arg->type, arg->qual, args); } if (tk != ',') { if (tk != TK_ELLIPSIS || !copts.cplusplus) return args; } else { tk = lex(); } } } Boolean CFunc_ParseFakeArgList(Boolean flag) { DeclInfo di; if (tk == TK_ELLIPSIS) return 1; do { memclrw(&di, sizeof(di)); CParser_GetDeclSpecs(&di, 0); if (di.x48) return 0; scandeclarator(&di); if (tk == '=') { tk = lex(); assignment_expression(); } switch (tk) { case TK_ELLIPSIS: return 1; case ',': if (!flag) tk = lex(); else return 1; break; default: return 0; } } while (tk != TK_ELLIPSIS); return 1; } FuncArg *parameter_type_list(DeclInfo *declinfo) { FuncArg *args; NameSpace *nspace; Boolean save_in_func_arglist; declinfo->x44 = 0; declinfo->x45 = 0; declinfo->x1C = NULL; if (tk == TK_ELLIPSIS || isdeclaration(0, 0, 0, 0)) { if (!copts.cplusplus) { nspace = CScope_NewListNameSpace(NULL, 0); nspace->parent = cscope_current; cscope_current = nspace; save_in_func_arglist = in_func_arglist; in_func_arglist = 1; args = parameter_list(declinfo); in_func_arglist = save_in_func_arglist; cscope_current = nspace->parent; if (!CScope_IsEmptyNameSpace(nspace)) declinfo->x1C = nspace; } else { args = parameter_list(declinfo); } } else if (copts.cplusplus) { args = NULL; if (tk != ')') CError_Error(CErrorStr127); } else { identifier_list(declinfo); args = &oldstyle; } return args; } CLabel *findlabel(void) { CLabel *scan; for (scan = Labels; scan; scan = scan->next) { if (tkidentifier == scan->name) return scan; } return NULL; } CLabel *newlabel(void) { CLabel *label = lalloc(sizeof(CLabel)); memclrw(label, sizeof(CLabel)); label->name = label->uniquename = CParser_GetUniqueName(); return label; } Statement *CFunc_AppendStatement(StatementType sttype) { Statement *stmt = lalloc(sizeof(Statement)); stmt->next = NULL; stmt->type = sttype; stmt->value = curstmtvalue; stmt->flags = 0; stmt->sourceoffset = sourceoffset; stmt->sourcefilepath = sourcefilepath; stmt->dobjstack = cexcept_dobjstack; curstmt->next = stmt; curstmt = stmt; return stmt; } Statement *CFunc_InsertStatement(StatementType sttype, Statement *after) { Statement *stmt = lalloc(sizeof(Statement)); stmt->next = after->next; after->next = stmt; stmt->type = sttype; stmt->value = after->value; stmt->flags = 0; stmt->sourceoffset = after->sourceoffset; stmt->sourcefilepath = after->sourcefilepath; stmt->dobjstack = after->dobjstack; return stmt; } Statement *CFunc_InsertBeforeStatement(StatementType sttype, Statement *before) { Statement *stmt = lalloc(sizeof(Statement)); *stmt = *before; before->next = stmt; before->type = sttype; before->flags = 0; return before; } void CheckCLabels(void) { CLabel *scan; for (scan = Labels; scan; scan = scan->next) { if (!scan->stmt) CError_Error(CErrorStr159, scan->name->name); } } Object *create_temp_object(Type *type) { Object *object = CParser_NewLocalDataObject(NULL, 1); object->name = CParser_GetUniqueName(); object->type = type; CFunc_SetupLocalVarInfo(object); return object; } ENode *create_temp_node(Type *type) { ENode *node; if (cinit_tempnodefunc) return cinit_tempnodefunc(type, 0); node = CExpr_NewETEMPNode(type, 0); if (IS_TYPE_CLASS(type) && CClass_Destructor(TYPE_CLASS(type))) node->data.temp.needs_dtor = 1; return node; } ENode *create_temp_node2(Type *type) { ENode *node; if (cinit_tempnodefunc) return cinit_tempnodefunc(type, 1); node = CExpr_NewETEMPNode(type, 0); node->data.temp.needs_dtor = 1; return node; } static ENode *CFunc_DestroyReverse(ENode *expr, DtorTemp *list) { expr = makediadicnode(expr, CABI_DestroyObject(list->dtor, create_objectrefnode(list->object), CABIDestroy1, 1, 0), ECOMMA); expr->rtype = &stvoid; if (list->next) expr = CFunc_DestroyReverse(expr, list->next); return expr; } static ENode *CFunc_TempTransDestroy(ENode *expr, DtorTemp *list, Boolean flag) { Object *tempobj; if (flag) { CError_ASSERT(738, !(IS_TYPE_CLASS(expr->rtype) && CClass_Destructor(TYPE_CLASS(expr->rtype)))); tempobj = create_temp_object(expr->rtype); expr = makediadicnode(create_objectnode(tempobj), expr, EASS); } expr = CFunc_DestroyReverse(expr, list); if (flag) { expr = makediadicnode(expr, create_objectnode(tempobj), ECOMMA); expr->rtype = tempobj->type; } return expr; } void CFunc_WarnUnused(void) { if (copts.warn_unusedvar) { ObjectList *list; for (list = locals; list; list = list->next) { if ( !(list->object->flags & OBJECT_FLAGS_UNUSED) && !IsTempName(list->object->name) && !(list->object->qual & Q_10000) ) { CError_SetErrorToken(&list->object->u.var.info->deftoken); CError_Warning(CErrorStr182, &list->object->name->name); } } } if (copts.warn_unusedarg) { ObjectList *list; for (list = arguments; list; list = list->next) { if ( !(list->object->flags & OBJECT_FLAGS_UNUSED) && !IsTempName(list->object->name) && list->object->name != this_name_node && list->object->name != self_name_node ) { CError_SetErrorToken(&symdecltoken); CError_Warning(CErrorStr182, &list->object->name->name); } } } } void CFunc_CodeCleanup(Statement *stmt) { if (cscope_currentclass && cscope_currentclass->sominfo) CSOM_InitSOMSelf(cscope_currentclass, stmt); CFunc_WarnUnused(); CExcept_ExceptionTansform(stmt); } static Boolean DestructorNeeded(ExceptionAction *ea, ExceptionAction *end) { while (ea) { if (CExcept_ActionNeedsDestruction(ea)) return 1; if (ea == end) break; ea = ea->prev; } return 0; } static Statement *DestructLocals(Statement *stmt, ExceptionAction *ea, ExceptionAction *end) { while (ea) { stmt = CExcept_ActionCleanup(ea, stmt); if (ea == end) break; ea = ea->prev; } return stmt; } static Boolean NeedsDestruction(Statement *stmt1, Statement *stmt2) { ExceptionAction *ea2; ExceptionAction *ea1; ExceptionAction *scan; ea1 = stmt1->dobjstack; ea2 = stmt2->dobjstack; for (scan = ea2; scan; scan = scan->prev) { if (scan == ea1) return 0; } while (ea1 && ea1 != ea2) { if (CExcept_ActionNeedsDestruction(ea1)) return 1; ea1 = ea1->prev; } return 0; } static ExceptionAction *FindLastNonCommonStackObj(Statement *stmt1, Statement *stmt2) { ExceptionAction *ea1; ExceptionAction *ea2; for (ea2 = stmt2->dobjstack; ea2; ea2 = ea2->prev) { for (ea1 = stmt1->dobjstack; ea1; ea1 = ea1->prev) { if (ea1->prev == ea2) return ea1; } } return NULL; } static void DestructorReturnTransform(Statement *stmt1, Statement *stmt2) { Statement *stmt; Object *tempobj; if (stmt1->dobjstack != stmt2->dobjstack && NeedsDestruction(stmt1, stmt2)) stmt1 = DestructLocals(stmt1, stmt1->dobjstack, FindLastNonCommonStackObj(stmt1, stmt2)); if (DestructorNeeded(stmt2->dobjstack, NULL)) { if (CMach_GetFunctionResultClass(TYPE_FUNC(cscope_currentfunc->type)) != 1) { tempobj = create_temp_object(stmt2->expr->rtype); stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt1); stmt->expr = makediadicnode(create_objectnode(tempobj), stmt2->expr, EASS); stmt->sourceoffset = stmt2->sourceoffset; stmt->sourcefilepath = stmt2->sourcefilepath; DestructLocals(stmt, stmt2->dobjstack, NULL); stmt2->expr = create_objectnode(tempobj); } else { stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt1); stmt->expr = stmt2->expr; stmt->sourceoffset = stmt2->sourceoffset; stmt->sourcefilepath = stmt2->sourcefilepath; DestructLocals(stmt, stmt2->dobjstack, NULL); stmt2->expr = nullnode(); } } } static Statement *DestructorIfTransform(Statement *stmt) { CLabel *label; Statement *newStmt; if (stmt->type == ST_IFGOTO) stmt->type = ST_IFNGOTO; else stmt->type = ST_IFGOTO; label = newlabel(); newStmt = DestructLocals(stmt, stmt->dobjstack, FindLastNonCommonStackObj(stmt, stmt->label->stmt)); newStmt = CFunc_InsertStatement(ST_GOTO, newStmt); newStmt->label = stmt->label; newStmt = CFunc_InsertStatement(ST_LABEL, newStmt); newStmt->label = label; label->stmt = newStmt; stmt->label = label; newStmt->dobjstack = stmt->dobjstack; return newStmt; } static Boolean IsSubStack(ExceptionAction *exc1, ExceptionAction *exc2) { if (!exc1) return 1; while (exc2) { if (exc2 == exc1) return 1; exc2 = exc2->prev; } return 0; } static void CFunc_CheckInitSkip(Statement *stmt, ExceptionAction *exc) { if (stmt->dobjstack != exc && !IsSubStack(exc, stmt->dobjstack)) { while (exc) { if (CExcept_ActionNeedsDestruction(exc) && exc->type != EAT_ACTIVECATCHBLOCK) { CError_Warning(CErrorStr211); break; } exc = exc->prev; } } } void CFunc_DestructorCleanup(Statement *stmt) { Statement *scan; Statement *next; SwitchCase *swcase; if (copts.cplusplus) { for (scan = stmt; scan; scan = scan->next) { switch (scan->type) { case ST_NOP: case ST_LABEL: case ST_EXPRESSION: case ST_RETURN: case ST_BEGINCATCH: case ST_ENDCATCH: case ST_ENDCATCHDTOR: case ST_GOTOEXPR: case ST_ASM: break; case ST_SWITCH: CFunc_CheckInitSkip(scan, ((SwitchInfo *) scan->label)->defaultlabel->stmt->dobjstack); for (swcase = ((SwitchInfo *) scan->label)->cases; swcase; swcase = swcase->next) { CFunc_CheckInitSkip(scan, swcase->label->stmt->dobjstack); } break; case ST_GOTO: case ST_IFGOTO: case ST_IFNGOTO: CFunc_CheckInitSkip(scan, scan->label->stmt->dobjstack); break; default: CError_FATAL(1045); } } if (cexcept_hasdobjects) { while (1) { next = stmt->next; if (!next) { if (stmt->type != ST_RETURN && stmt->dobjstack) DestructLocals(stmt, stmt->dobjstack, NULL); return; } switch (next->type) { case ST_GOTO: if ( stmt->dobjstack != next->label->stmt->dobjstack && NeedsDestruction(stmt, next->label->stmt) ) { DestructLocals(stmt, stmt->dobjstack, FindLastNonCommonStackObj(stmt, next->label->stmt)); } stmt = next; continue; case ST_RETURN: if (next->expr && DestructorNeeded(stmt->dobjstack, NULL)) { DestructorReturnTransform(stmt, next); } else if (stmt->dobjstack) { DestructLocals(stmt, stmt->dobjstack, NULL); } stmt = next; continue; } switch (stmt->type) { case ST_GOTO: case ST_SWITCH: case ST_RETURN: case ST_GOTOEXPR: break; case ST_NOP: case ST_LABEL: case ST_EXPRESSION: case ST_IFGOTO: case ST_IFNGOTO: case ST_BEGINCATCH: case ST_ENDCATCH: case ST_ENDCATCHDTOR: case ST_ASM: if ( stmt->dobjstack != next->dobjstack && NeedsDestruction(stmt, next) ) { DestructLocals(stmt, stmt->dobjstack, FindLastNonCommonStackObj(stmt, next)); } break; default: CError_FATAL(1109); } switch (next->type) { case ST_NOP: case ST_LABEL: case ST_EXPRESSION: case ST_SWITCH: case ST_BEGINCATCH: case ST_ENDCATCH: case ST_ENDCATCHDTOR: case ST_ASM: stmt = next; continue; case ST_IFGOTO: case ST_IFNGOTO: if ( next->dobjstack != next->label->stmt->dobjstack && NeedsDestruction(next, next->label->stmt) ) { stmt = DestructorIfTransform(next); } else { stmt = next; } break; default: CError_FATAL(1138); } } } } } static void scancase(DeclThing *thing) { SwitchCase *swcase; Statement *stmt; CInt64 min; CInt64 max; if (!thing->switchinfo) { CError_Error(CErrorStr169); return; } tk = lex(); min = CExpr_IntConstConvert(thing->switchinfo->x8, thing->switchinfo->x8, CExpr_IntegralConstExpr()); if (!copts.ANSI_strict && tk == TK_ELLIPSIS) { tk = lex(); max = CExpr_IntConstConvert(thing->switchinfo->x8, thing->switchinfo->x8, CExpr_IntegralConstExpr()); if (CInt64_Greater(min, max)) CError_Error(CErrorStr366); if (thing->switchinfo->x8->size == stsignedlonglong.size) CError_Error(CErrorStr368); } else { max = min; } for (swcase = thing->switchinfo->cases; swcase; swcase = swcase->next) { if (CInt64_GreaterEqual(swcase->min, min) && CInt64_LessEqual(swcase->min, max)) CError_Error(CErrorStr172); if (CInt64_GreaterEqual(swcase->max, min) && CInt64_LessEqual(swcase->max, max)) CError_Error(CErrorStr172); if (CInt64_Less(swcase->min, min) && CInt64_Greater(swcase->max, max)) CError_Error(CErrorStr172); } stmt = CFunc_AppendStatement(ST_LABEL); stmt->label = newlabel(); stmt->label->stmt = stmt; swcase = lalloc(sizeof(SwitchCase)); swcase->min = min; swcase->label = stmt->label; swcase->next = thing->switchinfo->cases; thing->switchinfo->cases = swcase; swcase->max = max; if (tk != ':') CError_ErrorSkip(CErrorStr170); else tk = lex(); statement(thing); } static void CFunc_NameLocalStaticDataObject(Object *obj, char *str) { char buf[64]; HashNameNode *name; if (!(cscope_currentfunc && (cscope_currentfunc->qual & Q_INLINE)) || CParser_HasInternalLinkage(cscope_currentfunc)) { obj->name = CParser_AppendUniqueName(str); } else { sprintf(buf, "$localstatic%ld$", cfunc_staticvarcount++); name = CMangler_GetLinkName(cscope_currentfunc); name = CParser_NameConcat(buf, name->name); name = CParser_NameConcat(str, name->name); obj->name = name; obj->qual |= Q_20000; obj->sclass = 0; } } static void sinit_insert_expr(ENode *expr) { Statement *stmt; if (!sinit_first_object) { sinit_first_object = CParser_NewCompilerDefDataObject(); sinit_first_object->type = TYPE(&stsignedchar); sinit_first_object->sclass = TK_STATIC; CFunc_NameLocalStaticDataObject(sinit_first_object, "init"); CInit_DeclareData(sinit_first_object, NULL, NULL, sinit_first_object->type->size); sinit_label = newlabel(); stmt = CFunc_AppendStatement(ST_IFGOTO); stmt->expr = create_objectnode(sinit_first_object); stmt->label = sinit_label; } stmt = CFunc_AppendStatement(ST_EXPRESSION); stmt->expr = expr; } static void ainit_insert_expr(ENode *expr) { Statement *stmt; if (ainit_only_one) { if (ainit_expr) { stmt = CFunc_AppendStatement(ST_EXPRESSION); stmt->expr = ainit_expr; } ainit_expr = expr; } else { stmt = CFunc_AppendStatement(ST_EXPRESSION); stmt->expr = expr; } } static ENode *ainit_register_object(Type *type, Object *local, SInt32 offset, Boolean flag) { return CExcept_RegisterDestructorObject(local, offset, CClass_Destructor(TYPE_CLASS(type)), flag); } static void CFunc_LocalDataDeclarator(DeclInfo *di, TStreamElement *deftoken, Boolean flag1, Boolean flag2) { Object *object; Object *aliasObject; NameSpace *globalNS; NameSpaceObjectList *nsol; NameSpaceName *nsname; Statement *stmt; if (di->nspace) CError_Error(CErrorStr121); CDecl_CompleteType(di->thetype); object = NULL; if ((nsol = CScope_FindName(cscope_current, di->name))) { switch (nsol->object->otype) { case OT_OBJECT: object = OBJECT(nsol->object); break; case OT_NAMESPACE: CError_Error(CErrorStr321); return; case OT_ENUMCONST: case OT_TYPE: CError_Error(CErrorStr322); break; case OT_TYPETAG: break; default: CError_FATAL(1344); } } if (object) CError_Error(CErrorStr333, object); if (di->storageclass == TK_EXTERN) { object = NULL; globalNS = CScope_FindGlobalNS(cscope_current); if ((nsol = CScope_FindName(globalNS, di->name))) { switch (nsol->object->otype) { case OT_OBJECT: object = OBJECT(nsol->object); break; case OT_NAMESPACE: CError_Error(CErrorStr321); return; case OT_ENUMCONST: case OT_TYPE: CError_Error(CErrorStr322); break; case OT_TYPETAG: break; default: CError_FATAL(1381); } } if (object) { if ( !is_typesame(di->thetype, object->type) || (di->qual & (Q_CONST | Q_VOLATILE | Q_PASCAL | Q_20000 | Q_OVERLOAD | Q_ALIGNED_MASK)) != (object->qual & (Q_CONST | Q_VOLATILE | Q_PASCAL | Q_20000 | Q_OVERLOAD | Q_ALIGNED_MASK)) ) { CError_Error(CErrorStr249, di->name->name, object->type, object->qual, di->thetype, di->qual); } } else { object = CParser_NewGlobalDataObject(di); object->nspace = globalNS; } CParser_NewAliasObject(object, 0); return; } if (di->storageclass != TK_STATIC) object = CParser_NewObject(di); else object = CParser_NewGlobalDataObject(di); object->name = di->name; object->type = di->thetype; object->qual = di->qual; object->sclass = di->storageclass; switch (di->storageclass) { case TK_STATIC: if (flag1) { CError_Error(CErrorStr177); return; } if (flag2) CError_Error(CErrorStr174); if (CanCreateObject(di->thetype)) { CError_QualifierCheck(di->qual & ~(Q_CONST | Q_VOLATILE | Q_PASCAL | Q_20000 | Q_OVERLOAD | Q_ALIGNED_MASK)); CParser_NewAliasObject(object, 0); object->nspace = cscope_root; object->datatype = DDATA; CFunc_NameLocalStaticDataObject(object, object->name->name); if (copts.cplusplus) { sinit_first_object = NULL; CInit_InitializeStaticData(object, sinit_insert_expr); if (sinit_first_object) { stmt = CFunc_AppendStatement(ST_EXPRESSION); stmt->expr = makediadicnode( create_objectnode(sinit_first_object), intconstnode(TYPE(&stsignedchar), 1), EASS); stmt = CFunc_AppendStatement(ST_LABEL); stmt->label = sinit_label; sinit_label->stmt = stmt; } } else { CInit_InitializeData(object); } } break; case 0: case TK_AUTO: case TK_REGISTER: if (CanCreateObject(di->thetype)) { CError_QualifierCheck(di->qual & ~(Q_CONST | Q_VOLATILE | Q_PASCAL | Q_ALIGNED_MASK)); object->datatype = DLOCAL; CFunc_SetupLocalVarInfo(object); object->u.var.info->deftoken = *deftoken; if (object->sclass == TK_REGISTER && flag1) object->u.var.info->usage = 100; CScope_AddObject(cscope_current, object->name, OBJ_BASE(object)); if (!flag1) { if (IS_TYPE_SOM_CLASS(di->thetype)) { CSOM_InitAutoClass(object); } else { CInit_InitializeAutoData(object, ainit_insert_expr, ainit_register_object); if (object->type != di->thetype && (IS_TYPE_STRUCT(object->type) || IS_TYPE_CLASS(object->type))) { CError_ASSERT(1478, !cscope_current->is_hash); CError_ASSERT(1479, nsname = CScope_FindNameSpaceName(cscope_current, object->name)); CError_ASSERT(1480, nsname->first.object == OBJ_BASE(object)); CError_ASSERT(1481, !nsname->first.next); nsname->name = CParser_AppendUniqueName(object->name->name); aliasObject = CParser_NewAliasObject(object, 0); aliasObject->type = di->thetype; } } } if (object->datatype == DLOCAL) { ObjectList *list = lalloc(sizeof(ObjectList)); list->object = object; list->next = locals; locals = list; } IsCompleteType(di->thetype); } break; default: CError_FATAL(1504); } } static ENode *CFunc_ParseLocalDeclarationList(Boolean flag1, Boolean flag2, Boolean flag3, Boolean flag4) { Type *type; UInt32 qual; DeclInfo di; TStreamElement deftoken; ainit_expr = NULL; ainit_only_one = flag2; while (flag2 || isdeclaration(copts.cplusplus, 0, 0, 0)) { CPrep_GetFileOffsetInfo2(&cparser_fileoffset, &sourceoffset, &sourcefilepath); memclrw(&di, sizeof(di)); di.x4E = cfunc_is_extern_c; CParser_GetDeclSpecs(&di, 0); if (IS_TYPE_TEMPLATE(di.thetype)) { CError_Error(CErrorStr146); di.thetype = TYPE(&stsignedint); } type = di.thetype; qual = di.qual; if (tk != ';') { while (1) { deftoken = *CPrep_CurStreamElement(); di.name = NULL; scandeclarator(&di); if (di.name) { if (di.storageclass != TK_TYPEDEF) { if (IS_TYPE_FUNC(di.thetype)) { if (!CDecl_FunctionDeclarator(&di, CScope_FindGlobalNS(cscope_current), 0, 0)) break; } else { CFunc_LocalDataDeclarator(&di, &deftoken, flag1, flag2); } } else { CDecl_TypedefDeclarator(&di); } } else { CError_Error(CErrorStr134); } if (tk == ';') break; if (tk != ',') { if (!flag2) CError_Error(CErrorStr123); break; } di.nspace = NULL; di.thetype = type; di.qual = qual; tk = lex(); } } else { CParser_CheckAnonymousUnion(&di, 1); } if (flag2) break; if (flag4) break; tk = lex(); } if (flag2) { if (!ainit_expr) { if (!flag3) { CError_Error(CErrorStr141); ainit_expr = nullnode(); } } else { ainit_expr = checkreference(ainit_expr); } } return ainit_expr; } static void makeifstatement(ENode *expr, CLabel *label1, CLabel *label2, Boolean flag1, Boolean flag2) { Statement *stmt; CLabel *tmplabel; if (!expr) { if (flag1) { stmt = CFunc_AppendStatement(ST_GOTO); stmt->label = label1; return; } return; } if ( ENODE_IS(expr, ETYPCON) && IS_TYPE_INT(expr->rtype) && IS_TYPE_INT(expr->data.monadic->rtype) && expr->rtype->size >= expr->data.monadic->rtype->size ) expr = expr->data.monadic; if (isnotzero(expr)) { if (flag1) { stmt = CFunc_AppendStatement(ST_GOTO); stmt->label = label1; return; } return; } if (iszero(expr)) { if (!flag1) { stmt = CFunc_AppendStatement(ST_GOTO); stmt->label = label1; return; } return; } if (ENODE_IS(expr, ELOGNOT)) { makeifstatement(expr->data.monadic, label1, label2, !flag1, flag2); return; } if (ENODE_IS(expr, ELOR)) { tmplabel = newlabel(); if (flag1) { makeifstatement(expr->data.diadic.left, label1, tmplabel, 1, flag2); tmplabel->stmt = CFunc_AppendStatement(ST_LABEL); tmplabel->stmt->label = tmplabel; makeifstatement(expr->data.diadic.right, label1, label2, 1, flag2); return; } else { makeifstatement(expr->data.diadic.left, label2, tmplabel, 1, flag2); tmplabel->stmt = CFunc_AppendStatement(ST_LABEL); tmplabel->stmt->label = tmplabel; makeifstatement(expr->data.diadic.right, label1, label2, 0, flag2); return; } } if (ENODE_IS(expr, ELAND)) { tmplabel = newlabel(); if (flag1) { makeifstatement(expr->data.diadic.left, label2, tmplabel, 0, flag2); tmplabel->stmt = CFunc_AppendStatement(ST_LABEL); tmplabel->stmt->label = tmplabel; makeifstatement(expr->data.diadic.right, label1, label2, 1, flag2); return; } else { makeifstatement(expr->data.diadic.left, label1, tmplabel, 0, flag2); tmplabel->stmt = CFunc_AppendStatement(ST_LABEL); tmplabel->stmt->label = tmplabel; makeifstatement(expr->data.diadic.right, label1, label2, 0, flag2); return; } } stmt = CFunc_AppendStatement(ST_IFGOTO); stmt->label = label1; stmt->expr = expr; if (!flag1) stmt->type = ST_IFNGOTO; if (flag2) stmt->flags |= StmtFlag_4; } static void CFunc_HasDtorTempCallBack(ENode *expr) { if (expr->data.temp.needs_dtor || expr->data.temp.uniqueid) cfunc_hasdtortemp = 1; } static void ifstatement(Boolean flag1, ENode *expr, CLabel *label, Boolean flag2) { Statement *stmt; CLabel *tmplabel; if (expr && copts.cplusplus && copts.exceptions) { cfunc_hasdtortemp = 0; CExpr_SearchExprTree(expr, CFunc_HasDtorTempCallBack, 1, ETEMP); if (cfunc_hasdtortemp) { stmt = CFunc_AppendStatement(flag1 ? ST_IFGOTO : ST_IFNGOTO); stmt->label = label; stmt->expr = expr; if (flag2) stmt->flags |= StmtFlag_4; return; } } tmplabel = newlabel(); makeifstatement(expr, label, tmplabel, flag1, flag2); tmplabel->stmt = CFunc_AppendStatement(ST_LABEL); tmplabel->stmt->label = tmplabel; } Statement *CFunc_GenerateLoop(Statement *stmt, Type *type, ENode *lowerBound, ENode *upperBound, ENode *increment1, ENode *increment2, ENode *(*callback)(ENode *, ENode *)) { ENode *var1; ENode *var2; CLabel *label; ENode *ind; ENode *ind2; Statement *s; var1 = CExpr_NewETEMPNode(type, 1); ind = lalloc(sizeof(ENode)); *ind = *var1; ind = makemonadicnode(ind, EINDIRECT); ind->rtype = type; // initialise var1 to lowerBound if (stmt) { stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); s = stmt; } else { s = CFunc_AppendStatement(ST_EXPRESSION); } s->expr = makediadicnode(ind, lowerBound, EASS); if (increment2) { var2 = CExpr_NewETEMPNode(type, 1); ind = lalloc(sizeof(ENode)); *ind = *var2; ind = makemonadicnode(ind, EINDIRECT); ind->rtype = type; // initialise var2 to upperBound if (stmt) { stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); s = stmt; } else { s = CFunc_AppendStatement(ST_EXPRESSION); } s->expr = makediadicnode(ind, upperBound, EASS); } // label for loop body label = newlabel(); if (stmt) { stmt = CFunc_InsertStatement(ST_LABEL, stmt); s = stmt; } else { s = CFunc_AppendStatement(ST_LABEL); } s->label = label; label->stmt = s; if (callback) { ind = lalloc(sizeof(ENode)); *ind = *var1; ind = makemonadicnode(ind, EINDIRECT); ind->rtype = type; if (increment2) { ind2 = lalloc(sizeof(ENode)); *ind2 = *var2; ind2 = makemonadicnode(ind2, EINDIRECT); ind2->rtype = type; } else { ind2 = NULL; } // generate a loop body if ((ind = callback(ind, ind2))) { if (stmt) { stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); s = stmt; } else { s = CFunc_AppendStatement(ST_EXPRESSION); } s->expr = ind; } } if (increment1) { ind = lalloc(sizeof(ENode)); *ind = *var1; ind = makemonadicnode(ind, EINDIRECT); ind->rtype = type; // add increment1 to var1 if (stmt) { stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); s = stmt; } else { s = CFunc_AppendStatement(ST_EXPRESSION); } s->expr = makediadicnode(ind, increment1, EADDASS); if (increment2) { ind = lalloc(sizeof(ENode)); *ind = *var2; ind = makemonadicnode(ind, EINDIRECT); ind->rtype = type; // add increment2 to var2 if (stmt) { stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); s = stmt; } else { s = CFunc_AppendStatement(ST_EXPRESSION); } s->expr = makediadicnode(ind, increment2, EADDASS); } } ind = lalloc(sizeof(ENode)); *ind = *var1; ind = makemonadicnode(ind, EINDIRECT); ind->rtype = type; // loop if var1 < upperBound if (stmt) { stmt = CFunc_InsertStatement(ST_IFGOTO, stmt); s = stmt; } else { s = CFunc_AppendStatement(ST_IFGOTO); } s->expr = makediadicnode(ind, upperBound, ELESS); s->expr->rtype = TYPE(&stbool); s->label = label; s->flags = StmtFlag_4; return stmt; } static Boolean checklabel(void) { HashNameNode *savename; short savesize; short token; savename = tkidentifier; savesize = tksize; token = lookahead(); tkidentifier = savename; tksize = savesize; return token == ':'; } static ENode *returnstatementadjust(ENode *expr, Type *type, UInt32 qual) { Object *object; ENode *expr2; ENode *objexpr; ObjectList *list; ENodeList *exprlist; for (list = arguments; list; list = list->next) { if (list->object->name == temp_argument_name) break; } CError_ASSERT(1907, list); object = list->object; if ((expr2 = CExpr_IsTempConstruction(expr, type, &objexpr)) && ENODE_IS(objexpr, ETEMP)) { *objexpr = *create_objectnode(object); return expr2; } if (IS_TYPE_CLASS(type)) { expr2 = create_objectnode(object); exprlist = lalloc(sizeof(ENodeList)); exprlist->next = NULL; exprlist->node = expr; return CExpr_ConstructObject(TYPE_CLASS(type), expr2, exprlist, 1, 1, 0, 1, 0); } expr2 = create_objectnode(object); expr2 = makemonadicnode(expr2, EINDIRECT); expr2->rtype = type; return makediadicnode(expr2, CExpr_AssignmentPromotion(expr, type, qual, 1), EASS); } static void CFunc_AutoResultCheck(ENode *expr) { while (1) { while (ENODE_IS(expr, ECOMMA)) expr = expr->data.diadic.right; switch (expr->type) { case EOBJREF: if (expr->data.objref->datatype != DLOCAL) break; case ETEMP: CError_Warning(CErrorStr326); break; case EADD: case ESUB: CFunc_AutoResultCheck(expr->data.diadic.left); expr = expr->data.diadic.right; continue; default: break; } break; } } static void statement(DeclThing *thing) { Statement *stmt; Statement *stmt2; CLabel *label; DeclBlock *block; ENode *expr; HashNameNode *name; DeclThing subthing; CPrep_GetFileOffsetInfo2(&cparser_fileoffset, &sourceoffset, &sourcefilepath); switch (tk) { case TK_RETURN: tk = lex(); if ( (thing->thetype == &stvoid && !copts.cplusplus) || CClass_IsConstructor(cscope_currentfunc) || CClass_IsDestructor(cscope_currentfunc) ) { if (tk != ';') { CError_Error(CErrorStr315); expression(); } stmt = CFunc_AppendStatement(ST_RETURN); stmt->expr = NULL; CError_ResetErrorSkip(); tk = lex(); return; } if (tk == ';') { if (thing->thetype != &stvoid && (copts.pedantic || copts.cplusplus)) CError_Warning(CErrorStr184); stmt = CFunc_AppendStatement(ST_RETURN); stmt->expr = NULL; CError_ResetErrorSkip(); tk = lex(); return; } if (copts.old_argmatch) expr = expression(); else expr = s_expression(); if (thing->thetype == &stvoid) { if (expr->rtype != &stvoid) CError_Error(CErrorStr315); stmt = CFunc_AppendStatement(ST_EXPRESSION); stmt->expr = expr; stmt = CFunc_AppendStatement(ST_RETURN); stmt->expr = NULL; } else { if (CMach_GetFunctionResultClass(TYPE_FUNC(cscope_currentfunc->type)) == 1) expr = returnstatementadjust(expr, thing->thetype, thing->qual); else expr = CExpr_AssignmentPromotion(expr, thing->thetype, thing->qual, 1); stmt = CFunc_AppendStatement(ST_RETURN); stmt->expr = expr; if (IS_TYPE_POINTER_ONLY(thing->thetype)) CFunc_AutoResultCheck(expr); } break; case TK_CASE: scancase(thing); return; case TK_DEFAULT: if (!thing->switchinfo) { CError_Error(CErrorStr169); return; } if (lex() != ':') CError_ErrorSkip(CErrorStr170); else tk = lex(); if (thing->switchinfo->defaultlabel) CError_ErrorSkip(CErrorStr173); stmt = CFunc_AppendStatement(ST_LABEL); stmt->label = newlabel(); stmt->label->stmt = stmt; thing->switchinfo->defaultlabel = stmt->label; statement(thing); return; case TK_SWITCH: if (lex() != '(') CError_ErrorSkip(CErrorStr114); else tk = lex(); if (copts.cplusplus && !copts.ARM_scoping && isdeclaration(1, 0, 0, '=')) { block = CFunc_NewDeclBlock(); expr = CFunc_ParseLocalDeclarationList(0, 1, 0, 0); if (CScope_IsEmptyNameSpace(cscope_current)) { CFunc_RestoreBlock(block); block = NULL; } } else { expr = expression(); block = NULL; } stmt = CFunc_AppendStatement(ST_SWITCH); stmt->expr = CExpr_ConvertToIntegral(expr); if (tk != ')') CError_ErrorSkip(CErrorStr115); else tk = lex(); stmt->label = (CLabel *) lalloc(sizeof(SwitchInfo)); ((SwitchInfo *) stmt->label)->defaultlabel = NULL; ((SwitchInfo *) stmt->label)->cases = NULL; ((SwitchInfo *) stmt->label)->x8 = stmt->expr->rtype; label = newlabel(); subthing = *thing; subthing.loopBreak = label; subthing.switchinfo = (SwitchInfo *) stmt->label; CFunc_CompoundStatement(&subthing); if (!subthing.switchinfo->defaultlabel) subthing.switchinfo->defaultlabel = label; if (!subthing.switchinfo->cases) { stmt->type = ST_EXPRESSION; stmt2 = lalloc(sizeof(Statement)); *stmt2 = *stmt; stmt->next = stmt2; stmt2->type = ST_GOTO; stmt2->label = subthing.switchinfo->defaultlabel; stmt2->dobjstack = cexcept_dobjstack; } stmt = CFunc_AppendStatement(ST_LABEL); stmt->label = label; label->stmt = stmt; if (block) CFunc_RestoreBlock(block); return; case TK_GOTO: if ((tk = lex()) != TK_IDENTIFIER) { if (tk == '*' && !copts.ANSI_strict) { tk = lex(); stmt = CFunc_AppendStatement(ST_GOTOEXPR); stmt->expr = expression(); if (!IS_TYPE_POINTER_ONLY(stmt->expr->rtype)) { CError_Error(CErrorStr146); stmt->expr = nullnode(); stmt->expr->rtype = TYPE(&void_ptr); } } else { CError_Error(CErrorStr107); return; } } else { stmt = CFunc_AppendStatement(ST_GOTO); if (!(stmt->label = findlabel())) { stmt->label = newlabel(); stmt->label->next = Labels; Labels = stmt->label; stmt->label->name = tkidentifier; } tk = lex(); } break; case TK_BREAK: if (thing->loopBreak) { stmt = CFunc_AppendStatement(ST_GOTO); stmt->label = thing->loopBreak; } else { CError_Error(CErrorStr169); } tk = lex(); break; case TK_CONTINUE: if (thing->loopContinue) { stmt = CFunc_AppendStatement(ST_GOTO); stmt->label = thing->loopContinue; } else { CError_Error(CErrorStr169); } tk = lex(); break; case TK_FOR: { CLabel *forLabel1; CLabel *forLabel2; CLabel *forLabel3; ENode *forCond; ENode *forInc; if (lex() != '(') CError_ErrorSkip(CErrorStr114); else tk = lex(); block = NULL; if (tk != ';') { if (!copts.cplusplus || !isdeclaration(1, 0, 0, 0)) { expr = expression(); CExpr_CheckUnusedExpression(expr); } else { if (!copts.ARM_scoping) block = CFunc_NewDeclBlock(); expr = CFunc_ParseLocalDeclarationList(0, 1, 1, 0); if (block && CScope_IsEmptyNameSpace(cscope_current)) { CFunc_RestoreBlock(block); block = NULL; } } if (expr) { stmt = CFunc_AppendStatement(ST_EXPRESSION); stmt->expr = expr; } if (tk == ';') CError_ResetErrorSkip(); else CError_Error(CErrorStr123); } else { CError_ResetErrorSkip(); } if ((tk = lex()) != ';') { if (copts.cplusplus && !copts.ARM_scoping && isdeclaration(1, 0, 0, '=')) { if (!block) block = CFunc_NewDeclBlock(); expr = CFunc_ParseLocalDeclarationList(0, 1, 0, 0); if (CScope_IsEmptyNameSpace(cscope_current)) { CFunc_RestoreBlock(block); block = NULL; } } else { expr = expression(); CExpr_CheckUnwantedAssignment(expr); } forCond = CExpr_ConvertToCondition(expr); if (tk == ';') CError_ResetErrorSkip(); else CError_Error(CErrorStr123); } else { CError_ResetErrorSkip(); forCond = NULL; } if ((tk = lex()) != ')') { forInc = expression(); CExpr_CheckUnusedExpression(forInc); if (tk == ')') CError_ResetErrorSkip(); else CError_Error(CErrorStr115); } else { CError_ResetErrorSkip(); forInc = NULL; } if (copts.warn_possunwant) { spaceskip = 0; if ((tk = lex()) == ';' && !spaceskip) CError_Warning(CErrorStr206); } else { tk = lex(); } if (forCond) { stmt = CFunc_AppendStatement(ST_GOTO); label = newlabel(); stmt->label = label; } else { label = newlabel(); } CFunc_LoopIncrement(); stmt = CFunc_AppendStatement(ST_LABEL); forLabel1 = stmt->label = newlabel(); forLabel1->stmt = stmt; forLabel2 = newlabel(); forLabel3 = newlabel(); subthing = *thing; subthing.loopContinue = forLabel3; subthing.loopBreak = forLabel2; if (tk != '{') { DeclBlock *b = CFunc_NewDeclBlock(); CFunc_CompoundStatement(&subthing); CFunc_RestoreBlock(b); } else { CFunc_CompoundStatement(&subthing); } stmt = CFunc_AppendStatement(ST_LABEL); stmt->label = forLabel3; forLabel3->stmt = stmt; if (forInc) { stmt = CFunc_AppendStatement(ST_EXPRESSION); stmt->expr = forInc; } stmt = CFunc_AppendStatement(ST_LABEL); stmt->label = label; label->stmt = stmt; ifstatement(1, forCond, forLabel1, 1); CFunc_LoopDecrement(); stmt = CFunc_AppendStatement(ST_LABEL); stmt->label = forLabel2; forLabel2->stmt = stmt; if (block) CFunc_RestoreBlock(block); return; } case TK_DO: { CLabel *label1; CLabel *label2; CLabel *label3; CFunc_LoopIncrement(); stmt = CFunc_AppendStatement(ST_LABEL); label1 = stmt->label = newlabel(); label1->stmt = stmt; label2 = newlabel(); label3 = newlabel(); subthing = *thing; subthing.loopContinue = label2; subthing.loopBreak = label3; tk = lex(); CFunc_CompoundStatement(&subthing); stmt = CFunc_AppendStatement(ST_LABEL); stmt->label = label2; label2->stmt = stmt; if (tk != TK_WHILE) CError_Error(CErrorStr105); if (lex() != '(') CError_ErrorSkip(CErrorStr114); else tk = lex(); expr = CExpr_ConvertToCondition(expression()); CExpr_CheckUnwantedAssignment(expr); if (tk != ')') CError_ErrorSkip(CErrorStr115); else tk = lex(); ifstatement(1, expr, label1, 1); CFunc_LoopDecrement(); stmt = CFunc_AppendStatement(ST_LABEL); stmt->label = label3; label3->stmt = stmt; break; } case TK_WHILE: { CLabel *label1; CLabel *label2; CLabel *label3; if ((tk = lex()) != '(') CError_ErrorSkip(CErrorStr114); else tk = lex(); if (copts.cplusplus && !copts.ARM_scoping && isdeclaration(1, 0, 0, '=')) { block = CFunc_NewDeclBlock(); expr = CFunc_ParseLocalDeclarationList(0, 1, 0, 0); if (CScope_IsEmptyNameSpace(cscope_current)) { CFunc_RestoreBlock(block); block = NULL; } } else { expr = expression(); block = NULL; CExpr_CheckUnwantedAssignment(expr); } expr = CExpr_ConvertToCondition(expr); if (tk != ')') { CError_ErrorSkip(CErrorStr115); } else { if (copts.warn_possunwant) { spaceskip = 0; if ((tk = lex()) == ';' && !spaceskip) CError_Warning(CErrorStr206); } else { tk = lex(); } } stmt = CFunc_AppendStatement(ST_GOTO); label1 = newlabel(); stmt->label = label1; CFunc_LoopIncrement(); stmt = CFunc_AppendStatement(ST_LABEL); label2 = stmt->label = newlabel(); label2->stmt = stmt; label3 = newlabel(); subthing = *thing; subthing.loopContinue = label1; subthing.loopBreak = label3; CFunc_CompoundStatement(&subthing); stmt = CFunc_AppendStatement(ST_LABEL); stmt->label = label1; label1->stmt = stmt; ifstatement(1, expr, label2, 1); CFunc_LoopDecrement(); stmt = CFunc_AppendStatement(ST_LABEL); stmt->label = label3; label3->stmt = stmt; if (block) CFunc_RestoreBlock(block); return; } case TK_IF: { CLabel *label1; if ((tk = lex()) != '(') CError_ErrorSkip(CErrorStr114); else tk = lex(); if (copts.cplusplus && !copts.ARM_scoping && isdeclaration(1, 0, 0, '=')) { block = CFunc_NewDeclBlock(); expr = CFunc_ParseLocalDeclarationList(0, 1, 0, 0); if (CScope_IsEmptyNameSpace(cscope_current)) { CFunc_RestoreBlock(block); block = NULL; } } else { expr = expression(); block = NULL; CExpr_CheckUnwantedAssignment(expr); } expr = CExpr_ConvertToCondition(expr); label1 = newlabel(); ifstatement(0, expr, label1, 0); if (tk != ')') { CError_ErrorSkip(CErrorStr115); } else { if (copts.warn_possunwant) { spaceskip = 0; if ((tk = lex()) == ';' && !spaceskip) CError_Warning(CErrorStr206); } else { tk = lex(); } } CFunc_CompoundStatement(thing); if (tk == TK_ELSE) { if (copts.warn_possunwant) { spaceskip = 0; if ((tk = lex()) == ';' && !spaceskip) CError_Warning(CErrorStr206); } else { tk = lex(); } stmt = CFunc_AppendStatement(ST_GOTO); label = stmt->label = newlabel(); stmt = CFunc_AppendStatement(ST_LABEL); stmt->label = label1; label1->stmt = stmt; CFunc_CompoundStatement(thing); label1 = label; } stmt = CFunc_AppendStatement(ST_LABEL); stmt->label = label1; label1->stmt = stmt; if (block) CFunc_RestoreBlock(block); return; } case '{': CFunc_CompoundStatement(thing); return; case TK_ASM: if (copts.cplusplus || !copts.ANSI_strict) { tk = lex(); volatileasm = 0; if (tk == TK_VOLATILE || (tk == TK_IDENTIFIER && !strcmp(tkidentifier->name, "__volatile__"))) { tk = lex(); volatileasm = 1; } if (tk == '(') { InlineAsm_Assemble(); if (tk == ')') { tk = lex(); break; } else { CError_Error(CErrorStr115); return; } } if (tk == '{') { InlineAsm_Assemble(); if (tk != '}') { CError_Error(CErrorStr130); return; } if ((tk = lex()) == ';') tk = lex(); CError_ResetErrorSkip(); return; } CError_Error(CErrorStr114); } else { CError_Error(CErrorStr121); } return; case TK_TRY: tk = lex(); CExcept_ScanTryBlock(thing, 0); return; case TK_USING: if ((tk = lex()) == TK_NAMESPACE) { tk = lex(); CScope_ParseUsingDirective(cscope_current); } else { CScope_ParseUsingDeclaration(cscope_current, 0, 0); } return; case TK_NAMESPACE: if ((tk = lex()) != TK_IDENTIFIER) { CError_Error(CErrorStr107); return; } name = tkidentifier; if ((tk = lex()) != '=') { CError_Error(CErrorStr121); return; } CScope_ParseNameSpaceAlias(name); break; case ';': break; case TK_IDENTIFIER: if (checklabel()) { stmt = CFunc_AppendStatement(ST_LABEL); if ((stmt->label = findlabel())) { if (stmt->label->stmt) CError_Error(CErrorStr171, tkidentifier->name); } else { stmt->label = newlabel(); stmt->label->next = Labels; Labels = stmt->label; stmt->label->name = tkidentifier; } stmt->label->stmt = stmt; tk = lex(); tk = lex(); statement(thing); return; } tk = TK_IDENTIFIER; default: if (copts.cplusplus && isdeclaration(1, 0, 0, 0)) { CFunc_ParseLocalDeclarationList(0, 0, 0, 1); tk = lex(); return; } stmt = CFunc_AppendStatement(ST_EXPRESSION); stmt->expr = expression(); CExpr_CheckUnusedExpression(stmt->expr); } if (tk == ';') { CPrep_TokenStreamFlush(); tk = lex(); CError_ResetErrorSkip(); } else { CError_ErrorSkip(CErrorStr123); } } void CFunc_CompoundStatement(DeclThing *thing) { DeclBlock *block; block = CFunc_NewDeclBlock(); if (tk == '{') { tk = lex(); if (!copts.cplusplus && isdeclaration(0, 0, 0, 0)) CFunc_ParseLocalDeclarationList(0, 0, 0, 0); while (tk != '}') statement(thing); CPrep_GetFileOffsetInfo2(&cparser_fileoffset, &sourceoffset, &sourcefilepath); tk = lex(); } else { statement(thing); } CFunc_RestoreBlock(block); } static void CFunc_InsertArgumentCopyConversion(Object *obj, Type *type1, Type *type2, Boolean flag) { Object *newobj; Statement *stmt; ENode *expr; NameSpaceObjectList *nsol; ObjectList *list; newobj = lalloc(sizeof(Object)); *newobj = *obj; newobj->type = type2; CFunc_SetupLocalVarInfo(newobj); obj->name = CParser_GetUniqueName(); if (flag) obj->type = CDecl_NewPointerType(type1); else obj->type = type1; CError_ASSERT(2527, (nsol = CScope_FindName(cscope_current, newobj->name)) && nsol->object == OBJ_BASE(obj)); nsol->object = OBJ_BASE(newobj); list = lalloc(sizeof(ObjectList)); list->object = newobj; list->next = locals; locals = list; stmt = CFunc_AppendStatement(ST_EXPRESSION); expr = create_objectnode(obj); if (flag) { expr->rtype = CDecl_NewPointerType(type1); expr = makemonadicnode(expr, EINDIRECT); } expr->rtype = type1; if (type1 != type2) expr = promote(expr, type2); stmt->expr = makediadicnode(create_objectnode(newobj), expr, EASS); } static void CFunc_AdjustOldStyleArgs(void) { ObjectList *list; for (list = arguments; list; list = list->next) { if (IS_TYPE_FLOAT(list->object->type) && list->object->type->size < stdouble.size) CFunc_InsertArgumentCopyConversion(list->object, TYPE(&stdouble), list->object->type, 0); } } void CFunc_SetupNewFuncArgs(Object *func, FuncArg *args) { Object *obj; ObjectList *newlist; arguments = NULL; if (args != &elipsis && args != &oldstyle) { newlist = NULL; while (args && args != &elipsis) { IsCompleteType(args->type); obj = CParser_NewLocalDataObject(NULL, 0); obj->name = !args->name ? no_name_node : args->name; obj->type = args->type; obj->qual = args->qual; obj->sclass = args->sclass; CFunc_SetupLocalVarInfo(obj); if (IS_TYPE_CLASS(obj->type) && CClass_ReferenceArgument(TYPE_CLASS(obj->type))) { obj->type = CDecl_NewPointerType(obj->type); TPTR_QUAL(obj->type) = Q_REFERENCE | Q_RESTRICT; } if (obj->name == no_name_node && copts.ANSI_strict && !copts.cplusplus && !(func->qual & Q_80000)) CError_Error(CErrorStr127); if (newlist) { newlist->next = lalloc(sizeof(ObjectList)); newlist = newlist->next; } else { newlist = lalloc(sizeof(ObjectList)); arguments = newlist; } newlist->next = NULL; newlist->object = obj; args = args->next; } } } static ObjectList *CFunc_CopyObjectList(const FuncArg *args) { Object *obj; ObjectList *list; ObjectList *last; list = NULL; while (args) { if (list) { last->next = lalloc(sizeof(ObjectList)); last = last->next; } else { last = lalloc(sizeof(ObjectList)); list = last; } obj = CParser_NewLocalDataObject(NULL, 0); obj->name = args->name; obj->type = args->type; obj->qual = args->qual; obj->sclass = args->sclass; CFunc_SetupLocalVarInfo(obj); last->object = obj; last->next = NULL; args = args->next; } return list; } static void SetupFunctionArguments(Object *func, DeclInfo *di, Statement *firstStmt) { ObjectList *list; Object *resultobj; Object *obj; Type *type; DeclInfo my_di; if (TYPE_FUNC(func->type)->args) { if (di->x45) { arguments = CFunc_CopyObjectList(di->x18); while (1) { if (tk == '{') break; memclrw(&my_di, sizeof(my_di)); CParser_GetDeclSpecs(&my_di, 0); type = my_di.thetype; if (my_di.storageclass && my_di.storageclass != TK_REGISTER) CError_Error(CErrorStr127); while (1) { my_di.thetype = type; my_di.name = NULL; scandeclarator(&my_di); if (!my_di.name) { CError_Error(CErrorStr107); break; } adjustargumenttype(&my_di); IsCompleteType(my_di.thetype); if ((obj = CFunc_IsInObjList(arguments, my_di.name))) { if (obj->type) CError_Error(CErrorStr333, obj); obj->type = my_di.thetype; obj->sclass = my_di.storageclass; obj->qual = my_di.qual; } else { CError_Error(CErrorStr127); } if (tk != ',') break; tk = lex(); } if (tk != ';') CError_ErrorSkip(CErrorStr123); else tk = lex(); } for (list = arguments; list; list = list->next) { if (!list->object->type) list->object->type = TYPE(&stsignedint); } } else { CFunc_SetupNewFuncArgs(func, TYPE_FUNC(func->type)->args); } } if (CMach_GetFunctionResultClass(TYPE_FUNC(func->type)) == 1) { resultobj = CParser_NewLocalDataObject(NULL, 0); resultobj->name = temp_argument_name; resultobj->type = CDecl_NewPointerType(TYPE_FUNC(func->type)->functype); CFunc_SetupLocalVarInfo(resultobj); list = lalloc(sizeof(ObjectList)); list->object = resultobj; if (CABI_GetStructResultArgumentIndex(TYPE_FUNC(func->type))) { CError_ASSERT(2797, arguments); list->next = arguments->next; arguments->next = list; } else { list->next = arguments; arguments = list; } } for (list = arguments; list; list = list->next) { NameSpaceObjectList *nsol = CScope_InsertName(cscope_current, list->object->name); nsol->object = OBJ_BASE(list->object); } } NameSpace *CFunc_FuncGenSetup(Statement *stmt, Object *func) { NameSpace *nspace; DeclBlock *block; nspace = CScope_NewListNameSpace(NULL, 0); nspace->parent = cscope_current; cscope_current = nspace; arguments = NULL; locals = NULL; Labels = NULL; localcount = 0; cfunc_staticvarcount = 0; CExcept_Setup(); memclrw(stmt, sizeof(Statement)); curstmt = stmt; stmt->type = ST_NOP; curstmtvalue = 1; stmt->value = 1; blockcount = 0; block = lalloc(sizeof(DeclBlock)); memclrw(block, sizeof(DeclBlock)); block->index = blockcount++; block->parent_nspace = cscope_current; firstblock = block; currentblock = block; return nspace; } CFuncSave *CFunc_GetGlobalCompilerState(void) { CFuncSave *state; if (!cscope_currentfunc && !cscope_currentclass && cscope_current == cscope_root) return NULL; locklheap(); state = lalloc(sizeof(CFuncSave)); CScope_SetNameSpaceScope(cscope_root, &state->scope); state->arguments = arguments; arguments = NULL; state->locals = locals; locals = NULL; state->labels = Labels; Labels = NULL; state->curstmt = curstmt; curstmt = NULL; state->firstblock = firstblock; firstblock = NULL; state->currentblock = currentblock; currentblock = NULL; state->cexcept_dobjstack = cexcept_dobjstack; cexcept_dobjstack = NULL; state->sinit_label = sinit_label; sinit_label = NULL; state->ainit_expr = ainit_expr; ainit_expr = NULL; state->ctor_chain = ctor_chain; ctor_chain = NULL; state->cinit_tempnodefunc = cinit_tempnodefunc; cinit_tempnodefunc = NULL; state->trychain = trychain; trychain = NULL; state->cparser_fileoffset = cparser_fileoffset; state->symdecltoken = symdecltoken; state->functionbodyoffset = functionbodyoffset; functionbodyoffset = 0; state->functionbodypath = functionbodypath; functionbodypath = NULL; state->symdecloffset = symdecloffset; symdecloffset = 0; state->symdeclend = symdeclend; state->sourceoffset = sourceoffset; sourceoffset = 0; state->sourcefilepath = sourcefilepath; sourcefilepath = NULL; state->curstmtvalue = curstmtvalue; curstmtvalue = 0; state->name_obj_check = name_obj_check; name_obj_check = NULL; state->check_arglist = check_arglist; check_arglist = NULL; state->blockcount = blockcount; blockcount = 0; state->localcount = localcount; localcount = 0; state->tk = tk; state->tkidentifier = tkidentifier; state->global_access = global_access; state->cexcept_hasdobjects = cexcept_hasdobjects; cexcept_hasdobjects = 0; state->sinit_first_object = sinit_first_object; sinit_first_object = NULL; state->ainit_only_one = ainit_only_one; ainit_only_one = 0; state->cfunc_is_extern_c = cfunc_is_extern_c; cfunc_is_extern_c = 0; state->temp_reference_init = temp_reference_init; return state; } void CFunc_SetGlobalCompilerState(CFuncSave *state) { if (state) { CScope_RestoreScope(&state->scope); arguments = state->arguments; locals = state->locals; Labels = state->labels; curstmt = state->curstmt; firstblock = state->firstblock; currentblock = state->currentblock; cexcept_dobjstack = state->cexcept_dobjstack; sinit_label = state->sinit_label; ainit_expr = state->ainit_expr; ctor_chain = state->ctor_chain; cinit_tempnodefunc = state->cinit_tempnodefunc; trychain = state->trychain; name_obj_check = state->name_obj_check; check_arglist = state->check_arglist; curstmtvalue = state->curstmtvalue; cparser_fileoffset = state->cparser_fileoffset; symdecltoken = state->symdecltoken; functionbodyoffset = state->functionbodyoffset; functionbodypath = state->functionbodypath; symdecloffset = state->symdecloffset; symdeclend = state->symdeclend; sourceoffset = state->sourceoffset; sourcefilepath = state->sourcefilepath; blockcount = state->blockcount; tk = state->tk; tkidentifier = state->tkidentifier; global_access = state->global_access; localcount = state->localcount; cexcept_hasdobjects = state->cexcept_hasdobjects; sinit_first_object = state->sinit_first_object; ainit_only_one = state->ainit_only_one; cfunc_is_extern_c = state->cfunc_is_extern_c; temp_reference_init = state->temp_reference_init; unlocklheap(); } } void CFunc_Gen(Statement *stmt, Object *func, UInt8 unk) { Boolean flag; CI_FuncData packed; if ((TYPE_FUNC(func->type)->flags & FUNC_FLAGS_400000) && !anyerrors) { CInline_PackIFunctionData(&packed, stmt, func); flag = 1; } else { flag = 0; } CInline_GenFunc(stmt, func, unk); if (flag) CClass_DefineCovariantFuncs(func, &packed); } static void CFunc_CheckCtorInitializer(TypeClass *tclass, CtorChain *chain) { ObjMemberVar *ivar; CtorChain *scan; if (tclass->mode != CLASS_MODE_1) { for (ivar = tclass->ivars; ivar; ivar = ivar->next) { if (IS_TYPE_REFERENCE(ivar->type)) { for (scan = chain; scan; scan = scan->next) { if (scan->what == CtorChain_MemberVar && scan->u.membervar == ivar) break; } if (!scan) CError_Error(CErrorStr256, ivar->name->name); } else if (CParser_IsConst(ivar->type, ivar->qual)) { for (scan = chain; scan; scan = scan->next) { if (scan->what == CtorChain_MemberVar && scan->u.membervar == ivar) break; } if (!scan && !IS_TYPE_CLASS(ivar->type)) CError_Error(CErrorStr255, ivar->name->name); } } } } void CFunc_CheckClassCtors(TypeClass *tclass) { CFunc_CheckCtorInitializer(tclass, NULL); } static void CFunc_ParseCtorInitializer(void) { CtorChain *chain; ENodeList *args; TypeClass *tclass; ObjMemberVar *ivar; ClassList *base; VClassList *vbase; ENode *expr; Type *origtype; ctor_chain = NULL; if (tk == ':') { do { tclass = NULL; switch ((tk = lex())) { case TK_IDENTIFIER: for (ivar = cscope_currentclass->ivars; ivar; ivar = ivar->next) { if (ivar->name == tkidentifier && lookahead() == '(') goto do_ivar; } for (base = cscope_currentclass->bases; base; base = base->next) { if (base->base->classname == tkidentifier) { if (lookahead() == '(') { tclass = base->base; tk = lex(); } else { tkidentifier = base->base->classname; } break; } } break; case TK_COLON_COLON: break; default: CError_Error(CErrorStr212); return; } if (!tclass) tclass = CClass_GetQualifiedClass(); if (tclass) { for (vbase = cscope_currentclass->vbases; vbase; vbase = vbase->next) { if (vbase->base == tclass) break; } if (vbase) { for (chain = ctor_chain; chain; chain = chain->next) { if (chain->what == CtorChain_VBase && chain->u.vbase == vbase) { CError_Error(CErrorStr212); return; } } chain = lalloc(sizeof(CtorChain)); chain->what = CtorChain_VBase; chain->u.vbase = vbase; } else { for (base = cscope_currentclass->bases; base; base = base->next) { if (base->base == tclass) break; } if (base) { for (chain = ctor_chain; chain; chain = chain->next) { if (chain->what == CtorChain_Base && chain->u.base == base) { CError_Error(CErrorStr212); return; } } chain = lalloc(sizeof(CtorChain)); chain->what = CtorChain_Base; chain->u.base = base; } else { CError_Error(CErrorStr212); return; } } } else { for (ivar = cscope_currentclass->ivars; ivar; ivar = ivar->next) { if (ivar->name == tkidentifier) break; } if (ivar) { do_ivar: for (chain = ctor_chain; chain; chain = chain->next) { if (chain->what == CtorChain_MemberVar && chain->u.membervar == ivar) CError_Error(CErrorStr212); } chain = lalloc(sizeof(CtorChain)); chain->what = CtorChain_MemberVar; chain->u.membervar = ivar; } else { CError_Error(CErrorStr212); return; } tk = lex(); } if (tk != '(') { CError_Error(CErrorStr114); return; } tk = lex(); args = CExpr_ScanExpressionList(1); if (tk != ')') { CError_Error(CErrorStr115); return; } switch (chain->what) { case CtorChain_Base: expr = CABI_MakeThisExpr(NULL, chain->u.base->offset); chain->objexpr = CExpr_ConstructObject(chain->u.base->base, expr, args, 1, 0, 0, 0, 1); break; case CtorChain_VBase: expr = CABI_MakeThisExpr(chain->u.vbase->base, chain->u.vbase->offset); chain->objexpr = CExpr_ConstructObject(chain->u.vbase->base, expr, args, 1, 0, 0, 0, 1); break; case CtorChain_MemberVar: expr = CABI_MakeThisExpr(cscope_currentclass, chain->u.membervar->offset); expr->flags = chain->u.membervar->qual & ENODE_FLAG_QUALS; switch (chain->u.membervar->type->type) { case TYPECLASS: chain->objexpr = CExpr_ConstructObject(TYPE_CLASS(chain->u.membervar->type), expr, args, 1, 1, 0, 1, 1); break; case TYPEARRAY: if (args) { CError_Error(CErrorStr212); continue; } chain->objexpr = NULL; break; default: if (!args) { args = lalloc(sizeof(ENodeList)); args->next = NULL; args->node = CExpr_DoExplicitConversion(chain->u.membervar->type, chain->u.membervar->qual, NULL); } if (args->next) { CError_Error(CErrorStr212); return; } expr = makemonadicnode(expr, EINDIRECT); expr->rtype = chain->u.membervar->type; if (IS_TYPE_BITFIELD(origtype = expr->rtype)) { expr->data.monadic = makemonadicnode(expr->data.monadic, EBITFIELD); expr->data.monadic->rtype = origtype; expr->rtype = TYPE_BITFIELD(origtype)->bitfieldtype; } chain->objexpr = makediadicnode(expr, CExpr_AssignmentPromotion(args->node, expr->rtype, expr->flags, 1), EASS); } break; default: CError_FATAL(3286); } chain->next = ctor_chain; ctor_chain = chain; } while ((tk = lex()) == ','); } } static void CFunc_FunctionRedefinedCheck(Object *func) { if (TYPE_FUNC(func->type)->flags & FUNC_FLAGS_100) CError_Error(CErrorStr333, func); if ((TYPE_FUNC(func->type)->flags & FUNC_FLAGS_2) && func->datatype != DINLINEFUNC) CError_Error(CErrorStr333, func); TYPE_FUNC(func->type)->flags |= FUNC_FLAGS_2; } static Object *CFunc_DeclareFuncName(char *str, HashNameNode *name) { Object *obj; Object *aliasobj; DeclInfo di; memclrw(&di, sizeof(di)); di.name = name; di.storageclass = TK_STATIC; di.qual = Q_CONST; di.thetype = CDecl_NewArrayType(TYPE(&stchar), strlen(str) + 1); obj = CParser_NewGlobalDataObject(&di); aliasobj = CParser_NewAliasObject(obj, 0); obj->nspace = cscope_root; obj->datatype = DDATA; CFunc_NameLocalStaticDataObject(obj, obj->name->name); return aliasobj; } void CFunc_ParseFuncDef(Object *func, DeclInfo *di, TypeClass *tclass, Boolean is_method, Boolean is_static, NameSpace *nspace) { Boolean has_try; Object *nameobj_func; Object *nameobj_FUNCTION; Object *nameobj_pretty; char *prettyname; Statement *stmt18; Statement *stmt16; Statement firstStmt; DeclThing thing; CScopeSave scope; nameobj_func = NULL; nameobj_FUNCTION = NULL; nameobj_pretty = NULL; prettyname = NULL; CError_ASSERT(3373, IS_TYPE_FUNC(func->type)); CFunc_FunctionRedefinedCheck(func); CParser_UpdateObject(func, di); if (!is_method) { CScope_SetFunctionScope(func, &scope); if (tclass) cscope_current = tclass->nspace; } else { CScope_SetMethodScope(func, tclass, is_static, &scope); } if (nspace) cscope_current = nspace; if (cscope_currentclass) CClass_MemberDef(func, cscope_currentclass); cfunc_is_extern_c = di->x4E; CError_ASSERT(3392, IS_TYPE_FUNC(func->type)); if (di->x45 && (func->qual & Q_ASM)) CError_Error(CErrorStr176); if (cparamblkptr->isPrecompiling == 1 && !(func->qual & Q_INLINE)) CError_ErrorTerm(CErrorStr180); if (di->x49) CError_Error(CErrorStr127); CFunc_FuncGenSetup(&firstStmt, func); if (!IS_TYPE_VOID(TYPE_FUNC(func->type)->functype)) IsCompleteType(TYPE_FUNC(func->type)->functype); SetupFunctionArguments(func, di, &firstStmt); stmt18 = curstmt; CPrep_GetFileOffsetInfo2(&cparser_fileoffset, &sourceoffset, &sourcefilepath); functionbodyoffset = sourceoffset; firstStmt.sourceoffset = sourceoffset; functionbodypath = sourcefilepath; firstStmt.sourcefilepath = sourcefilepath; if (di->x45) CFunc_AdjustOldStyleArgs(); if (di->x1C) CScope_MergeNameSpace(cscope_current, di->x1C); if (tk == TK_TRY) { tk = lex(); has_try = 1; } else { has_try = 0; } if (CClass_IsConstructor(func)) { CError_ASSERT(3445, cscope_currentclass); CFunc_ParseCtorInitializer(); CFunc_CheckCtorInitializer(cscope_currentclass, ctor_chain); } CPrep_TokenStreamFlush(); if (!(func->qual & Q_ASM)) { if (tk == '{') { if (!has_try) tk = lex(); } else { CError_ErrorSkip(CErrorStr135); has_try = 0; } if (func->name) { nameobj_func = CFunc_DeclareFuncName(func->name->name, GetHashNameNode("__func__")); nameobj_FUNCTION = CFunc_DeclareFuncName(func->name->name, GetHashNameNode("__FUNCTION__")); prettyname = CError_GetObjectName(func); nameobj_pretty = CFunc_DeclareFuncName(prettyname, GetHashNameNode("__PRETTY_FUNCTION__")); } if (!copts.cplusplus) CFunc_ParseLocalDeclarationList(0, 0, 0, 0); thing.switchinfo = NULL; thing.loopContinue = NULL; thing.loopBreak = NULL; thing.thetype = TYPE_FUNC(func->type)->functype; thing.qual = TYPE_FUNC(func->type)->qual; if (has_try) { CExcept_ScanTryBlock(&thing, CClass_IsConstructor(func) || CClass_IsDestructor(func)); if (tk != 0) CPrep_UnLex(); tk = '}'; } else { while (tk != '}') statement(&thing); } stmt16 = curstmt; if (stmt16->type != ST_RETURN && stmt16->type != ST_GOTO) { CPrep_GetFileOffsetInfo2(&cparser_fileoffset, &sourceoffset, &sourcefilepath); CFunc_AppendStatement(ST_RETURN); curstmt->dobjstack = NULL; curstmt->expr = NULL; if ( (copts.cplusplus || copts.c9x) && !strcmp(func->name->name, "main") && TYPE_FUNC(func->type)->functype == TYPE(&stsignedint) ) curstmt->expr = intconstnode(TYPE(&stsignedint), 0); if ( stmt16->type == ST_EXPRESSION && stmt16->expr->type == EFUNCCALL && stmt16->expr->rtype == &stvoid && (stmt16->expr->flags & ENODE_FLAG_VOLATILE) ) curstmt->flags |= StmtFlag_8; } CheckCLabels(); if (nameobj_func && (nameobj_func->flags & OBJECT_FLAGS_UNUSED)) CInit_DeclareData(nameobj_func->u.alias.object, func->name->name, NULL, strlen(func->name->name) + 1); if (nameobj_FUNCTION && (nameobj_FUNCTION->flags & OBJECT_FLAGS_UNUSED)) CInit_DeclareData(nameobj_FUNCTION->u.alias.object, func->name->name, NULL, strlen(func->name->name) + 1); if (nameobj_pretty && (nameobj_pretty->flags & OBJECT_FLAGS_UNUSED)) CInit_DeclareData(nameobj_pretty->u.alias.object, prettyname, NULL, strlen(prettyname) + 1); if (!fatalerrors) { if (CClass_IsConstructor(func)) CABI_TransConstructor(func, stmt18, cscope_currentclass, NULL, has_try); if (CClass_IsDestructor(func)) CABI_TransDestructor(func, func, &firstStmt, cscope_currentclass, 0); CFunc_DestructorCleanup(&firstStmt); CFunc_CodeCleanup(&firstStmt); symdeclend = CPrep_GetFileOffsetInfo(&cparser_fileoffset); CFunc_Gen(&firstStmt, func, di->x45); } } else { if (tk == '{') { in_assembler = 1; tk = lex(); in_assembler = 0; } else { CError_ErrorSkip(CErrorStr135); } CFunc_ParseLocalDeclarationList(1, 0, 0, 0); Assembler(func); } if (tk != '}') CError_Error(CErrorStr130); CScope_RestoreScope(&scope); } void InitExpr_Register(ENode *expr, Object *object) { InitExpr *initexpr; InitExpr *scan; if ( cparamblkptr->isPrecompiling == 1 && object->sclass != TK_STATIC && !(object->qual & (Q_20000 | Q_OVERLOAD)) ) { CError_Error(CErrorStr180); return; } if (copts.suppress_init_code) return; initexpr = galloc(sizeof(InitExpr)); initexpr->next = NULL; initexpr->object = object; initexpr->expr = CInline_CopyExpression(expr, CopyMode1); if (init_expressions) { scan = init_expressions; while (scan->next) scan = scan->next; scan->next = initexpr; } else { init_expressions = initexpr; } } void CFunc_GenerateDummyFunction(Object *func) { NameSpace *nspace; Boolean saveDebugInfo; Statement firstStmt; if (!anyerrors) { nspace = CFunc_FuncGenSetup(&firstStmt, NULL); saveDebugInfo = copts.isGeneratingDebugInfo; copts.isGeneratingDebugInfo = 0; CFunc_CodeCleanup(&firstStmt); CFunc_Gen(&firstStmt, func, 0); cscope_current = nspace->parent; copts.isGeneratingDebugInfo = saveDebugInfo; } } void CFunc_GenerateSingleExprFunc(Object *func, ENode *expr) { NameSpace *nspace; Boolean saveDebugInfo; Statement firstStmt; Statement *stmt; if (cparamblkptr->isPrecompiling == 1) { CError_Error(CErrorStr180); return; } if (!anyerrors) { nspace = CFunc_FuncGenSetup(&firstStmt, func); saveDebugInfo = copts.isGeneratingDebugInfo; copts.isGeneratingDebugInfo = 0; stmt = CFunc_AppendStatement(ST_EXPRESSION); stmt->expr = expr; CFunc_CodeCleanup(&firstStmt); CInline_GenFunc(&firstStmt, func, 0); cscope_current = nspace->parent; copts.isGeneratingDebugInfo = saveDebugInfo; } } void CFunc_GenerateDummyCtorFunc(Object *func, Object *real_ctor) { ENode *expr; NameSpace *nspace; FuncArg *arg1; FuncArg *arg0; ENodeList *list; Boolean saveDebugInfo; Statement firstStmt; Statement *stmt; if (cparamblkptr->isPrecompiling == 1) { CError_Error(CErrorStr180); return; } if (!anyerrors) { cscope_currentfunc = func; nspace = CFunc_FuncGenSetup(&firstStmt, func); saveDebugInfo = copts.isGeneratingDebugInfo; copts.isGeneratingDebugInfo = 0; CFunc_SetupNewFuncArgs(func, TYPE_FUNC(func->type)->args); expr = CExpr_NewENode(EFUNCCALL); expr->type = EFUNCCALL; expr->cost = 200; expr->rtype = TYPE(&void_ptr); expr->data.funccall.funcref = CExpr_MakeObjRefNode(real_ctor, 0); expr->data.funccall.functype = TYPE_FUNC(func->type); CError_ASSERT(3716, IS_TYPE_FUNC(real_ctor->type)); CError_ASSERT(3717, TYPE_FUNC(real_ctor->type)->flags & FUNC_FLAGS_METHOD); CError_ASSERT(3718, arg0 = TYPE_FUNC(real_ctor->type)->args); CError_ASSERT(3720, arg1 = arg0->next); CError_ASSERT(3721, arguments); list = lalloc(sizeof(ENodeList)); expr->data.funccall.args = list; list->node = create_objectnode(arguments->object); if (TYPE_METHOD(real_ctor->type)->theclass->flags & CLASS_FLAGS_20) { CError_ASSERT(3727, arg1 = arg1->next); CError_ASSERT(3728, arguments->next); list->next = lalloc(sizeof(ENodeList)); list = list->next; list->node = create_objectnode(arguments->next->object); } while (arg1) { CError_ASSERT(3737, arg1->dexpr); list->next = lalloc(sizeof(ENodeList)); list = list->next; list->node = CExpr_GetDefaultArgument(expr->data.funccall.funcref, arg1); arg1 = arg1->next; } list->next = NULL; stmt = CFunc_AppendStatement(ST_RETURN); stmt->expr = expr; CFunc_CodeCleanup(&firstStmt); CInline_GenFunc(&firstStmt, func, 0); cscope_current = nspace->parent; cscope_currentfunc = NULL; copts.isGeneratingDebugInfo = saveDebugInfo; } }