#include "compiler/CExpr.h" #include "compiler/CABI.h" #include "compiler/CClass.h" #include "compiler/CDecl.h" #include "compiler/CInt64.h" #include "compiler/CError.h" #include "compiler/CFunc.h" #include "compiler/CInline.h" #include "compiler/CMachine.h" #include "compiler/CParser.h" #include "compiler/CScope.h" #include "compiler/CodeGen.h" #include "compiler/CompilerTools.h" #include "compiler/enode.h" #include "compiler/objects.h" #include "compiler/scopes.h" #ifdef __MWERKS__ #undef va_start #undef va_arg #define va_start(ap, parm) ap = __va_start(parm) #define __va_start(parm) (va_list) (&parm + 1) //#define va_arg(ap, type) ((((type *) (ap = (va_list) (( ((long) ap + sizeof(type) - 1) & ~(sizeof(type)) ) + sizeof(type) ) ))[-1])) #define va_arg(ap, type) (*(((type *) (ap = (char *)((((unsigned long)ap + __builtin_align(type) - 1) & ~(__builtin_align(type) - 1) ) + sizeof(type)))) - 1)) #endif // TODO MOVE ME extern ENode *CSOM_EnvCheck(ENode *, ENodeList *); extern Boolean CTemplTool_IsTemplateArgumentDependentExpression(ENode *expr); extern ENode *CTemplTool_DeduceDefaultArg(Object *func, ENode *expr); extern Boolean CObjC_IsCompatibleType(Type *a, Type *b); ENode *assign_node; Boolean temp_reference_init; static SInt32 assign_value; // type? static ENode *firstarrayexpr; static Match5 user_std_match; static Boolean cexpr_hascall; static Boolean cexpr_esearch_bool[MAXEXPR]; static Boolean cexpr_rsearch_bool[MAXEXPR]; static CExprSearchCB cexpr_esearch_callback; static CExprReplaceCB cexpr_rsearch_callback; static Type *cexpr_left_conversion_type; static Type *cexpr_right_conversion_type; // data objects, need to figure out the types static void *diadic_arg1; static void *diadic_arg2; static void *mon_arg; static void CExpr_RecSearchExprTree(ENode *expr) { ENodeList *list; restart: if (cexpr_esearch_bool[expr->type]) cexpr_esearch_callback(expr); switch (expr->type) { case EPOSTINC: case EPOSTDEC: case EPREINC: case EPREDEC: case EINDIRECT: case EMONMIN: case EBINNOT: case ELOGNOT: case EFORCELOAD: case ETYPCON: case EBITFIELD: expr = expr->data.monadic; goto restart; case EMUL: case EMULV: case EDIV: case EMODULO: case EADDV: case ESUBV: case EADD: case ESUB: case ESHL: case ESHR: case ELESS: case EGREATER: case ELESSEQU: case EGREATEREQU: case EEQU: case ENOTEQU: case EAND: case EXOR: case EOR: case ELAND: case ELOR: case EASS: case EMULASS: case EDIVASS: case EMODASS: case EADDASS: case ESUBASS: case ESHLASS: case ESHRASS: case EANDASS: case EXORASS: case EORASS: case ECOMMA: case EPMODULO: case EROTL: case EROTR: case EBCLR: case EBTST: case EBSET: CExpr_RecSearchExprTree(expr->data.diadic.left); expr = expr->data.diadic.right; goto restart; case EINTCONST: case EFLOATCONST: case ESTRINGCONST: case EOBJREF: case EPRECOMP: case ETEMP: case EARGOBJ: case ELOCOBJ: case ELABEL: case EOBJLIST: case EMEMBER: case EINSTRUCTION: case EVECTOR128CONST: return; case EFUNCCALL: case EFUNCCALLP: for (list = expr->data.funccall.args; list; list = list->next) CExpr_RecSearchExprTree(list->node); expr = expr->data.funccall.funcref; goto restart; case ENULLCHECK: CExpr_RecSearchExprTree(expr->data.nullcheck.nullcheckexpr); expr = expr->data.nullcheck.condexpr; goto restart; case EMFPOINTER: CExpr_RecSearchExprTree(expr->data.mfpointer.accessnode); expr = expr->data.mfpointer.mfpointer; goto restart; case ECOND: CExpr_RecSearchExprTree(expr->data.cond.cond); CExpr_RecSearchExprTree(expr->data.cond.expr1); expr = expr->data.cond.expr2; goto restart; case ENEWEXCEPTION: case ENEWEXCEPTIONARRAY: CExpr_RecSearchExprTree(expr->data.newexception.initexpr); expr = expr->data.newexception.tryexpr; goto restart; case EMYSTERY67: if (expr->data.itc.initexpr) CExpr_RecSearchExprTree(expr->data.itc.initexpr); if (expr->data.itc.tryexpr) CExpr_RecSearchExprTree(expr->data.itc.tryexpr); if (expr->data.itc.catchexpr) CExpr_RecSearchExprTree(expr->data.itc.catchexpr); if (expr->data.itc.result) CExpr_RecSearchExprTree(expr->data.itc.result); return; default: #line 128 CError_FATAL(); } } void CExpr_SearchExprTree(ENode *expr, CExprSearchCB callback, int count, ...) { va_list ap; short i; cexpr_esearch_callback = callback; va_start(ap, count); for (i = 0; i < MAXEXPR; i++) cexpr_esearch_bool[i] = 0; i = 0; while ((short) i < count) { cexpr_esearch_bool[va_arg(ap, int)] = 1; ++i; } va_end(ap); CExpr_RecSearchExprTree(expr); } static ENode *CExpr_RecSearchExprTreeReplace(ENode *expr) { ENodeList *list; ENode *replaced; if (cexpr_rsearch_bool[expr->type]) { replaced = cexpr_rsearch_callback(expr); if (!replaced) return expr; expr = replaced; } switch (expr->type) { case EPOSTINC: case EPOSTDEC: case EPREINC: case EPREDEC: case EINDIRECT: case EMONMIN: case EBINNOT: case ELOGNOT: case EFORCELOAD: case ETYPCON: case EBITFIELD: expr->data.monadic = CExpr_RecSearchExprTreeReplace(expr->data.monadic); return expr; case EMUL: case EMULV: case EDIV: case EMODULO: case EADDV: case ESUBV: case EADD: case ESUB: case ESHL: case ESHR: case ELESS: case EGREATER: case ELESSEQU: case EGREATEREQU: case EEQU: case ENOTEQU: case EAND: case EXOR: case EOR: case ELAND: case ELOR: case EASS: case EMULASS: case EDIVASS: case EMODASS: case EADDASS: case ESUBASS: case ESHLASS: case ESHRASS: case EANDASS: case EXORASS: case EORASS: case ECOMMA: case EPMODULO: case EROTL: case EROTR: case EBCLR: case EBTST: case EBSET: expr->data.diadic.left = CExpr_RecSearchExprTreeReplace(expr->data.diadic.left); expr->data.diadic.right = CExpr_RecSearchExprTreeReplace(expr->data.diadic.right); return expr; case EINTCONST: case EFLOATCONST: case ESTRINGCONST: case EOBJREF: case EPRECOMP: case ETEMP: case EARGOBJ: case ELOCOBJ: case ELABEL: case EMEMBER: case EINSTRUCTION: case EVECTOR128CONST: return expr; case EFUNCCALL: case EFUNCCALLP: for (list = expr->data.funccall.args; list; list = list->next) list->node = CExpr_RecSearchExprTreeReplace(list->node); expr->data.funccall.funcref = CExpr_RecSearchExprTreeReplace(expr->data.funccall.funcref); return expr; case ENULLCHECK: expr->data.nullcheck.nullcheckexpr = CExpr_RecSearchExprTreeReplace(expr->data.nullcheck.nullcheckexpr); expr->data.nullcheck.condexpr = CExpr_RecSearchExprTreeReplace(expr->data.nullcheck.condexpr); return expr; case EMFPOINTER: expr->data.mfpointer.accessnode = CExpr_RecSearchExprTreeReplace(expr->data.mfpointer.accessnode); expr->data.mfpointer.mfpointer = CExpr_RecSearchExprTreeReplace(expr->data.mfpointer.mfpointer); return expr; case ECOND: expr->data.cond.cond = CExpr_RecSearchExprTreeReplace(expr->data.cond.cond); expr->data.cond.expr1 = CExpr_RecSearchExprTreeReplace(expr->data.cond.expr1); expr->data.cond.expr2 = CExpr_RecSearchExprTreeReplace(expr->data.cond.expr2); return expr; default: #line 220 CError_FATAL(); return NULL; } } ENode *CExpr_SearchExprTreeReplace(ENode *expr, CExprReplaceCB callback, int count, ...) { va_list ap; short i; cexpr_rsearch_callback = callback; va_start(ap, count); for (i = 0; i < MAXEXPR; i++) cexpr_rsearch_bool[i] = 0; i = 0; while ((short) i < count) { cexpr_rsearch_bool[va_arg(ap, int)] = 1; ++i; } va_end(ap); return CExpr_RecSearchExprTreeReplace(expr); } static void CExpr_HasFuncCallCallBack(ENode *expr) { cexpr_hascall = 1; } Boolean CExpr_HasFuncCall(ENode *expr) { cexpr_hascall = 0; CExpr_SearchExprTree(expr, CExpr_HasFuncCallCallBack, 2, EFUNCCALL, EFUNCCALLP); return cexpr_hascall; } void CExpr_AliasTransform(ENode *expr) { ENode *n; Object *obj = expr->data.objref; if (obj->u.alias.offset) { n = makediadicnode( create_objectrefnode(obj->u.alias.object), intconstnode(TYPE(&stunsignedlong), obj->u.alias.offset), EADD); *expr = *n; } else { expr->data.objref = obj->u.alias.object; } } ENode *CExpr_UnaryFloatExpression(ENode *expr) { return expr; } ENode *CExpr_BinaryFloatExpression(ENode *expr) { return expr; } ENode *CExpr_NewENode(ENodeType ty) { ENode *expr = lalloc(sizeof(ENode)); memclrw(expr, sizeof(ENode)); expr->type = ty; return expr; } ENode *CExpr_NewTemplDepENode(TemplDepSubType t) { ENode *expr = CExpr_NewENode(ETEMPLDEP); expr->rtype = &sttemplexpr; expr->data.templdep.subtype = t; return expr; } ENode *nullnode(void) { ENode *expr = CExpr_NewENode(EINTCONST); expr->rtype = (Type *) &stsignedlong; return expr; } ENode *intconstnode(Type *type, SInt32 value) { ENode *expr = CExpr_NewENode(EINTCONST); expr->rtype = type; CInt64_SetLong(&expr->data.intval, value); return expr; } ENode *stringconstnode(char *str) { ENode *expr; SInt32 size; size = strlen(str) + 1; expr = CExpr_NewENode(ESTRINGCONST); expr->rtype = CDecl_NewArrayType((Type *) &stchar, size); expr->data.string.size = size; expr->data.string.data = str; expr->data.string.ispascal = 0; if (copts.const_strings) expr->flags = Q_CONST; expr = makemonadicnode(expr, EINDIRECT); expr->data.monadic->rtype = CDecl_NewPointerType(expr->rtype); return expr; } ENode *forceintegral(ENode *expr) { if (!IS_TYPE_ENUM(expr->rtype)) { CError_Error(144); return nullnode(); } else { expr->rtype = TYPE_ENUM(expr->rtype)->enumtype; return expr; } } ENode *makemonadicnode(ENode *inner, ENodeType ty) { ENode *expr = lalloc(sizeof(ENode)); expr->type = ty; if ((expr->cost = inner->cost) == 0) expr->cost = 1; expr->flags = inner->flags & ENODE_FLAG_QUALS; expr->rtype = inner->rtype; expr->data.monadic = inner; return expr; } ENode *makediadicnode(ENode *left, ENode *right, ENodeType ty) { ENode *expr = lalloc(sizeof(ENode)); expr->type = ty; expr->rtype = left->rtype; expr->data.diadic.left = left; expr->data.diadic.right = right; if (left->cost != right->cost) { expr->cost = right->cost; if (left->cost > expr->cost) expr->cost = left->cost; } else { expr->cost = right->cost + 1; if (expr->cost > 200) expr->cost = 200; } expr->flags = (left->flags | right->flags) & ENODE_FLAG_QUALS; return expr; } ENode *makecommaexpression(ENode *left, ENode *right) { ENode *expr; if (ENODE_IS(right, EINDIRECT) && !ENODE_IS(right->data.monadic, EBITFIELD)) { Boolean savecpp = copts.cplusplus; copts.cplusplus = 1; expr = makediadicnode(left, getnodeaddress(right, 0), ECOMMA); copts.cplusplus = savecpp; expr->rtype = expr->data.diadic.right->rtype; expr = makemonadicnode(expr, EINDIRECT); } else { expr = makediadicnode(left, right, ECOMMA); } expr->rtype = right->rtype; expr->flags = right->flags; return expr; } short iszero(ENode *expr) { switch (expr->type) { case EINTCONST: return CInt64_IsZero(&expr->data.intval); case EFLOATCONST: return CMach_FloatIsZero(expr->data.floatval); default: return 0; } } short isnotzero(ENode *expr) { Object *obj; switch (expr->type) { case EINTCONST: return !CInt64_IsZero(&expr->data.intval); case EFLOATCONST: return !CMach_FloatIsZero(expr->data.floatval); case ESTRINGCONST: case ETEMP: return 1; case EOBJREF: obj = expr->data.objref; break; case EADD: case ESUB: if (ENODE_IS(expr->data.diadic.left, EOBJREF) && ENODE_IS(expr->data.diadic.right, EINTCONST)) { obj = expr->data.diadic.left->data.objref; break; } if (ENODE_IS(expr->data.diadic.left, EINTCONST) && ENODE_IS(expr->data.diadic.right, EOBJREF)) { obj = expr->data.diadic.right->data.objref; break; } return 0; default: return 0; } switch (obj->datatype) { case DLOCAL: return 1; default: return 0; } } Boolean CExpr_IsOne(ENode *expr) { if (ENODE_IS(expr, EINTCONST)) return CInt64_Equal(expr->data.intval, cint64_one); else if (ENODE_IS(expr, EFLOATCONST)) return CMach_FloatIsOne(expr->data.floatval); else return 0; } Boolean CExpr_AllBitsSet(ENode *expr) { SInt32 v; if (ENODE_IS(expr, EINTCONST)) { switch (expr->rtype->size) { case 1: v = CInt64_GetULong(&expr->data.intval) & 0xFF; return v == 0xFF; case 2: v = CInt64_GetULong(&expr->data.intval) & 0xFFFF; return v == 0xFFFF; case 3: v = CInt64_GetULong(&expr->data.intval) & 0xFFFFFF; return v == 0xFFFFFF; case 4: v = CInt64_GetULong(&expr->data.intval) & 0xFFFFFFFF; return v == 0xFFFFFFFF; default: return CInt64_Equal(expr->data.intval, cint64_negone); } } return 0; } ENode *CExpr_NewETEMPNode(Type *type, Boolean assign_id) { ENode *expr = lalloc(sizeof(ENode)); expr->type = ETEMP; expr->cost = 0; expr->flags = 0; expr->rtype = CDecl_NewPointerType(type); expr->data.temp.type = type; expr->data.temp.uniqueid = assign_id ? CParser_GetUniqueID() : 0; expr->data.temp.needs_dtor = 0; return expr; } static ENode *CExpr_DerefETEMPCopy(ENode *expr) { ENode *copy; #line 636 CError_ASSERT(expr->rtype->type == TYPEPOINTER); copy = lalloc(sizeof(ENode)); *copy = *expr; copy = makemonadicnode(copy, EINDIRECT); copy->rtype = TYPE_POINTER(copy->rtype)->target; } ENode *CExpr_GetETEMPCopy(ENode *expr) { ENode *newnode; ENode *assnode; ENode *finalnode; newnode = CExpr_NewETEMPNode(expr->rtype, 1); newnode->flags = expr->flags; assnode = makediadicnode(CExpr_DerefETEMPCopy(newnode), expr, EASS); assnode->data.diadic.right = lalloc(sizeof(ENode)); *assnode->data.diadic.right = *expr; *expr = *assnode; finalnode = makemonadicnode(newnode, EINDIRECT); finalnode->rtype = expr->rtype; return finalnode; } ENode *integralpromote(ENode *expr) { if (!IS_TYPE_INT(expr->rtype)) expr = forceintegral(expr); if (TYPE_INTEGRAL(expr->rtype)->integral >= IT_INT) return expr; if (!ENODE_IS(expr, EINTCONST)) expr = makemonadicnode(expr, ETYPCON); expr->rtype = (Type *) &stsignedint; return expr; } CInt64 CExpr_IntConstConvert(Type *a, Type *b, CInt64 val) { if (a == (Type *) &stbool) return CMach_CalcIntDiadic(b, val, TK_LOGICAL_NE, cint64_zero); else return CMach_CalcIntDiadic(a, val, '+', cint64_zero); } ENode *promote(ENode *expr, Type *type) { if (ENODE_IS(expr, EINTCONST)) { if (IS_TYPE_FLOAT(type)) { expr->type = EFLOATCONST; expr->data.floatval = CMach_CalcFloatConvertFromInt(expr->rtype, expr->data.intval); } else { expr->data.intval = CExpr_IntConstConvert(type, expr->rtype, expr->data.intval); } expr->rtype = type; return expr; } if (ENODE_IS(expr, EFLOATCONST)) { if (IS_TYPE_FLOAT(type)) { expr->data.floatval = CMach_CalcFloatConvert(type, expr->data.floatval); expr->rtype = type; return expr; } else if (IS_TYPE_INT(type)) { expr->data.intval = CMach_CalcIntConvertFromFloat(type, expr->data.floatval); expr->type = EINTCONST; expr->rtype = type; return expr; } } expr = makemonadicnode(expr, ETYPCON); expr->rtype = type; return expr; } void CExpr_ArithmeticConversion(ENode **left, ENode **right) { switch ((*left)->rtype->type) { case TYPEINT: case TYPEFLOAT: break; case TYPEENUM: (*left)->rtype = TYPE_ENUM((*left)->rtype)->enumtype; break; default: CError_Error(144); (*left) = nullnode(); } switch ((*right)->rtype->type) { case TYPEINT: case TYPEFLOAT: break; case TYPEENUM: (*right)->rtype = TYPE_ENUM((*right)->rtype)->enumtype; break; default: CError_Error(144); (*right) = nullnode(); } if (IS_TYPE_FLOAT((*left)->rtype) || IS_TYPE_FLOAT((*right)->rtype)) { if ((*left)->rtype != (*right)->rtype) { if (TYPE_INTEGRAL((*left)->rtype)->integral > TYPE_INTEGRAL((*right)->rtype)->integral) *right = promote(*right, (*left)->rtype); else *left = promote(*left, (*right)->rtype); } return; } *left = integralpromote(*left); *right = integralpromote(*right); if ((*left)->rtype != (*right)->rtype) { if (TYPE_INTEGRAL((*left)->rtype)->integral < TYPE_INTEGRAL((*right)->rtype)->integral) { ENode **tmp = left; left = right; right = tmp; } if ((*left)->rtype->size == (*right)->rtype->size && !is_unsigned((*left)->rtype) && is_unsigned((*right)->rtype)) { if ((*left)->rtype == (Type *) &stsignedlong) { *left = promote(*left, (Type *) &stunsignedlong); } else { #line 838 CError_ASSERT((*left)->rtype == (Type *) &stsignedlonglong); *left = promote(*left, (Type *) &stunsignedlonglong); } } *right = promote(*right, (*left)->rtype); } } static ENode *CExpr_GetEA(ENode *expr) { ENode *copy; for (;;) { switch (expr->type) { case EINDIRECT: expr = expr->data.monadic; for (;;) { switch (expr->type) { case EOBJREF: copy = lalloc(sizeof(ENode)); *copy = *expr; return copy; case ECOMMA: expr = expr->data.diadic.right; continue; default: return CExpr_GetETEMPCopy(expr); } } break; case EPOSTINC: case EPOSTDEC: case EPREINC: case EPREDEC: expr = expr->data.monadic; continue; case EASS: case EMULASS: case EDIVASS: case EMODASS: case EADDASS: case ESUBASS: case ESHLASS: case ESHRASS: case EANDASS: case EXORASS: case EORASS: expr = expr->data.monadic; continue; case ECOMMA: expr = expr->data.diadic.right; continue; default: return NULL; } } } ENode *CExpr_TempModifyExpr(ENode *expr) { // register issues Type *type; ENode *tempnode; ENode *eanode; ENode *assnode2; ENode *left; ENode *right; ENode *work; type = expr->rtype; tempnode = CExpr_NewETEMPNode(type, 1); eanode = CExpr_GetEA(expr); if (!eanode) { CError_Error(142); return expr; } left = makemonadicnode(tempnode, EINDIRECT); left->rtype = type; work = makediadicnode(left, expr, EASS); left = makemonadicnode(eanode, EINDIRECT); left->rtype = type; right = nullnode(); right->rtype = (Type *) &stbool; CInt64_SetLong(&right->data.intval, 1); assnode2 = makediadicnode(left, right, EASS); work = makediadicnode(work, assnode2, ECOMMA); right = makemonadicnode(tempnode, EINDIRECT); right->rtype = type; work = makediadicnode(work, right, ECOMMA); return work; } Boolean CExpr_IsLValue(ENode *expr) { while (!ENODE_IS(expr, EINDIRECT)) { switch (expr->type) { case EPREINC: case EPREDEC: return copts.cplusplus; case EASS: case EMULASS: case EDIVASS: case EMODASS: case EADDASS: case ESUBASS: case ESHLASS: case ESHRASS: case EANDASS: case EXORASS: case EORASS: if (!copts.cplusplus) return 0; expr = expr->data.diadic.left; continue; case ECOMMA: if (!copts.cplusplus) return 0; expr = expr->data.diadic.right; continue; case ECOND: if ( copts.cplusplus && is_typesame(expr->data.cond.expr1->rtype, expr->data.cond.expr2->rtype) && (expr->data.cond.expr1->rtype->type != TYPEPOINTER || (UInt32) (expr->data.cond.expr1->flags & ENODE_FLAG_QUALS) == (expr->data.cond.expr2->flags & ENODE_FLAG_QUALS)) ) { return CExpr_IsLValue(expr->data.cond.expr1) && CExpr_IsLValue(expr->data.cond.expr2); } return 0; default: return 0; } } expr = expr->data.monadic; switch (expr->type) { case ETEMP: return 0; case EFUNCCALL: if (expr->data.funccall.functype->functype->type != TYPEPOINTER || (expr->data.funccall.functype->flags & FUNC_FLAGS_1000)) return 0; default: return 1; } } ENode *CExpr_LValue(ENode *expr, Boolean flag1, Boolean flag2) { ENode *eanode; ENode *tmpnode; loop: switch (expr->type) { case ETYPCON: if (copts.pointercast_lvalue || !copts.ANSI_strict) { if (expr->rtype->type == TYPEPOINTER && expr->data.monadic->rtype->type == TYPEPOINTER) { switch (expr->data.monadic->type) { case EINDIRECT: case ETYPCON: expr->data.monadic->rtype = expr->rtype; expr->data.monadic->flags = expr->flags; expr = expr->data.monadic; goto loop; } } } break; case EINDIRECT: if (flag2) { if (!CExpr_IsLValue(expr)) CError_Warning(142); if ( ENODE_IS(expr->data.monadic, EOBJREF) && expr->data.monadic->data.objref->name == this_name_node && cscope_currentfunc && cscope_currentclass && expr->data.monadic->data.objref == CClass_ThisSelfObject()) CError_Error(189); } if (flag1) { if (CParser_IsConst(expr->rtype, expr->flags & ENODE_FLAG_QUALS)) CError_Error(179); } return expr; case EPREINC: case EPREDEC: case EASS: case EMULASS: case EDIVASS: case EMODASS: case EADDASS: case ESUBASS: case ESHLASS: case ESHRASS: case EANDASS: case EXORASS: case EORASS: case ECOMMA: if (copts.cplusplus) { if ((eanode = CExpr_GetEA(expr))) { tmpnode = makediadicnode(expr, eanode, ECOMMA); tmpnode->rtype = tmpnode->data.diadic.right->rtype; tmpnode = makemonadicnode(tmpnode, EINDIRECT); tmpnode->rtype = expr->rtype; return tmpnode; } CError_Error(190); return expr; } break; case ECOND: if ( copts.cplusplus && is_typesame(expr->data.cond.expr1->rtype, expr->data.cond.expr2->rtype) && (expr->data.cond.expr1->rtype->type != TYPEPOINTER || (UInt32) (expr->data.cond.expr1->flags & ENODE_FLAG_QUALS) == (expr->data.cond.expr2->flags & ENODE_FLAG_QUALS)) ) { expr->data.cond.expr1 = CExpr_LValue(expr->data.cond.expr1, flag1, flag2); expr->data.cond.expr2 = CExpr_LValue(expr->data.cond.expr2, flag1, flag2); if (ENODE_IS(expr->data.cond.expr1, EINDIRECT) && ENODE_IS(expr->data.cond.expr2, EINDIRECT)) { if (!ENODE_IS(expr->data.cond.expr1->data.monadic, EBITFIELD) && !ENODE_IS(expr->data.cond.expr2->data.monadic, EBITFIELD)) { expr->data.cond.expr1 = getnodeaddress(expr->data.cond.expr1, 0); expr->data.cond.expr2 = getnodeaddress(expr->data.cond.expr2, 0); expr->rtype = expr->data.cond.expr1->rtype; tmpnode = makemonadicnode(expr, EINDIRECT); tmpnode->rtype = TYPE_POINTER(tmpnode->rtype)->target; return tmpnode; } } } break; } if (flag2) CError_Error(142); return expr; } ENode *CExpr_MakeObjRefNode(Object *obj, Boolean flag) { ENode *expr; if (obj->sclass == OBJECT_SCLASS_104) { CError_Error(141); return intconstnode((Type *) &void_ptr, 0); } expr = lalloc(sizeof(ENode)); memclrw(expr, sizeof(ENode)); expr->type = EOBJREF; expr->data.objref = obj; expr->rtype = CDecl_NewPointerType(obj->type); if (!IS_TYPE_FUNC(obj->type)) expr->flags = obj->qual & ENODE_FLAG_QUALS; if (flag) obj->flags |= OBJECT_FLAGS_UNUSED; return expr; } ENode *create_objectrefnode(Object *obj) { if (name_obj_check && !name_obj_check(NULL, obj)) return intconstnode((Type *) &void_ptr, 0); return CExpr_MakeObjRefNode(obj, 1); } ENode *create_objectnode2(Object *obj) { ENode *expr; if (name_obj_check && !name_obj_check(NULL, obj)) return nullnode(); expr = makemonadicnode(CExpr_MakeObjRefNode(obj, 1), EINDIRECT); expr->rtype = TYPE_POINTER(expr->rtype)->target; return expr; } ENode *create_objectnode(Object *obj) { return checkreference(create_objectnode2(obj)); } static ENode *CExpr_ExpandArg(ENode *expr, Type *type) { if (ENODE_IS(expr, ETYPCON) && IS_TYPE_FLOAT(type)) { expr->rtype = type; return expr; } else { return promote(expr, type); } } ENode *CExpr_IsTempConstruction(ENode *expr, Type *type, ENode **resultexpr) { ENodeList *args; ENode *funccall; ENode *funcref; if (!ENODE_IS(expr, EINDIRECT) || expr->rtype != type || !ENODE_IS((funccall = expr->data.monadic), EFUNCCALL) || !(args = funccall->data.funccall.args)) return NULL; if (!ENODE_IS((funcref = funccall->data.funccall.funcref), EOBJREF) || !CClass_IsConstructor(funcref->data.objref)) { if (expr->data.monadic->data.funccall.functype->functype != type) return NULL; if (CABI_GetStructResultArgumentIndex() == 1) { args = args->next; #line 1277 CError_ASSERT(args); } } if (resultexpr) *resultexpr = args->node; return expr->data.monadic; } ENode *CExpr_AdjustFunctionCall(ENode *expr) { ENodeList *list; switch (expr->data.funccall.functype->functype->type) { case TYPECLASS: CDecl_CompleteType(expr->data.funccall.functype->functype); case TYPESTRUCT: if (!expr->data.funccall.functype->functype->size) CError_Error(136, expr->data.funccall.functype->functype, 0); } if (CMach_GetFunctionResultClass(expr->data.funccall.functype)) { list = lalloc(sizeof(ENodeList)); if (IS_TYPE_CLASS(expr->data.funccall.functype->functype)) { CDecl_CompleteType(expr->data.funccall.functype->functype); if (CClass_Destructor(TYPE_CLASS(expr->data.funccall.functype->functype))) list->node = create_temp_node2(expr->rtype); else list->node = create_temp_node(expr->rtype); } else { list->node = create_temp_node(expr->rtype); } list->next = expr->data.funccall.args; expr->data.funccall.args = list; if (expr->data.funccall.funcref->flags & ENODE_FLAG_10) expr = CSOM_EnvCheck(expr, list); expr = makemonadicnode(expr, EINDIRECT); expr->data.monadic->rtype = CDecl_NewPointerType(expr->rtype); return expr; } if (expr->data.funccall.funcref->flags & ENODE_FLAG_10) expr = CSOM_EnvCheck(expr, NULL); return expr; } ENode *funccallexpr(Object *func, ENode *arg1, ENode *arg2, ENode *arg3, ENode *arg4) { ENode *expr; TypeFunc *tfunc; ENodeList *list; tfunc = TYPE_FUNC(func->type); #line 1411 CError_ASSERT(IS_TYPE_FUNC(tfunc)); expr = lalloc(sizeof(ENode)); expr->type = EFUNCCALL; expr->cost = 4; expr->rtype = tfunc->functype; expr->flags = tfunc->qual & ENODE_FLAG_QUALS; expr->data.funccall.funcref = create_objectrefnode(func); expr->data.funccall.functype = tfunc; if (arg1) { list = lalloc(sizeof(ENodeList)); expr->data.funccall.args = list; list->node = arg1; if (arg2) { list->next = lalloc(sizeof(ENodeList)); list = list->next; list->node = arg2; if (arg3) { list->next = lalloc(sizeof(ENodeList)); list = list->next; list->node = arg3; if (arg4) { list->next = lalloc(sizeof(ENodeList)); list = list->next; list->node = arg4; } } } list->next = NULL; } else { expr->data.funccall.args = NULL; } return CExpr_AdjustFunctionCall(expr); } ENode *CExpr_FuncCallSix(Object *func, ENode *arg1, ENode *arg2, ENode *arg3, ENode *arg4, ENode *arg5, ENode *arg6) { ENode *expr; TypeFunc *tfunc; ENodeList *list; tfunc = TYPE_FUNC(func->type); #line 1460 CError_ASSERT(IS_TYPE_FUNC(tfunc)); expr = lalloc(sizeof(ENode)); expr->type = EFUNCCALL; expr->cost = 4; expr->rtype = tfunc->functype; expr->flags = tfunc->qual & ENODE_FLAG_QUALS; expr->data.funccall.funcref = create_objectrefnode(func); expr->data.funccall.functype = tfunc; list = lalloc(sizeof(ENodeList)); expr->data.funccall.args = list; list->node = arg1; list->next = lalloc(sizeof(ENodeList)); list = list->next; list->node = arg2; list->next = lalloc(sizeof(ENodeList)); list = list->next; list->node = arg3; list->next = lalloc(sizeof(ENodeList)); list = list->next; list->node = arg4; list->next = lalloc(sizeof(ENodeList)); list = list->next; list->node = arg5; if (arg6) { list->next = lalloc(sizeof(ENodeList)); list = list->next; list->node = arg6; } list->next = NULL; return CExpr_AdjustFunctionCall(expr); } static void CExpr_CalcStdAssign(short checkresult, Match5 *match, Type *t1, UInt32 q1, Type *t2, UInt32 q2, Boolean flag) { memclrw(match, sizeof(Match5)); switch (checkresult) { case CheckResult1: match->x0++; break; case CheckResult2: match->x2++; break; case CheckResult3: match->x4++; match->x6 += assign_value; break; default: #line 1504 CError_FATAL(); } if (flag || (IS_TYPE_POINTER_ONLY(t2) && (IS_TYPE_POINTER_ONLY(t1) || IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(t2))) != 0)) { if ((q2 & Q_CONST) == (q1 & Q_CONST)) match->x8++; if ((q2 & Q_VOLATILE) == (q1 & Q_VOLATILE)) match->x8++; } } void CExpr_MatchCV(Type *t1, UInt32 q1, Type *t2, UInt32 q2, Match13 *match) { Boolean r8; if (IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(t2))) { t2 = TYPE_POINTER(t2)->target; r8 = 1; } else { r8 = 0; } while (IS_TYPE_POINTER_ONLY(t2) && IS_TYPE_POINTER_ONLY(t1)) { if (r8) { if ((TYPE_POINTER(t1)->qual & Q_CONST) != (TYPE_POINTER(t2)->qual & Q_CONST)) match->xC--; if ((TYPE_POINTER(t1)->qual & Q_VOLATILE) != (TYPE_POINTER(t2)->qual & Q_VOLATILE)) match->xC--; } t2 = TYPE_POINTER(t2)->target; t1 = TYPE_POINTER(t1)->target; r8 = 1; } if ((q1 & Q_CONST) != (q2 & Q_CONST)) match->xC--; if ((q1 & Q_VOLATILE) != (q2 & Q_VOLATILE)) match->xC--; } Boolean CExpr_MatchAssign(Type *type, UInt32 qual, ENode *expr, Match13 *match) { switch (assign_check(expr, type, qual, 0, 0, 1)) { case CheckResult0: return 0; case CheckResult1: match->x4++; break; case CheckResult2: match->x6++; break; case CheckResult3: match->x8++; match->xA += assign_value; break; case CheckResult4: match->xE++; match->match5.x0 += user_std_match.x0; match->match5.x2 += user_std_match.x2; match->match5.x4 += user_std_match.x4; match->match5.x6 += user_std_match.x6; match->match5.x8 += user_std_match.x8; break; default: #line 1585 CError_FATAL(); } if (IS_TYPE_POINTER_ONLY(type)) CExpr_MatchCV(expr->rtype, expr->flags & ENODE_FLAG_QUALS, type, qual, match); return 1; } static short CExpr_StdMatchCompare(Match5 *a, Match5 *b, Boolean flag) { if (a->x0 > b->x0) return 1; if (a->x0 == b->x0) { if (a->x2 > b->x2) return 1; if (a->x2 == b->x2) { if (a->x4 > b->x4) return 1; if (a->x4 == b->x4) { if (a->x6 > b->x6) return 1; if (a->x6 == b->x6) { if (!flag) return 0; if (a->x8 > b->x8) return 1; if (a->x8 == b->x8) return 0; } } } } return -1; } static short CExpr2_MemberPointerConversion(Type *type, ENode *expr, Boolean flag1) { // returns CheckResult } ENode *CExpr_ClassPointerCast(BClassList *cls, ENode *origexpr, Boolean nullcheckflag) { ENode *expr; ClassList *base; Boolean do_nullcheck; TypeClass *tclass; SInt32 offset; ENode *tmp; expr = origexpr; tclass = TYPE_CLASS(cls->type); do_nullcheck = 0; #line 1691 CError_ASSERT(cls); if (!IS_TYPE_POINTER_ONLY(origexpr->rtype)) { CError_Error(CErrorStr141); return origexpr; } cls = cls->next; while (cls) { for (base = tclass->bases; base; base = base->next) { if (base->base == TYPE_CLASS(cls->type)) break; } if (!base) { CError_Error(CErrorStr221); while (cls->next) cls = cls->next; tmp = nullnode(); tmp->rtype = CDecl_NewPointerType(cls->type); return tmp; } if (base->is_virtual) { if (!base->base->sominfo) { do_nullcheck = 1; if ((offset = base->offset) && !canadd(expr, offset)) { expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), offset), EADD); optimizecomm(expr); } expr->rtype = CDecl_NewPointerType(CDecl_NewPointerType(TYPE(base->base))); expr = makemonadicnode(expr, EINDIRECT); } } else { if ((offset = base->offset)) { do_nullcheck = 1; if (!canadd(expr, offset)) { expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), offset), EADD); optimizecomm(expr); } } } switch (expr->type) { case EPOSTINC: case EPOSTDEC: case EPREINC: case EPREDEC: expr = makemonadicnode(expr, ETYPCON); } expr->rtype = CDecl_NewPointerType(TYPE(base->base)); tclass = TYPE_CLASS(cls->type); cls = cls->next; } if (nullcheckflag && do_nullcheck) expr = do_castnullcheck(expr, origexpr); return expr; } ENode *CExpr_GetClassAccessNode(BClassList *a, BClassList *b, ENode *expr, Object *obj, AccessType access, Boolean flag) { TypeClass *tclass; ENode *tmp; if (!expr) { if (!cscope_currentfunc || !cscope_currentclass || !cscope_is_member_func || !(expr = CClass_CreateThisSelfExpr())) { CError_Error(CErrorStr221); return NULL; } expr = makemonadicnode(expr, EINDIRECT); expr->rtype = TYPE(cscope_currentclass); } #line 1786 CError_ASSERT(a); #line 1787 CError_ASSERT(IS_TYPE_CLASS(expr->rtype)); tclass = TYPE_CLASS(expr->rtype); a = CScope_GetClassAccessPath(a, tclass); if (!a || a->type != TYPE(tclass)) { CError_Error(CErrorStr221); return NULL; } if (flag) CClass_CheckPathAccess(a, obj, access); if (!TYPE_CLASS(a->type)->sominfo) { if (b) a = CClass_AppendPath(a, b); if (!ENODE_IS(expr, EINDIRECT)) expr = CExpr_LValue(expr, 0, 0); if (ENODE_IS(expr, EINDIRECT)) { expr->data.monadic->flags = expr->flags; tmp = expr->data.monadic; switch (tmp->type) { case EPOSTINC: case EPOSTDEC: case EPREINC: case EPREDEC: tmp = makemonadicnode(tmp, ETYPCON); } expr = makemonadicnode(CExpr_ClassPointerCast(a, tmp, 0), EINDIRECT); expr->rtype = TYPE(tclass); } } return expr; } static short std_assign_check_overload(NameSpaceObjectList *list, TemplArg *templargs, Type *type, Boolean flag1) { } ENode *CExpr_ConvertToBool(ENode *expr, Boolean flag) { if (IS_TYPE_MEMBERPOINTER(expr->rtype)) expr = CExpr_ConvertToCondition(expr); switch (expr->rtype->type) { case TYPEINT: case TYPEFLOAT: case TYPEENUM: case TYPEPOINTER: if (IS_TYPE_ENUM(expr->rtype)) expr = forceintegral(expr); switch (expr->type) { case EINTCONST: CInt64_SetLong(&expr->data.intval, !CInt64_IsZero(&expr->data.intval)); break; case EFLOATCONST: CInt64_SetLong(&expr->data.intval, !CMach_FloatIsZero(expr->data.floatval)); expr->type = EINTCONST; break; default: expr = makemonadicnode(expr, ELOGNOT); expr->rtype = TYPE(&stbool); expr = makemonadicnode(expr, ELOGNOT); } break; default: CError_Error( flag ? CErrorStr247 : CErrorStr209, expr->rtype, expr->flags & ENODE_FLAG_QUALS, &stbool, 0); expr = nullnode(); } expr->rtype = TYPE(&stbool); return expr; } static short std_assign_check(ENode *expr, Type *type, Boolean flag1, Boolean flag2) { short result; if (copts.cplusplus) { illegalimplicitconversion = 0; if ((result = iscpp_typeequal(expr->rtype, type))) { assign_node = expr; if (result == -1) { assign_value = 1; return CheckResult3; } else { return CheckResult1; } } if (flag1 && illegalimplicitconversion) { CError_Error(CErrorStr209, expr->rtype, expr->flags & ENODE_FLAG_QUALS, type, 0); return CheckResult0; } } else { if (is_typeequal(expr->rtype, type)) { assign_node = expr; return CheckResult1; } } if (type == TYPE(&stbool)) { switch (expr->rtype->type) { case TYPEPOINTER: case TYPEMEMBERPOINTER: assign_value = 0; case TYPEINT: case TYPEFLOAT: case TYPEENUM: if (flag1) assign_node = CExpr_ConvertToBool(expr, 0); return CheckResult3; default: return CheckResult0; } } if (IS_TYPE_ENUM(expr->rtype) && (IS_TYPE_INT(type) || IS_TYPE_FLOAT(type))) { result = CheckResult3; if (IS_TYPE_INT(type)) { if (TYPE_ENUM(expr->rtype)->enumtype == type) { result = CheckResult2; } else if (TYPE_INTEGRAL(TYPE_ENUM(expr->rtype)->enumtype)->integral < IT_INT) { switch (TYPE_INTEGRAL(type)->integral) { case IT_INT: if (expr->rtype->size < stsignedint.size || TYPE_ENUM(expr->rtype)->enumtype == TYPE(&stsignedshort)) result = CheckResult2; break; case IT_UINT: if (expr->rtype->size >= stsignedint.size && TYPE_ENUM(expr->rtype)->enumtype != TYPE(&stsignedshort)) result = CheckResult2; break; } } } if (flag1) { expr->rtype = TYPE_ENUM(expr->rtype)->enumtype; assign_node = promote(expr, type); } return result; } if (IS_TYPE_INT(expr->rtype) && (IS_TYPE_INT(type) || IS_TYPE_FLOAT(type))) { result = CheckResult3; if (TYPE_INTEGRAL(expr->rtype)->integral <= IT_INT) { if (type == TYPE(&stsignedint) || type == TYPE(&stunsignedint)) { switch (TYPE_INTEGRAL(type)->integral) { case IT_INT: if (expr->rtype->size < stsignedint.size || type != TYPE(&stunsignedshort)) result = CheckResult2; break; case IT_UINT: if (expr->rtype->size == stsignedint.size && type == TYPE(&stunsignedshort)) result = CheckResult2; break; } } } if (flag1 && type != expr->rtype) assign_node = promote(expr, type); else assign_node = expr; return result; } if (IS_TYPE_FLOAT(expr->rtype) && (IS_TYPE_INT(type) || IS_TYPE_FLOAT(type))) { if (type == TYPE(&stdouble) && (expr->rtype == TYPE(&stfloat) || expr->rtype == TYPE(&stshortdouble))) result = CheckResult2; else result = CheckResult3; if (flag1 && (!IS_TYPE_FLOAT(type) || type->size != expr->rtype->size)) assign_node = promote(expr, type); else assign_node = expr; return result; } if (IS_TYPE_POINTER_ONLY(type)) { if (ENODE_IS(expr, EINTCONST) && CInt64_IsZero(&expr->data.intval) && (IS_TYPE_INT(expr->rtype) || (!copts.cplusplus && IS_TYPE_ENUM(expr->rtype)))) { if (flag1) expr->rtype = TYPE(&stunsignedlong); assign_node = expr; return CheckResult3; } if (ENODE_IS(expr, EOBJLIST)) { return std_assign_check_overload(expr->data.objlist.list, expr->data.objlist.templargs, type, flag1); } if (IS_TYPE_POINTER_ONLY(expr->rtype)) { if (ENODE_IS(expr, EOBJREF) && IS_TYPE_FUNC(expr->data.objref->type) && (TYPE_FUNC(expr->data.objref->type)->flags & FUNC_FLAGS_100000)) { NameSpaceObjectList list; list.next = NULL; list.object = OBJ_BASE(expr->data.objref); return std_assign_check_overload(&list, NULL, type, flag1); } if (copts.objective_c && CObjC_IsCompatibleType(expr->rtype, type)) { assign_value = 1; return CheckResult3; } if (IS_TYPE_CLASS(TYPE_POINTER(expr->rtype)->target) && IS_TYPE_CLASS(TYPE_POINTER(type)->target)) { short depth; Boolean isambig; BClassList *path; path = CClass_GetBasePath( TYPE_CLASS(TYPE_POINTER(expr->rtype)->target), TYPE_CLASS(TYPE_POINTER(type)->target), &depth, &isambig ); if (path) { assign_value = 1000 - depth; if (flag1) { if (isambig) CError_Error(CErrorStr188); if (flag2) CClass_CheckPathAccess(path, NULL, ACCESSPUBLIC); assign_node = CExpr_ClassPointerCast(path, expr, 1); } return CheckResult3; } else { if (flag1) { if (isambig) CError_Error(CErrorStr188); else CError_Error( CErrorStr244, expr->rtype, expr->flags & ENODE_FLAG_QUALS, type, 0); } return CheckResult0; } } } } if (IS_TYPE_MEMBERPOINTER(type) && !IS_TYPE_CLASS(expr->rtype)) { return CExpr2_MemberPointerConversion(type, expr, flag1); } if (IS_TYPE_CLASS(expr->rtype) && IS_TYPE_CLASS(type)) { short depth; Boolean isambig; BClassList *path; path = CClass_GetBasePath( TYPE_CLASS(expr->rtype), TYPE_CLASS(type), &depth, &isambig ); if (path) { assign_value = 1000 - depth; if (flag1) { if (isambig) CError_Error(CErrorStr188); CClass_CheckPathAccess(path, NULL, ACCESSPUBLIC); assign_node = getnodeaddress(expr, 0); assign_node = CExpr_ClassPointerCast(path, assign_node, 0); assign_node = makemonadicnode(assign_node, EINDIRECT); assign_node->rtype = type; } return CheckResult3; } } if (IS_TYPE_ENUM(type)) { switch (expr->rtype->type) { case TYPEINT: case TYPEFLOAT: case TYPEENUM: if (!copts.cplusplus) { if (flag1) { if (copts.pedantic) CError_Warning(CErrorStr217, expr->rtype, expr->flags & ENODE_FLAG_QUALS, type, 0); assign_node = do_typecast(expr, type, 0); assign_node->flags = expr->flags; } return CheckResult2; } else { if (flag1) CError_Error(CErrorStr217, expr->rtype, expr->flags & ENODE_FLAG_QUALS, type, 0); } } } return CodeGen_AssignCheck(expr, type, flag1, flag2); } static short is_compatible_conversion(Type *a, Type *b) { if (IS_TYPE_REFERENCE(a)) a = TYPE_POINTER(a)->target; if (IS_TYPE_REFERENCE(b)) b = TYPE_POINTER(b)->target; return iscpp_typeequal(b, a); } static void CExpr_ConIteratorInit(ConIterator *iter) { ClassList *base; ConIterator *subiter; ConIteratorList *list; for (base = iter->tclass->bases; base; base = base->next) { if (base->base->flags & CLASS_FLAGS_40) { subiter = galloc(sizeof(ConIterator)); memclrw(subiter, sizeof(ConIterator)); subiter->parent = iter; subiter->tclass = base->base; CExpr_ConIteratorInit(subiter); list = galloc(sizeof(ConIteratorList)); memclrw(list, sizeof(ConIteratorList)); list->iter = subiter; list->next = iter->children; iter->children = list; } } } void CExpr_ConversionIteratorInit(ConversionIterator *iter, TypeClass *tclass) { memclrw(iter, sizeof(ConversionIterator)); if (tclass->flags & CLASS_FLAGS_40) { iter->coniter = &iter->myconiter; iter->myconiter.tclass = tclass; CExpr_ConIteratorInit(&iter->myconiter); CScope_InitObjectIterator(&iter->objiter, tclass->nspace); } } static Boolean CExpr_ConversionIteratorIsHidden(ConIterator *iter, TypeFunc *tfunc) { CScopeObjectIterator objiter; ObjBase *obj; TypeFunc *objtfunc; while (iter) { CScope_InitObjectIterator(&objiter, iter->tclass->nspace); while (1) { if (!(obj = CScope_NextObjectIteratorObject(&objiter))) break; objtfunc = TYPE_FUNC(OBJECT(obj)->type); if ( IS_TYPE_FUNC(objtfunc) && (objtfunc->flags & FUNC_FLAGS_40) && is_compatible_conversion(tfunc->functype, objtfunc->functype) && (tfunc->args->qual & Q_CONST) == (objtfunc->args->qual & Q_CONST) && (tfunc->qual & Q_CONST) == (objtfunc->qual & Q_CONST) ) return 1; } iter = iter->parent; } return 0; } Object *CExpr_ConversionIteratorNext(ConversionIterator *iter) { ConIterator *ci; Object *obj; ci = iter->coniter; if (!ci) return NULL; restart: if ((obj = OBJECT(CScope_NextObjectIteratorObject(&iter->objiter)))) { if ( IS_TYPE_FUNC(obj->type) && (TYPE_FUNC(obj->type)->flags & FUNC_FLAGS_40) && !CExpr_ConversionIteratorIsHidden(ci->parent, TYPE_FUNC(obj->type)) ) { return obj; } goto restart; } do { if (ci->children) { iter->coniter = ci->children->iter; ci->children = ci->children->next; ci = iter->coniter; CScope_InitObjectIterator(&iter->objiter, ci->tclass->nspace); goto restart; } } while ((ci = ci->parent)); return NULL; } void user_assign_check() {} ENode *CExpr_ConvertToCondition(ENode *expr) { switch (expr->rtype->type) { case TYPEINT: case TYPEFLOAT: case TYPEPOINTER: return expr; case TYPEENUM: expr->rtype = TYPE_ENUM(expr->rtype)->enumtype; return expr; case TYPEMEMBERPOINTER: return memberpointercompare(ENOTEQU, expr, nullnode()); case TYPECLASS: return CExpr_Convert(expr, TYPE(&stbool), 0, 0, 1); default: CError_Error(376, expr->rtype, expr->flags & ENODE_FLAG_QUALS); return nullnode(); } } void CExpr_ConvertToIntegral() {} void CExpr_CheckArithmConversion() {} void get_address_of_temp_copy() {} short assign_check(ENode *expr, Type *type, UInt32 qual, Boolean flag1, Boolean flag2, Boolean flag3) { } void CExpr_MatchCompare() {} static void MatchOverloadFunc() {} void CExpr_GetFuncMatchArgs() {} static NameSpaceObjectList *CExpr_CopyNameSpaceObjectList(NameSpaceObjectList *list) { NameSpaceObjectList *first; NameSpaceObjectList *work; first = work = lalloc(sizeof(NameSpaceObjectList)); while (1) { work->object = list->object; list = list->next; if (!list) { work->next = NULL; break; } else { work->next = lalloc(sizeof(NameSpaceObjectList)); work = work->next; } } return first; } static void CExpr_MatchArgList() {} ENode *CExpr_GetDefaultArgument(ENode *funcexpr, FuncArg *arg) { ENode *tmp; if (CTemplTool_IsTemplateArgumentDependentExpression(arg->dexpr)) { #line 3264 CError_ASSERT(ENODE_IS(funcexpr, EOBJREF)); tmp = CTemplTool_DeduceDefaultArg( funcexpr->data.objref, CInline_CopyExpression(arg->dexpr, CopyMode0) ); return argumentpromotion(tmp, arg->type, arg->qual, 1); } return CInline_CopyExpression(arg->dexpr, CopyMode0); } static ENode *CExpr_GenericCall(ENode *funcexpr, ENodeList *argexprs, TypeFunc *tfunc, FuncArg *args) { ENodeList *list; ENode *callexpr; while (args) { if (args->dexpr) { if (argexprs) { list = argexprs; while (list->next) list = list->next; list->next = lalloc(sizeof(ENodeList)); list = list->next; } else { list = argexprs = lalloc(sizeof(ENodeList)); } list->next = NULL; list->node = CExpr_GetDefaultArgument(funcexpr, args); } args = args->next; } callexpr = lalloc(sizeof(ENode)); callexpr->type = EFUNCCALL; callexpr->cost = 4; callexpr->rtype = tfunc->functype; callexpr->flags = tfunc->qual & ENODE_FLAG_QUALS; callexpr->data.funccall.funcref = funcexpr; callexpr->data.funccall.funcref->rtype = CDecl_NewPointerType(TYPE(tfunc)); callexpr->data.funccall.args = argexprs; callexpr->data.funccall.functype = tfunc; funcexpr->data.objref->flags |= OBJECT_FLAGS_UNUSED; return CExpr_AdjustFunctionCall(callexpr); } static Boolean CExpr_IsObjrefPlusX(ENode *expr) { Type *type; if (ENODE_IS(expr, EOBJREF)) { type = expr->data.objref->type; while (IS_TYPE_ARRAY(type)) type = TYPE_POINTER(type)->target; return IS_TYPE_CLASS(type); } if (ENODE_IS2(expr, EADD, ESUB)) { if (CExpr_IsObjrefPlusX(expr->data.diadic.left)) return 1; if (CExpr_IsObjrefPlusX(expr->data.diadic.right)) return 1; } return 0; } static Boolean CExpr_IsStaticType(ENode *expr) { return ENODE_IS(expr, EINDIRECT) && CExpr_IsObjrefPlusX(expr->data.monadic); } ENode *CExpr_VarArgPromotion(ENode *expr, Boolean flag) { if (!copts.old_argmatch) expr = pointer_generation(expr); switch (expr->rtype->type) { case TYPEVOID: case TYPEFUNC: CError_Error(CErrorStr353); expr = nullnode(); break; case TYPEINT: case TYPEENUM: expr = integralpromote(expr); break; case TYPEFLOAT: if (TYPE_INTEGRAL(expr->rtype)->integral < IT_DOUBLE) expr = promote(expr, TYPE(&stdouble)); break; case TYPECLASS: expr = classargument(expr); break; } if (!flag && copts.warn_largeargs) { if ((IS_TYPE_INT(expr->rtype) && TYPE_INTEGRAL(expr->rtype)->integral >= IT_LONGLONG) || IS_TYPE_FLOAT(expr->rtype)) CError_Warning(CErrorStr316); } return expr; } void CExpr_GenericFuncCall() {} void CExpr_GenericPtmfCall() {} static void CExpr_ConvertEMember() {} void CExpr_MakeFunctionCall() {} static void accept_conversion_type() {} static void CExpr_OperatorConversion() {} static void wild_conversion_check() {} static void monadic_conversion_check() {} static void is_legal_type_combination() {} static void match_class_type_conversion() {} static void match_type_class_conversion() {} static void match_class_class_conversion() {} void CExpr_CheckOperatorConversion() {} void CExpr_CheckOperator() {} ENode *CExpr_ConstructObject(TypeClass *tclass, ENode *addr_expr, ENodeList *args, Boolean flag1, Boolean flag2, Boolean flag3, Boolean flag4, Boolean flag5) { ENode *expr; Object *ctor; #line 4595 CError_ASSERT(IS_TYPE_POINTER_ONLY(addr_expr->rtype)); addr_expr = makemonadicnode(addr_expr, EINDIRECT); addr_expr->rtype = TYPE(tclass); if (!flag3 && args && !args->next && args->node->rtype == TYPE(tclass) && !CClass_CopyConstructor(tclass)) { #line 4605 CError_ASSERT(IS_TYPE_CLASS(addr_expr->rtype)); expr = makediadicnode(addr_expr, args->node, EASS); if (!flag1) expr = getnodeaddress(expr, 0); return expr; } if ((ctor = CClass_Constructor(tclass))) { if (tclass->flags & CLASS_FLAGS_20) { ENodeList *list = lalloc(sizeof(ENodeList)); list->next = args; args = list; list->node = intconstnode(TYPE(&stsignedshort), flag2 != 0); } // TODO: 12CE80 call to genericfunccall } else { if (args) { if (!args->next && ENODE_IS(addr_expr, EINDIRECT)) { return makediadicnode( addr_expr, CExpr_AssignmentPromotion(args->node, TYPE(tclass), 0, 1), EASS); } CError_Error(174); } return addr_expr; } } static void CExpr_DeleteFuncCall() {} static void CExpr_CopyPlacementNewArg() {} static void CExpr_PlacementDeleteCall() {} static void scan_type_name() {} static void cv_qualifier_list() {} static void scan_new_declarator() {} static void scan_new_type_name() {} static void CExpr_NewAlloc() {} static void CExpr_NewExceptionSafeAlloc() {} static void CExpr_NewExceptionSafeInit() {} static void CExpr_NewArray() {} static void CExpr_NewSimpleClass() {} static void CExpr_NewClass() {} void scannew() {} static void CExpr_DeleteArray() {} void scandelete() {}