mirror of https://git.wuffs.org/MWCC
1935 lines
59 KiB
C
1935 lines
59 KiB
C
|
#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() {}
|