MWCC/compiler_and_linker/unsorted/CExpr2.c

1935 lines
59 KiB
C
Raw Normal View History

2022-11-07 03:06:21 +00:00
#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() {}