diff options
author | Ash Wolf <ninji@wuffs.org> | 2023-01-26 11:30:47 +0000 |
---|---|---|
committer | Ash Wolf <ninji@wuffs.org> | 2023-01-26 11:30:47 +0000 |
commit | 094b96ca1df4a035b5f93c351f773306c0241f3f (patch) | |
tree | 95ce05e3ebe816c7ee7996206bb37ea17d8ca33c /compiler_and_linker/unsorted/CExpr.c | |
parent | fc0c4c0df7b583b55a08317cf1ef6a71d27c0440 (diff) | |
download | MWCC-094b96ca1df4a035b5f93c351f773306c0241f3f.tar.gz MWCC-094b96ca1df4a035b5f93c351f773306c0241f3f.zip |
move lots of source files around to match their actual placement in the original treemain
Diffstat (limited to 'compiler_and_linker/unsorted/CExpr.c')
-rw-r--r-- | compiler_and_linker/unsorted/CExpr.c | 4971 |
1 files changed, 0 insertions, 4971 deletions
diff --git a/compiler_and_linker/unsorted/CExpr.c b/compiler_and_linker/unsorted/CExpr.c deleted file mode 100644 index 484f56d..0000000 --- a/compiler_and_linker/unsorted/CExpr.c +++ /dev/null @@ -1,4971 +0,0 @@ -#include "compiler/CExpr.h" -#include "compiler/CABI.h" -#include "compiler/CClass.h" -#include "compiler/CDecl.h" -#include "compiler/CError.h" -#include "compiler/CException.h" -#include "compiler/CInit.h" -#include "compiler/CInline.h" -#include "compiler/CIRTransform.h" -#include "compiler/CMachine.h" -#include "compiler/CMangler.h" -#include "compiler/CInt64.h" -#include "compiler/CObjC.h" -#include "compiler/CObjCModern.h" -#include "compiler/CParser.h" -#include "compiler/CPrep.h" -#include "compiler/CPrepTokenizer.h" -#include "compiler/CRTTI.h" -#include "compiler/CSOM.h" -#include "compiler/CTemplateNew.h" -#include "compiler/CTemplateTools.h" -#include "compiler/CodeGen.h" -#include "compiler/CompilerTools.h" -#include "compiler/PPCError.h" -#include "compiler/objects.h" -#include "compiler/scopes.h" -#include "compiler/templates.h" - -Boolean (*name_obj_check)(HashNameNode *, Object *); -Boolean disallowgreaterthan; - -// forward declarations -static ENode *makeaddnode(ENode *left, ENode *right); -static ENode *makesubnode(ENode *left, ENode *right); - -ENode *CExpr_RewriteConst(ENode *expr) { - Object *obj; - -restart: - if (ENODE_IS(expr, EINDIRECT) && ENODE_IS(expr->data.monadic, EOBJREF)) { - obj = expr->data.monadic->data.objref; - if (obj->datatype == DALIAS) { - CExpr_AliasTransform(expr->data.monadic); - goto restart; - } - - if ((obj->qual & Q_INLINE_DATA) && expr->rtype == obj->type) { - switch (expr->rtype->type) { - case TYPEINT: - case TYPEENUM: - expr->type = EINTCONST; - expr->data.intval = obj->u.data.u.intconst; - break; - case TYPEPOINTER: - expr->type = EINTCONST; - expr->data.intval = obj->u.data.u.intconst; - expr->rtype = TYPE(&stunsignedlong); - expr = makemonadicnode(expr, ETYPCON); - expr->rtype = obj->type; - break; - case TYPEFLOAT: - expr->type = EFLOATCONST; - if (obj->u.data.u.floatconst) - expr->data.floatval = *obj->u.data.u.floatconst; - else - expr->data.floatval = CMach_CalcFloatConvertFromInt(TYPE(&stsignedlong), cint64_zero); - break; - default: - CError_FATAL(105); - } - } - } - - return expr; -} - -void optimizecomm(ENode *expr) { - ENode *right; - ENode *left; - - if (ENODE_IS((right = expr->data.diadic.right), EINTCONST)) - return; - if (ENODE_IS((left = expr->data.diadic.left), EINTCONST)) { - swap: - expr->data.diadic.right = left; - expr->data.diadic.left = right; - return; - } - - if (ENODE_IS(left, EFLOATCONST)) - return; - if (ENODE_IS(right, EFLOATCONST)) - goto swap; - - if (expr->rtype->type > TYPEFLOAT) - return; - - if (left->cost > right->cost) - goto swap; -} - -static void checkadditive(ENode *expr) { - switch (expr->rtype->type) { - case TYPEINT: - if (expr->rtype == TYPE(&stbool)) - break; - case TYPEFLOAT: - return; - case TYPEENUM: - if (copts.cplusplus) - break; - return; - case TYPEPOINTER: - if (TPTR_TARGET(expr->rtype)->size == 0) - CDecl_CompleteType(TPTR_TARGET(expr->rtype)); - if (TPTR_TARGET(expr->rtype)->size == 0) - break; - return; - case TYPEARRAY: - if (ENODE_IS(expr, EOBJREF)) - return; - } - - CError_Error(CErrorStr376, expr->rtype, ENODE_QUALS(expr)); -} - -static void CExpr_CompareConvert(ENode **leftp, char *opname, ENode **rightp, Boolean flag) { - ENode *left; - ENode *right; - CInt64 val; - - left = *leftp; - right = *rightp; - - switch (left->rtype->type) { - case TYPEINT: - break; - case TYPEFLOAT: - if (left->rtype != right->rtype) - CExpr_ArithmeticConversion(leftp, rightp); - return; - case TYPEENUM: - left->rtype = TYPE_ENUM(left->rtype)->enumtype; - break; - default: - CError_Error(CErrorStr377, - left->rtype, ENODE_QUALS(left), - opname, - right->rtype, ENODE_QUALS(right)); - left = nullnode(); - } - - switch (right->rtype->type) { - case TYPEINT: - break; - case TYPEFLOAT: - CExpr_ArithmeticConversion(leftp, rightp); - return; - case TYPEENUM: - right->rtype = TYPE_ENUM(right->rtype)->enumtype; - break; - default: - CError_Error(CErrorStr377, - left->rtype, ENODE_QUALS(left), - opname, - right->rtype, ENODE_QUALS(right)); - right = nullnode(); - } - - if (left->rtype == right->rtype) { - *leftp = left; - *rightp = right; - return; - } - - if (left->rtype->size == right->rtype->size) { - if (is_unsigned(left->rtype) == is_unsigned(right->rtype)) { - left->rtype = right->rtype; - *leftp = left; - *rightp = right; - return; - } - } else { - if (ENODE_IS(right, EINTCONST) && left->rtype->size <= right->rtype->size && (is_unsigned(left->rtype) == is_unsigned(right->rtype) || is_unsigned(left->rtype))) { - val = CMach_CalcIntDiadic(left->rtype, right->data.intval, '+', cint64_zero); - val = CMach_CalcIntDiadic(right->rtype, val, '+', cint64_zero); - if (CInt64_Equal(val, right->data.intval)) { - right->rtype = left->rtype; - *leftp = left; - *rightp = right; - return; - } - } - - if (ENODE_IS(left, EINTCONST) && left->rtype->size >= right->rtype->size && (is_unsigned(left->rtype) == is_unsigned(right->rtype) || is_unsigned(right->rtype))) { - val = CMach_CalcIntDiadic(right->rtype, left->data.intval, '+', cint64_zero); - val = CMach_CalcIntDiadic(left->rtype, val, '+', cint64_zero); - if (CInt64_Equal(val, left->data.intval)) { - left->rtype = right->rtype; - *leftp = left; - *rightp = right; - return; - } - } - } - - *leftp = left; - *rightp = right; - CExpr_ArithmeticConversion(leftp, rightp); -} - -static ENode *CExpr_ConstResult(ENode *expr, SInt32 value) { - ENode *constnode; - - if (IS_TYPE_FLOAT(expr->rtype)) { - constnode = intconstnode(TYPE(&stsignedint), value); - constnode->type = EFLOATCONST; - constnode->data.floatval = CMach_CalcFloatConvertFromInt(TYPE(&stsignedint), constnode->data.intval); - constnode->rtype = expr->rtype; - } else { - constnode = intconstnode(expr->rtype, value); - } - - if (CInline_ExpressionHasSideEffect(expr)) - return makediadicnode(expr, constnode, ECOMMA); - else - return constnode; -} - -static ENode *makemultnode(ENode *left, ENode *right) { - CExpr_ArithmeticConversion(&left, &right); - if (iszero(left)) - return CExpr_ConstResult(right, 0); - if (iszero(right)) - return CExpr_ConstResult(left, 0); - - if (CExpr_IsOne(right)) - return left; - if (CExpr_IsOne(left)) - return right; - - if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { - left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, '*', right->data.intval); - return left; - } - if (ENODE_IS(left, EFLOATCONST) && ENODE_IS(right, EFLOATCONST)) { - left->data.floatval = CMach_CalcFloatDiadic(left->rtype, left->data.floatval, '*', right->data.floatval); - return left; - } - - left = makediadicnode(left, right, EMUL); - optimizecomm(left); - if (IS_TYPE_INT(left->rtype) && left->rtype->size > 2) { - left->cost++; - if (left->cost > 200) - left->cost = 200; - } - - if (IS_TYPE_FLOAT(left->rtype)) - left = CExpr_BinaryFloatExpression(left); - - return left; -} - -static ENode *makedivnode(ENode *left, ENode *right, Boolean no_warning) { - CExpr_ArithmeticConversion(&left, &right); - if (iszero(right) && IS_TYPE_INT(right->rtype)) { - if (!no_warning) - CError_Warning(CErrorStr139); - return right; - } - - if (CExpr_IsOne(right)) - return left; - - if (iszero(left) && IS_TYPE_INT(left->rtype)) - return CExpr_ConstResult(right, 0); - - if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { - left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, '/', right->data.intval); - return left; - } - if (ENODE_IS(left, EFLOATCONST) && ENODE_IS(right, EFLOATCONST)) { - left->data.floatval = CMach_CalcFloatDiadic(left->rtype, left->data.floatval, '/', right->data.floatval); - return left; - } - - left = makediadicnode(left, right, EDIV); - if (IS_TYPE_FLOAT(left->rtype)) - left = CExpr_BinaryFloatExpression(left); - - return left; -} - -static short canadd2(ENode *expr, CInt64 value) { - Float tmp; - - if (CInt64_IsZero(&value)) - return 1; - - switch (expr->type) { - case EINTCONST: - expr->data.intval = CMach_CalcIntDiadic(expr->rtype, expr->data.intval, '+', value); - return 1; - case EFLOATCONST: - tmp = CMach_CalcFloatConvertFromInt(TYPE(&stsignedlong), value); - expr->data.floatval = CMach_CalcFloatDiadic(expr->rtype, expr->data.floatval, '+', tmp); - return 1; - case EADD: - if (canadd2(expr->data.diadic.left, value)) - return 1; - if (canadd2(expr->data.diadic.right, value)) - return 1; - return 0; - case ESUB: - if (canadd2(expr->data.diadic.left, value)) - return 1; - if (canadd2(expr->data.diadic.right, CInt64_Neg(value))) - return 1; - return 0; - case ETYPCON: - if (IS_TYPE_POINTER_ONLY(expr->rtype) && ENODE_IS(expr->data.monadic, EINTCONST)) { - expr->data.monadic->data.intval = CMach_CalcIntDiadic(TYPE(&stunsignedlong), expr->data.monadic->data.intval, '+', value); - return 1; - } - return 0; - default: - return 0; - } -} - -short canadd(ENode *expr, SInt32 value) { - CInt64 value64; - CInt64_SetLong(&value64, value); - return canadd2(expr, value64); -} - -static ENode *addconst(ENode *expr, SInt32 value) { - ENode *right; - - if (canadd(expr, value)) - return expr; - - if (stsignedint.size < 4 && (value > 0x7FFF || value < -0x8000)) - right = intconstnode(TYPE(&stsignedlong), value); - else - right = intconstnode(TYPE(&stsignedint), value); - - CExpr_ArithmeticConversion(&expr, &right); - expr = makediadicnode(expr, right, EADD); - return expr; -} - -static ENode *integralpointerpromote(ENode *expr) { - Boolean uns; - Type *type; - - if (!IS_TYPE_INT(expr->rtype)) - expr = forceintegral(expr); - - if (expr->rtype->size != 4) { - type = TYPE(&stunsignedlong); - if (is_unsigned(type) != (uns = is_unsigned(expr->rtype))) { - if (uns) { - if (stunsignedlong.size == 4) { - type = TYPE(&stunsignedlong); - } else if (stunsignedint.size == 4) { - type = TYPE(&stunsignedint); - } else { - CError_FATAL(480); - } - } else { - if (stsignedlong.size == 4) { - type = TYPE(&stsignedlong); - } else if (stsignedint.size == 4) { - type = TYPE(&stsignedint); - } else { - CError_FATAL(486); - } - } - } - - if (ENODE_IS(expr, EINTCONST)) - expr->data.intval = CExpr_IntConstConvert(type, expr->rtype, expr->data.intval); - else - expr = makemonadicnode(expr, ETYPCON); - - expr->rtype = type; - } - - return expr; -} - -static ENode *padd(ENode *left, ENode *right) { - Type *innertype; - SInt32 innersize; - ENode *expr; - - right = integralpointerpromote(right); - innertype = TPTR_TARGET(left->rtype); - innersize = innertype->size; - if (innersize == 0) { - CDecl_CompleteType(innertype); - innersize = innertype->size; - if (innersize == 0) { - CError_Error(CErrorStr146); - return left; - } - } - - expr = makemultnode( - right, - intconstnode((innersize > 0x7FFF) ? TYPE(&stsignedlong) : TYPE(&stsignedint), innersize)); - - if (ENODE_IS(expr, EINTCONST) && canadd2(left, expr->data.intval)) - return left; - - if (ENODE_IS(left, EADD) && ENODE_IS(left->data.diadic.right, EINTCONST)) { - left->data.diadic.left = makediadicnode(left->data.diadic.left, expr, EADD); - return left; - } - - expr = makediadicnode(left, expr, EADD); - expr->rtype = left->rtype; - expr->flags = left->flags; - return expr; -} - -static ENode *psub(ENode *left, ENode *right) { - Type *innertype; - SInt32 innersize; - ENode *expr; - - if (IS_TYPE_POINTER(right->rtype)) { - innersize = TPTR_TARGET(left->rtype)->size; - if (innersize == 0) { - CDecl_CompleteType(TPTR_TARGET(left->rtype)); - innersize = TPTR_TARGET(left->rtype)->size; - if (innersize == 0) { - CError_Error(CErrorStr146); - return left; - } - } - - if (!is_typeequal(left->rtype, right->rtype)) { - CError_Error(CErrorStr245, left->rtype, ENODE_QUALS(left), right->rtype, ENODE_QUALS(right)); - return left; - } - - if (ENODE_IS(left, ETYPCON) && ENODE_IS(left->data.monadic, EINTCONST) && ENODE_IS(right, ETYPCON) && ENODE_IS(right->data.monadic, EINTCONST)) { - left->data.monadic->rtype = right->data.monadic->rtype = CABI_GetPtrDiffTType(); - expr = makesubnode(left->data.monadic, right->data.monadic); - if (innersize > 1) - expr = makedivnode(expr, intconstnode(CABI_GetPtrDiffTType(), innersize), 11); - return expr; - } - - expr = makediadicnode(left, right, ESUB); - expr->rtype = CABI_GetPtrDiffTType(); - if (innersize > 1) - expr = makediadicnode(expr, intconstnode(CABI_GetPtrDiffTType(), innersize), EDIV); - return expr; - } - - right = integralpointerpromote(right); - innertype = TPTR_TARGET(left->rtype); - innersize = innertype->size; - if (innersize == 0) { - CDecl_CompleteType(innertype); - innersize = innertype->size; - if (innersize == 0) { - CError_Error(CErrorStr146); - return left; - } - } - - expr = makemultnode(right, intconstnode(CABI_GetPtrDiffTType(), innersize)); - if (ENODE_IS(expr, EINTCONST) && canadd2(left, CInt64_Neg(expr->data.intval))) - return left; - - expr = makediadicnode(left, expr, ESUB); - expr->rtype = left->rtype; - expr->flags = left->flags; - return expr; -} - -static ENode *makeaddnode(ENode *left, ENode *right) { - if (IS_TYPE_POINTER(left->rtype)) - return padd(left, right); - if (IS_TYPE_POINTER(right->rtype)) - return padd(right, left); - - CExpr_ArithmeticConversion(&left, &right); - if (iszero(right)) - return left; - if (iszero(left)) - return right; - - if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { - left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, '+', right->data.intval); - return left; - } - if (ENODE_IS(left, EFLOATCONST) && ENODE_IS(right, EFLOATCONST)) { - left->data.floatval = CMach_CalcFloatDiadic(left->rtype, left->data.floatval, '+', right->data.floatval); - return left; - } - - if (ENODE_IS(left, EINTCONST) && canadd2(right, left->data.intval)) - return right; - if (ENODE_IS(right, EINTCONST) && canadd2(left, right->data.intval)) - return left; - - left = makediadicnode(left, right, EADD); - optimizecomm(left); - if (IS_TYPE_FLOAT(left->rtype)) - left = CExpr_BinaryFloatExpression(left); - return left; -} - -static ENode *makesubnode(ENode *left, ENode *right) { - if (ENODE_IS(right, EINTCONST) && !is_unsigned(right->rtype) && !IS_TYPE_FLOAT(left->rtype)) { - right->data.intval = CInt64_Neg(right->data.intval); - return makeaddnode(left, right); - } - - if (IS_TYPE_POINTER(left->rtype)) - return psub(left, right); - - CExpr_ArithmeticConversion(&left, &right); - if (iszero(right)) - return left; - if (iszero(left)) { - if (ENODE_IS(right, EINTCONST)) { - right->data.intval = CInt64_Neg(right->data.intval); - return right; - } - if (ENODE_IS(right, EFLOATCONST)) { - right->data.floatval = CMach_CalcFloatMonadic(right->rtype, '-', right->data.floatval); - return right; - } - return CExpr_UnaryFloatExpression(makemonadicnode(right, EMONMIN)); - } - - if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { - left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, '-', right->data.intval); - return left; - } - if (ENODE_IS(left, EFLOATCONST) && ENODE_IS(right, EFLOATCONST)) { - left->data.floatval = CMach_CalcFloatDiadic(left->rtype, left->data.floatval, '-', right->data.floatval); - return left; - } - - if (ENODE_IS(right, EINTCONST) && canadd2(left, CInt64_Neg(right->data.intval))) - return left; - - left = makediadicnode(left, right, ESUB); - if (IS_TYPE_FLOAT(left->rtype)) - left = CExpr_BinaryFloatExpression(left); - return left; -} - -ENode *checkreference(ENode *expr) { - if (!IS_TYPE_REFERENCE(expr->rtype)) - return expr; - - expr = makemonadicnode(expr, EINDIRECT); - expr->rtype = TPTR_TARGET(expr->rtype); - return expr; -} - -static ENode *pointer_generation2(ENode *expr) { - switch (expr->type) { - case EINDIRECT: - switch (expr->rtype->type) { - case TYPEARRAY: - switch (expr->data.monadic->type) { - case EPOSTINC: - case EPOSTDEC: - case EPREINC: - case EPREDEC: - expr->type = ETYPCON; - expr->rtype = CDecl_NewPointerType(TPTR_TARGET(expr->rtype)); - return expr; - default: - expr->data.monadic->rtype = CDecl_NewPointerType(TPTR_TARGET(expr->rtype)); - expr->data.monadic->flags = expr->flags; - return expr->data.monadic; - } - case TYPEFUNC: - expr = expr->data.monadic; - if (ENODE_IS(expr, EOBJREF) && expr->data.objref->datatype == DINLINEFUNC) - CError_Error(CErrorStr175); - return expr; - } - } - return expr; -} - -ENode *pointer_generation(ENode *expr) { - return CExpr_RewriteConst(pointer_generation2(expr)); -} - -ENode *CExpr_PointerGeneration(ENode *expr) { - switch (expr->type) { - case EINDIRECT: - switch (expr->rtype->type) { - case TYPEARRAY: - expr->data.monadic->rtype = CDecl_NewPointerType(TPTR_TARGET(expr->rtype)); - return expr->data.monadic; - case TYPEFUNC: - return expr->data.monadic; - } - } - return expr; -} - -static void CExpr_ConstPointerCheck(ENode *expr, Type *type, short qual) { - Type *exprtype; - Type *b; - Type *a; - short exprqual; - - exprtype = expr->rtype; - if (IS_TYPE_POINTER_ONLY(type) && IS_TYPE_POINTER_ONLY(exprtype)) { - exprqual = expr->flags; - - if (TPTR_TARGET(type) == &stvoid) { - exprqual = CParser_GetCVTypeQualifiers(TPTR_TARGET(exprtype), exprqual); - } else { - a = TPTR_TARGET(type); - b = TPTR_TARGET(exprtype); - while (IS_TYPE_POINTER_ONLY(a) && IS_TYPE_POINTER_ONLY(b)) { - if (CParser_IsMoreCVQualified(TPTR_QUAL(b), TPTR_QUAL(a))) { - CError_Warning(CErrorStr220, expr->rtype, ENODE_QUALS(expr), type, qual); - return; - } - a = TPTR_TARGET(a); - b = TPTR_TARGET(b); - } - } - - if (CParser_IsMoreCVQualified(exprqual, qual)) { - CError_Warning(CErrorStr220, expr->rtype, ENODE_QUALS(expr), type, (UInt32) qual); - } - } -} - -ENode *oldassignmentpromotion(ENode *expr, Type *type, short qual, Boolean flag) { - Boolean is_ref; - UInt32 ref_qual; - short orig_qual; - - is_ref = 0; - if (!IS_TYPE_MEMBERPOINTER(type)) { - if (IS_TYPE_REFERENCE(type)) { - if (ENODE_IS(expr, ECOND)) - expr = CExpr_LValue(expr, 0, 0); - expr = pointer_generation2(expr); - ref_qual = CParser_GetCVTypeQualifiers(expr->rtype, expr->flags); - is_ref = 1; - } else { - expr = pointer_generation(expr); - } - } - - if (ENODE_IS(expr, EMEMBER)) - expr = getpointertomemberfunc(expr, type, 1); - - if (!is_ref) - CExpr_ConstPointerCheck(expr, type, qual); - else - CExpr_ConstPointerCheck(expr, TPTR_TARGET(type), qual); - - if (!(assign_check(expr, type, orig_qual = qual, 1, 0, flag))) - return expr; - - if (is_ref) { - if (temp_reference_init) { - switch (TPTR_TARGET(type)->type) { - case TYPEPOINTER: - qual = TPTR_QUAL(TPTR_TARGET(type)); - } - if (!(qual & Q_CONST)) - CError_Warning(CErrorStr228); - } else { - if (ref_qual && ref_qual > CParser_GetCVTypeQualifiers(TPTR_TARGET(type), orig_qual)) - CError_Warning(CErrorStr259); - } - } - - return assign_node; -} - -ENode *argumentpromotion(ENode *expr, Type *type, short qual, Boolean flag) { - ENode *tmp; - ENodeList *list; - - if (IS_TYPE_CLASS(type) && CClass_ReferenceArgument(TYPE_CLASS(type))) { - if ((tmp = CExpr_IsTempConstruction(expr, type, NULL))) - return tmp; - - list = lalloc(sizeof(ENodeList)); - list->next = NULL; - list->node = expr; - tmp = CExpr_ConstructObject( - TYPE_CLASS(type), - create_temp_node(type), - list, 1, 1, 1, 1, 0); - return getnodeaddress(tmp, 0); - } - - return CExpr_AssignmentPromotion(expr, type, qual, flag); -} - -ENode *classargument(ENode *expr) { - ENodeList *list; - - if (CClass_CopyConstructor(TYPE_CLASS(expr->rtype))) { - list = lalloc(sizeof(ENodeList)); - list->next = NULL; - list->node = expr; - return CExpr_ConstructObject( - TYPE_CLASS(expr->rtype), - create_temp_node(expr->rtype), - list, 1, 1, 1, 1, 0); - } - - return expr; -} - -ENodeList *CExpr_ScanExpressionList(Boolean is_parens) { - ENodeList *list; - ENodeList *current; - - if (is_parens && tk == ')') - return NULL; - - list = current = lalloc(sizeof(ENodeList)); - - while (1) { - current->next = NULL; - current->node = assignment_expression(); - if (copts.old_argmatch && !ENODE_IS(current->node, EMEMBER)) - current->node = pointer_generation(current->node); - - if (is_parens) { - if (tk == ')') - break; - } else { - if (tk == ']') - break; - } - - if (tk != ',') { - CError_ErrorSkip(CErrorStr116); - break; - } - - tk = lex(); - current->next = lalloc(sizeof(ENodeList)); - current = current->next; - } - - return list; -} - -static ENode *skipcommaexpr(ENode *expr) { - while (ENODE_IS(expr, ECOMMA)) - expr = expr->data.diadic.right; - return expr; -} - -ENode *CExpr_DoExplicitConversion(Type *type, UInt32 qual, ENodeList *list) { - Object *obj; - ENode *tmp; - - if (!IS_TYPE_CLASS(type)) { - if (!list) - return do_typecast(nullnode(), type, qual); - if (list->next) - CError_Error(CErrorStr356); - return do_typecast(pointer_generation(list->node), type, qual); - } - - CDecl_CompleteType(type); - if (!(TYPE_CLASS(type)->flags & CLASS_COMPLETED)) - CError_Error(CErrorStr136, type, 0); - - CanCreateObject(type); - if (!list && CClass_IsPODClass(TYPE_CLASS(type))) { - obj = CParser_NewGlobalDataObject(NULL); - obj->name = CParser_GetUniqueName(); - obj->nspace = cscope_root; - obj->type = type; - obj->qual = qual; - obj->sclass = TK_STATIC; - CInit_DeclareData(obj, NULL, NULL, type->size); - - tmp = makemonadicnode(create_temp_node(type), EINDIRECT); - tmp->rtype = type; - tmp->flags = qual & ENODE_FLAG_QUALS; - return makediadicnode(tmp, create_objectnode(obj), EASS); - } - - return CExpr_ConstructObject(TYPE_CLASS(type), create_temp_node(type), list, 1, 1, 1, 1, 1); -} - -static ENode *CExpr_TemplArgDepCast(Type *type, UInt32 qual, ENodeList *args) { - ENode *expr = CExpr_NewTemplDepENode(TDE_CAST); - expr->data.templdep.u.cast.args = args; - expr->data.templdep.u.cast.type = type; - expr->data.templdep.u.cast.qual = qual; - return expr; -} - -static ENode *CExpr_ParseExplicitConversion(Type *type, UInt32 qual) { - ENodeList *args; - ENodeList *scan; - - if (IS_TEMPL_CLASS(type) && !CParser_CheckTemplateClassUsage(TEMPL_CLASS(type), 1)) - type = TYPE(&stsignedint); - - if (tk == '(') - tk = lex(); - else - CError_Error(CErrorStr114); - - args = CExpr_ScanExpressionList(1); - if (tk != ')') { - CError_Error(CErrorStr115); - return nullnode(); - } - - tk = lex(); - if (CTemplTool_IsTemplateArgumentDependentType(type)) - return CExpr_TemplArgDepCast(type, qual, args); - - for (scan = args; scan; scan = scan->next) { - if (CTemplTool_IsTemplateArgumentDependentExpression(scan->node)) - return CExpr_TemplArgDepCast(type, qual, args); - } - - return CExpr_DoExplicitConversion(type, qual, args); -} - -static ENode *CExpr_MemberVarAccess(BClassList *path, ObjMemberVar *var, ENode *expr) { - ENode *accessnode; - BClassList *varpath; - - CError_ASSERT(1152, path); - - if (TYPE_CLASS(path->type)->sominfo) - return CSOM_MemberVarAccess(path, var, expr); - - varpath = NULL; - if (var->has_path) - varpath = OBJ_MEMBER_VAR_PATH(var)->path; - accessnode = CExpr_GetClassAccessNode(path, varpath, expr, NULL, var->access, 1); - if (!accessnode) - return nullnode(); - - return CClass_AccessMember(accessnode, var->type, var->qual, var->offset); -} - -static Boolean CExpr_IsTemplateFunc(Object *obj) { - return IS_TEMPL_FUNC(obj->type); -} - -static ENode *CExpr_ExplicitTemplateArgCheck(NameResult *pr) { - NameSpaceObjectList *list; - NameSpaceObjectList *newhead; - NameSpaceObjectList *newlist; - ENode *expr; - - if (pr->obj_10) { - if (pr->obj_10->otype != OT_OBJECT || !CExpr_IsTemplateFunc(OBJECT(pr->obj_10))) - return NULL; - - list = lalloc(sizeof(NameSpaceObjectList)); - memclrw(list, sizeof(NameSpaceObjectList)); - list->object = pr->obj_10; - } else if (pr->nsol_14) { - for (list = pr->nsol_14; list; list = list->next) { - if (list->object->otype == OT_OBJECT && CExpr_IsTemplateFunc(OBJECT(list->object))) { - newhead = newlist = galloc(sizeof(NameSpaceObjectList)); - *newlist = *list; - newlist->next = NULL; - while ((list = list->next)) { - if (list->object->otype == OT_OBJECT && CExpr_IsTemplateFunc(OBJECT(list->object))) { - newlist->next = galloc(sizeof(NameSpaceObjectList)); - newlist = newlist->next; - *newlist = *list; - newlist->next = NULL; - } - } - list = newhead; - break; - } - } - if (!list) - return NULL; - } else { - return NULL; - } - - expr = CExpr_NewENode(EOBJLIST); - expr->rtype = OBJECT(list->object)->type; - expr->data.objlist.list = list; - expr->data.objlist.templargs = CTempl_ParseUncheckTemplArgs(NULL, 0); - - tk = lex(); - return expr; -} - -ENode *CExpr_MakeNameLookupResultExpr(NameResult *pr) { - ENode *expr; - - if (pr->obj_10) { - switch (pr->obj_10->otype) { - case OT_OBJECT: - CClass_CheckObjectAccess(pr->bcl_18, OBJECT(pr->obj_10)); - return create_objectnode(OBJECT(pr->obj_10)); - case OT_ENUMCONST: - CClass_CheckEnumAccess(pr->bcl_18, OBJ_ENUM_CONST(pr->obj_10)); - expr = lalloc(sizeof(ENode)); - expr->type = EINTCONST; - expr->cost = 0; - expr->flags = 0; - expr->rtype = OBJ_ENUM_CONST(pr->obj_10)->type; - expr->data.intval = OBJ_ENUM_CONST(pr->obj_10)->val; - return expr; - case OT_MEMBERVAR: - CError_Error(CErrorStr221); - return nullnode(); - default: - CError_FATAL(1268); - } - } - - if (pr->nsol_14) { - expr = CExpr_NewENode(EOBJLIST); - expr->rtype = OBJECT(pr->nsol_14->object)->type; - expr->data.objlist.list = pr->nsol_14; - return expr; - } - - CError_FATAL(1278); - return NULL; -} - -static Type *CExpr_NewPTMType(EMemberInfo *member, Object *obj) { - TypeMemberPointer *ptm; - TypeMemberFunc *tmethod; - BClassList *path; - - ptm = galloc(sizeof(TypeMemberPointer)); - memclrw(ptm, sizeof(TypeMemberPointer)); - ptm->type = TYPEMEMBERPOINTER; - - if (member->list->object->otype == OT_MEMBERVAR) { - path = member->path; - while (path->next) - path = path->next; - ptm->size = 4; - ptm->ty2 = path->type; - ptm->ty1 = OBJ_MEMBER_VAR(member->list->object)->type; - } else { - if (!obj) { - CError_ASSERT(1306, member->list->object->otype == OT_OBJECT); - obj = OBJECT(member->list->object); - CError_ASSERT(1308, IS_TYPE_FUNC(obj->type)); - } - - tmethod = galloc(sizeof(TypeMemberFunc)); - memclrw(tmethod, sizeof(TypeMemberFunc)); - *tmethod = *TYPE_METHOD(obj->type); - - CError_ASSERT(1312, tmethod->args); - - tmethod->args = tmethod->args->next; - CDecl_MakePTMFuncType(TYPE_FUNC(tmethod)); - tmethod->flags &= ~FUNC_DEFINED; - - ptm->size = 12; - ptm->ty2 = TYPE(tmethod->theclass); - ptm->ty1 = TYPE(tmethod); - } - - return TYPE(ptm); -} - -static ENode *CExpr_ParseNameResultExpr(NameResult *pr, ENode *expr, Boolean flag1, Boolean flag2) { - ENode *result; - ENode *ta_expr; - ObjEnumConst *oec; - TemplateAction *act; - EMemberInfo *member; - NameSpaceObjectList *list; - Object *obj; - TypeFunc *tfunc; - SInt32 val; - - if (pr->type) { - if (copts.cplusplus) { - if (IS_TYPE_TEMPLATE(pr->type)) { - if (TYPE_TEMPLATE(pr->type)->dtype == TEMPLDEP_ARGUMENT && TYPE_TEMPLATE(pr->type)->u.pid.type == TPT_NONTYPE) { - result = CExpr_NewTemplDepENode(TDE_PARAM); - result->data.templdep.u.pid = TYPE_TEMPLATE(pr->type)->u.pid; - tk = lex(); - return result; - } - if (TYPE_TEMPLATE(pr->type)->dtype == TEMPLDEP_QUALNAME && !pr->x20) { - result = CExpr_NewTemplDepENode(TDE_QUALNAME); - result->data.templdep.u.qual.type = TYPE_TEMPLATE(pr->type)->u.qual.type; - result->data.templdep.u.qual.name = TYPE_TEMPLATE(pr->type)->u.qual.name; - tk = lex(); - return result; - } - } - tk = lex(); - return CExpr_ParseExplicitConversion(pr->type, pr->qual); - } - CError_ErrorSkip(CErrorStr141); - tk = lex(); - return nullnode(); - } - - if (pr->obj_10) { - switch (pr->obj_10->otype) { - case OT_OBJECT: - if (OBJECT(pr->obj_10)->nspace && OBJECT(pr->obj_10)->nspace->theclass && (OBJECT(pr->obj_10)->nspace->theclass->flags & CLASS_IS_TEMPL)) { - result = CExpr_NewTemplDepENode(TDE_OBJ); - result->data.templdep.u.obj = OBJECT(pr->obj_10); - tk = lex(); - return result; - } - if (!expr || !IS_TEMPL_FUNC(OBJECT(pr->obj_10)->type)) { - if (!IS_TYPE_NONSTATIC_METHOD(OBJECT(pr->obj_10)->type)) { - tk = lex(); - if (tk == '<' && (ta_expr = CExpr_ExplicitTemplateArgCheck(pr))) - return ta_expr; - if (OBJECT(pr->obj_10)->datatype == DLOCAL && OBJECT(pr->obj_10)->u.var.info->func != cscope_currentfunc) { - CError_Error(CErrorStr330); - return nullnode(); - } - if (OBJECT(pr->obj_10)->datatype == DEXPR) { - result = CInline_CopyExpression(OBJECT(pr->obj_10)->u.expr, CopyMode0); - if (IS_TYPE_POINTER_ONLY(result->rtype) && ENODE_IS(result, EINTCONST)) { - result = makemonadicnode(result, ETYPCON); - result->data.monadic->rtype = TYPE(&stunsignedlong); - } - return result; - } - CClass_CheckObjectAccess(pr->bcl_18, OBJECT(pr->obj_10)); - if (tk == '(' && flag2 && OBJECT(pr->obj_10)->datatype == DFUNC && copts.cplusplus && !pr->x1D && !IS_TYPEFUNC_METHOD(TYPE_FUNC(OBJECT(pr->obj_10)->type))) { - result = CExpr_NewENode(EOBJLIST); - result->rtype = OBJECT(pr->obj_10)->type; - result->data.objlist.list = galloc(sizeof(NameSpaceObjectList)); - result->data.objlist.list->next = pr->nsol_14; - result->data.objlist.list->object = pr->obj_10; - result->data.objlist.name = OBJECT(pr->obj_10)->name; - return result; - } - - result = create_objectnode(OBJECT(pr->obj_10)); - if (expr) { - while (ENODE_IS(expr, EINDIRECT)) - expr = expr->data.monadic; - switch (expr->type) { - case EINTCONST: - case EOBJREF: - case EOBJLIST: - break; - default: - result = makecommaexpression(expr, result); - } - } - return result; - } - if (CClass_IsDestructor(OBJECT(pr->obj_10))) { - if ((tk = lex()) != '(') { - CError_Error(CErrorStr114); - return nullnode(); - } - if ((tk = lex()) != ')') { - CError_Error(CErrorStr115); - return nullnode(); - } - if (!expr && (!cscope_currentfunc || !cscope_currentclass || !cscope_is_member_func)) { - CError_Error(CErrorStr221); - return nullnode(); - } - if (pr->isambig) - CError_Error(CErrorStr188); - - if ((expr = CExpr_GetClassAccessNode(pr->bcl_18, NULL, expr, OBJECT(pr->obj_10), pr->obj_10->access, 1))) { - tk = lex(); - return CABI_DestroyObject(OBJECT(pr->obj_10), expr->data.monadic, 1, pr->x1D, 0); - } - } - } - break; - case OT_ENUMCONST: - CClass_CheckEnumAccess(pr->bcl_18, OBJ_ENUM_CONST(pr->obj_10)); - oec = OBJ_ENUM_CONST(pr->obj_10); - if (CInt64_IsZero(&oec->val) && IS_TYPE_ENUM(oec->type) && TYPE_ENUM(oec->type)->nspace && TYPE_ENUM(oec->type)->nspace->theclass && (TYPE_ENUM(oec->type)->nspace->theclass->flags & CLASS_IS_TEMPL)) { - val = 0; - expr = NULL; - for (act = TEMPL_CLASS(TYPE_ENUM(oec->type)->nspace->theclass)->actions; act; act = act->next) { - if (act->type == TAT_ENUMERATOR) { - if (act->u.enumerator.initexpr) { - expr = act->u.enumerator.initexpr; - val = 0; - } else { - val++; - } - if (act->u.enumerator.objenumconst == oec) { - CError_ASSERT(1521, expr); - expr = CInline_CopyExpression(expr, CopyMode0); - if (val) - expr = makediadicnode(expr, intconstnode(TYPE(&stsignedlong), val), EADD); - tk = lex(); - return expr; - } - } - } - } - result = lalloc(sizeof(ENode)); - result->type = EINTCONST; - result->cost = 0; - result->flags = 0; - result->rtype = OBJ_ENUM_CONST(pr->obj_10)->type; - result->data.intval = OBJ_ENUM_CONST(pr->obj_10)->val; - tk = lex(); - return result; - case OT_MEMBERVAR: - if (!flag1 || expr || !pr->x1D) { - if (pr->isambig) - CError_Error(CErrorStr188); - result = checkreference(CExpr_MemberVarAccess(pr->bcl_18, OBJ_MEMBER_VAR(pr->obj_10), expr)); - tk = lex(); - return result; - } - break; - default: - CError_FATAL(1552); - } - - member = lalloc(sizeof(EMemberInfo)); - memclrw(member, sizeof(EMemberInfo)); - member->path = pr->bcl_18; - member->expr = expr; - member->pr_1D = pr->x1D; - member->isambig = pr->isambig; - if ((tk = lex()) == '<' && (ta_expr = CExpr_ExplicitTemplateArgCheck(pr))) { - CError_ASSERT(1564, ENODE_IS(ta_expr, EOBJLIST)); - member->list = ta_expr->data.objlist.list; - member->templargs = ta_expr->data.objlist.templargs; - } else { - member->list = galloc(sizeof(NameSpaceObjectList)); - member->list->next = NULL; - member->list->object = pr->obj_10; - } - - result = CExpr_NewENode(EMEMBER); - result->data.emember = member; - result->rtype = &stvoid; - return result; - } - - if (pr->nsol_14) { - if ((tk = lex()) == '<' && (ta_expr = CExpr_ExplicitTemplateArgCheck(pr))) { - CError_ASSERT(1591, ENODE_IS(ta_expr, EOBJLIST)); - for (list = ta_expr->data.objlist.list; list; list = list->next) { - if (list->object->otype == OT_OBJECT && IS_TYPE_NONSTATIC_METHOD(OBJECT(list->object)->type)) { - member = lalloc(sizeof(EMemberInfo)); - memclrw(member, sizeof(EMemberInfo)); - - member->path = pr->bcl_18; - member->expr = expr; - member->list = ta_expr->data.objlist.list; - member->templargs = ta_expr->data.objlist.templargs; - member->pr_1D = pr->x1D; - member->isambig = pr->isambig; - - result = CExpr_NewENode(EMEMBER); - result->data.emember = member; - result->rtype = &stvoid; - return result; - } - } - return ta_expr; - } - - for (list = pr->nsol_14; list; list = list->next) { - if (list->object->otype == OT_OBJECT && IS_TYPE_NONSTATIC_METHOD(OBJECT(list->object)->type)) { - member = lalloc(sizeof(EMemberInfo)); - memclrw(member, sizeof(EMemberInfo)); - - member->path = pr->bcl_18; - member->expr = expr; - member->list = pr->nsol_14; - member->pr_1D = pr->x1D; - member->isambig = pr->isambig; - - result = CExpr_NewENode(EMEMBER); - result->data.emember = member; - result->rtype = &stvoid; - return result; - } - } - - if (tk == '<' && (ta_expr = CExpr_ExplicitTemplateArgCheck(pr))) - return ta_expr; - - result = CExpr_NewENode(EOBJLIST); - result->rtype = OBJECT(pr->nsol_14->object)->type; - result->data.objlist.list = pr->nsol_14; - if (tk == '(' && copts.cplusplus && flag2 && !pr->x1D && pr->nsol_14->object->otype == OT_OBJECT) - result->data.objlist.name = OBJECT(pr->nsol_14->object)->name; - return result; - } - - if (pr->name_4) { - if (copts.cplusplus && flag2) { - if (lookahead() == '(') { - result = CExpr_NewENode(EOBJLIST); - result->rtype = &stvoid; - result->data.objlist.name = pr->name_4; - tk = lex(); - return result; - } - CError_Error(CErrorStr140, pr->name_4->name); - tk = lex(); - return nullnode(); - } - - if (lookahead() != '(') { - CError_Error(CErrorStr140, pr->name_4->name); - tk = lex(); - return nullnode(); - } - - if (copts.checkprotos) - CError_Error(CErrorStr178); - - tfunc = galloc(sizeof(TypeFunc)); - memclrw(tfunc, sizeof(TypeFunc)); - tfunc->type = TYPEFUNC; - tfunc->functype = TYPE(&stsignedint); - tfunc->args = &oldstyle; - CDecl_SetFuncFlags(tfunc, 0); - - obj = CParser_NewFunctionObject(NULL); - obj->name = pr->name_4; - obj->sclass = TK_EXTERN; - obj->nspace = cscope_root; - obj->type = TYPE(tfunc); - - CScope_AddGlobalObject(obj); - tk = lex(); - return create_objectrefnode(obj); - } - - CError_FATAL(1711); - return NULL; -} - -static ENode *CExpr_ParseRotate(Boolean is_right) { - ENode *expr1; - ENode *expr2; - - if (lex() != '(') { - CError_Error(CErrorStr114); - return nullnode(); - } - - tk = lex(); - expr1 = assignment_expression(); - - if (tk != ',') { - CError_Error(CErrorStr116); - return nullnode(); - } - - tk = lex(); - expr2 = assignment_expression(); - - if (tk != ')') { - CError_Error(CErrorStr115); - return nullnode(); - } - - if (!IS_TYPE_INT(expr1->rtype)) - expr1 = forceintegral(expr1); - expr2 = integralpromote(expr2); - - tk = lex(); - if (iszero(expr1) || iszero(expr2)) - return expr1; - - return makediadicnode(expr1, expr2, is_right ? EROTR : EROTL); -} - -static ENode *CExpr_ParseNextArg(void) { - NameSpaceObjectList *list; - NameResult pr; - ENode *expr; - SInt32 rounded_size; - - if ((tk = lex()) != '(') { - CError_Error(CErrorStr114); - return nullnode(); - } - if ((tk = lex()) != TK_IDENTIFIER) { - CError_Error(CErrorStr107); - return nullnode(); - } - - list = CScope_FindObjectList(&pr, tkidentifier); - if (!list) { - CError_Error(CErrorStr140, tkidentifier->name); - return nullnode(); - } - - if (list->object->otype != OT_OBJECT || OBJECT(list->object)->datatype != DLOCAL) { - CError_Error(CErrorStr140, tkidentifier->name); - return nullnode(); - } - - rounded_size = CMach_RoundedSizeOf(OBJECT(list->object)); - expr = CExpr_MakeObjRefNode(OBJECT(list->object), 1); - expr = makediadicnode(expr, intconstnode(CABI_GetPtrDiffTType(), rounded_size), EADD); - expr->rtype = TYPE(&void_ptr); - - if ((tk = lex()) != ')') { - CError_Error(CErrorStr115); - return expr; - } else { - tk = lex(); - return expr; - } -} - -static ENode *CExpr_ParseVecStep(void) { - ENode *expr; - Type *type; - SInt32 value; - DeclInfo di; - - expr = intconstnode(TYPE(&stsignedint), 0); - if ((tk = lex()) == '(') { - if (tk == '(' && islookaheaddeclaration()) { - tk = lex(); - memclrw(&di, sizeof(DeclInfo)); - CParser_GetDeclSpecs(&di, 0); - scandeclarator(&di); - if (di.name) - CError_Error(CErrorStr121); - - if (tk != ')') - CError_ErrorSkip(CErrorStr115); - else - tk = lex(); - - type = di.thetype; - if (IS_TYPE_REFERENCE(type)) - type = TPTR_TARGET(type); - } else { - expr = unary_expression(); - if (ENODE_IS(expr, EINDIRECT) && ENODE_IS(expr->data.monadic, EBITFIELD)) - CError_Error(CErrorStr144); - type = expr->rtype; - } - - CDecl_CompleteType(type); - if (IS_TYPE_VECTOR(type)) { - switch (TYPE_STRUCT(type)->stype) { - case STRUCT_VECTOR_UCHAR: - case STRUCT_VECTOR_SCHAR: - case STRUCT_VECTOR_BCHAR: - value = 16; - break; - case STRUCT_VECTOR_USHORT: - case STRUCT_VECTOR_SSHORT: - case STRUCT_VECTOR_BSHORT: - case STRUCT_VECTOR_PIXEL: - value = 8; - break; - default: - value = 4; - } - expr = intconstnode(TYPE(&stsignedint), value); - } else { - PPCError_Error(PPCErrorStr104, "vec_step", "vec_step", type, 0); - } - } else { - CError_Error(CErrorStr114); - } - - return expr; -} - -static SInt32 CExpr_BuiltInComputeAlign(Type *type) { - return CMach_GetTypeAlign(type); -} - -static SInt32 CExpr_AtomTypeID(IntegralType what) { - switch (what) { - case IT_BOOL: return 1; - case IT_CHAR: return 2; - case IT_SCHAR: return 3; - case IT_UCHAR: return 4; - case IT_WCHAR_T: return 5; - case IT_SHORT: return 6; - case IT_USHORT: return 7; - case IT_INT: return 8; - case IT_UINT: return 9; - case IT_LONG: return 10; - case IT_ULONG: return 10; - case IT_LONGLONG: return 12; - case IT_ULONGLONG: return 13; - case IT_FLOAT: return 14; - case IT_SHORTDOUBLE: return 15; - case IT_DOUBLE: return 16; - case IT_LONGDOUBLE: return 17; - case IT_17: return 32; - case IT_18: return 33; - case IT_19: return 34; - case IT_20: return 35; - case IT_21: return 36; - case IT_22: return 37; - case IT_23: return 38; - case IT_24: return 39; - default: - CError_FATAL(1976); - return 0; - } -} - -static SInt32 CExpr_BuiltInComputeType(Type *type) { - switch (type->type) { - case TYPEINT: - return 0x100 | CExpr_AtomTypeID(TYPE_INTEGRAL(type)->integral); - case TYPEFLOAT: - return 0x200 | CExpr_AtomTypeID(TYPE_INTEGRAL(type)->integral); - case TYPEENUM: - return 0x400 | (CExpr_BuiltInComputeType(TYPE_ENUM(type)->enumtype) & 0xFF); - case TYPEPOINTER: - return 0x800; - case TYPEARRAY: - return 0x1000; - case TYPESTRUCT: - return 0x2000; - case TYPECLASS: - return 0x2000; - case TYPEMEMBERPOINTER: - return 0x4000; - case TYPEFUNC: - return 0x8000; - default: - CError_Error(CErrorStr146); - case TYPEVOID: - return 0; - } -} - -static SInt32 CExpr_BuiltInClassifyType(Type *type) { - switch (type->type) { - case TYPEVOID: return 0; - case TYPEFUNC: return 10; - case TYPEENUM: return 3; - case TYPEINT: return 1; - case TYPEFLOAT: return 8; - case TYPEPOINTER: case TYPEMEMBERPOINTER: return 5; - case TYPEARRAY: return 14; - case TYPESTRUCT: return 12; - case TYPECLASS: return 12; - case TYPEBITFIELD: return -1; - case TYPETEMPLATE: return -1; - default: return -1; - } -} - -static SInt32 CExpr_BuiltInComputeVArgType(Type *type) { - switch (type->type) { - case TYPEINT: - case TYPEENUM: - return 0; - case TYPEFLOAT: - return 1; - default: - return 2; - } -} - -static Type *CExpr_ParseTypeExpression(Boolean *outflag) { - ENode *expr; - Type *type; - DeclInfo di; - - tk = lex(); - if (tk == '(' && islookaheaddeclaration()) { - tk = lex(); - memclrw(&di, sizeof(DeclInfo)); - CParser_GetDeclSpecs(&di, 0); - scandeclarator(&di); - if (di.name) - CError_Error(CErrorStr121); - - if (tk != ')') - CError_ErrorSkip(CErrorStr115); - else - tk = lex(); - - type = di.thetype; - if (IS_TYPE_REFERENCE(type)) - type = TPTR_TARGET(type); - } else { - expr = unary_expression(); - if (ENODE_IS(expr, EINDIRECT) && ENODE_IS(expr->data.monadic, EBITFIELD)) - CError_Error(CErrorStr144); - - if (outflag) - *outflag = ENODE_IS(expr, EINTCONST) && CInt64_IsZero(&expr->data.intval); - - type = expr->rtype; - } - - CDecl_CompleteType(type); - return type; -} - -static ENode *CExpr_ParseBuiltin(SInt32 (*parser)(Type *)) { - ENode *expr; - expr = intconstnode(TYPE(&stsignedint), 0); - CInt64_SetLong(&expr->data.intval, parser(CExpr_ParseTypeExpression(NULL))); - return expr; -} - -static ENode *CExpr_ParseBuiltin_isintconst(void) { - ENode *expr; - expr = intconstnode(TYPE(&stsignedint), 0); - - tk = lex(); - if (tk != '(') - CError_ErrorSkip(CErrorStr121); - else - tk = lex(); - - if (ENODE_IS(expression(), EINTCONST)) - CInt64_SetLong(&expr->data.intval, 1); - - if (tk != ')') - CError_ErrorSkip(CErrorStr115); - else - tk = lex(); - - return expr; -} - -static ENode *primary_expression(Boolean flag) { - NameResult pr; - ENode *expr; - - switch (tk) { - case TK_TRUE: - expr = lalloc(sizeof(ENode)); - expr->type = EINTCONST; - expr->cost = 0; - expr->flags = 0; - expr->rtype = TYPE(&stbool); - CInt64_SetULong(&expr->data.intval, 1); - tk = lex(); - return expr; - case TK_FALSE: - expr = lalloc(sizeof(ENode)); - expr->type = EINTCONST; - expr->cost = 0; - expr->flags = 0; - expr->rtype = TYPE(&stbool); - CInt64_SetULong(&expr->data.intval, 0); - tk = lex(); - return expr; - case TK_INTCONST: - expr = lalloc(sizeof(ENode)); - expr->type = EINTCONST; - expr->cost = 0; - expr->flags = 0; - expr->rtype = atomtype(); - expr->data.intval = tkintconst; - tk = lex(); - return expr; - case TK_FLOATCONST: - expr = lalloc(sizeof(ENode)); - expr->type = EFLOATCONST; - expr->cost = 0; - expr->flags = 0; - expr->rtype = atomtype(); - expr->data.floatval = tkfloatconst; - tk = lex(); - return expr; - case TK_STRING: - expr = CExpr_NewENode(ESTRINGCONST); - expr->rtype = CDecl_NewArrayType(ispascalstring ? TYPE(&stunsignedchar) : TYPE(&stchar), tksize); - expr->data.string.size = tksize; - expr->data.string.data = tkstring; - expr->data.string.ispascal = ispascalstring; - if (copts.const_strings) - expr->flags = ENODE_FLAG_CONST; - expr = makemonadicnode(expr, EINDIRECT); - expr->data.monadic->rtype = CDecl_NewPointerType(expr->rtype); - tk = lex(); - return expr; - case TK_STRING_WIDE: - expr = CExpr_NewENode(ESTRINGCONST); - expr->rtype = CDecl_NewArrayType(CParser_GetWCharType(), tksize); - expr->data.string.size = tksize; - expr->data.string.data = tkstring; - expr->data.string.ispascal = ispascalstring; - if (copts.const_strings) - expr->flags = ENODE_FLAG_CONST; - expr = makemonadicnode(expr, EINDIRECT); - expr->data.monadic->rtype = CDecl_NewPointerType(expr->rtype); - tk = lex(); - return expr; - case TK_THIS: - case TK_SELF: - expr = CClass_CreateThisSelfExpr(); - if (!expr) - expr = nullnode(); - tk = lex(); - return expr; - case TK_AT_SELECTOR: - return CObjC_ParseSelectorExpression(); - case TK_AT_ENCODE: - return CObjC_ParseEncodeExpression(); - case TK_AT_PROTOCOL: - return CObjC_ParseProtocolExpression(); - case '@': - if (copts.objective_c) - return CObjC_ParseAtExpression(); - break; - case '(': - tk = lex(); - expr = s_expression(); - if (tk != ')') - CError_ErrorSkip(CErrorStr115); - else - tk = lex(); - if (ENODE_IS(expr, EASS)) - expr->flags = expr->flags | ENODE_FLAG_80; - return expr; - case '[': - if (copts.objective_c) - return CObjC_ParseMessageExpression(); - break; - case TK_IDENTIFIER: - if (tkidentifier->name[0] == '_' && tkidentifier->name[1] == '_') { - if (!strcmp(tkidentifier->name, "__builtin_align")) - return CExpr_ParseBuiltin(CExpr_BuiltInComputeAlign); - if (!strcmp(tkidentifier->name, "__builtin_ntype")) - return CExpr_ParseBuiltin(CExpr_BuiltInComputeType); - if (!strcmp(tkidentifier->name, "__builtin_type") || !strcmp(tkidentifier->name, "__builtin_vargtype")) - return CExpr_ParseBuiltin(CExpr_BuiltInComputeVArgType); - if (!strcmp(tkidentifier->name, "__builtin_classify_type")) - return CExpr_ParseBuiltin(CExpr_BuiltInClassifyType); - if (!strcmp(tkidentifier->name, "__builtin_next_arg")) - return CExpr_ParseNextArg(); - } - if (copts.altivec_model && !strcmp("vec_step", tkidentifier->name)) - return CExpr_ParseVecStep(); - case '~': - case TK_OPERATOR: - case TK_INHERITED: - case TK_COLON_COLON: - if (CScope_ParseExprName(&pr)) - return CExpr_ParseNameResultExpr(&pr, NULL, flag, 1); - tk = lex(); - return nullnode(); - } - - CError_ErrorSkip(CErrorStr141); - return nullnode(); -} - -static ENode *CExpr_SimpleExplicitConversion(void) { - DeclInfo di; - - memclrw(&di, sizeof(DeclInfo)); - - if (!copts.cpp_extensions && tk != TK_UU_TYPEOF_UU && tk != TK_TYPENAME && lookahead() != '(') - CError_Error(CErrorStr114); - - CParser_GetDeclSpecs(&di, 0); - return CExpr_ParseExplicitConversion(di.thetype, di.qual); -} - -static ENode *CExpr_NewPTMFCall(void) { - tk = lex(); - CExpr_ScanExpressionList(1); - - if (tk != ')') { - CError_Error(CErrorStr115); - return nullnode(); - } else { - CError_FATAL(2465); - return nullnode(); - } -} - -static ENode *call_ptmf(ENode *expr) { - Type *rettype; - ENodeList *args; - ENodeList *list1; - ENodeList *list2; - Object *callobj; - - rettype = TYPE_FUNC(TPTR_TARGET(expr->data.mfpointer.mfpointer->rtype))->functype; - tk = lex(); - args = CExpr_ScanExpressionList(1); - - if (tk != ')') { - CError_Error(CErrorStr115); - return nullnode(); - } - - if (IS_TYPE_STRUCT(rettype) || IS_TYPE_CLASS(rettype) || IS_TYPE_12BYTES_MEMBERPOINTER(rettype)) - callobj = rt_ptmf_scall4; - else - callobj = rt_ptmf_scall; - - list1 = lalloc(sizeof(ENodeList)); - list1->next = args; - list1->node = expr->data.mfpointer.accessnode->data.monadic; - - list2 = lalloc(sizeof(ENodeList)); - list2->next = list1; - list2->node = expr->data.mfpointer.mfpointer->data.monadic; - - if (!copts.old_argmatch) { - CError_ASSERT(2568, IS_TYPE_POINTER_ONLY(list2->node->rtype)); - list2->node->rtype = TYPE(&void_ptr); - } - - expr = CExpr_GenericPtmfCall( - callobj, - TYPE_FUNC(TPTR_TARGET(expr->data.mfpointer.mfpointer->rtype)), - list2); - tk = lex(); - return expr; -} - -static ENode *CExpr_DummyDestr(ENode *expr) { - SInt32 state; - NameResult pr; - DeclInfo di; - NameSpace *nspace; - - CPrep_TokenStreamGetState(&state); - nspace = cscope_current; - if ((tk = lex()) == TK_COLON_COLON) { - nspace = cscope_root; - tk = lex(); - } else if (tk != '~' && tk != TK_IDENTIFIER && !(tk >= TK_AUTO && tk <= TK_BYREF)) { - CPrep_TokenStreamSetCurState(&state); - return NULL; - } - -loop: - if (tk == '~') - goto is_tilde; - if (tk == TK_IDENTIFIER) { - if (CScope_FindTypeName(nspace, tkidentifier, &pr)) { - tk = lex(); - if (pr.nspace_0) { - if (tk == TK_COLON_COLON) { - tk = lex(); - nspace = pr.nspace_0; - goto loop; - } - } else if (IS_TYPE_CLASS(pr.type) && tk == TK_COLON_COLON) { - tk = lex(); - nspace = TYPE_CLASS(pr.type)->nspace; - goto loop; - } else { - if (!is_typesame(pr.type, expr->rtype)) - CError_Error(CErrorStr146); - if (tk == TK_COLON_COLON && ((tk = lex()) == '~') && ((tk = lex()) == TK_IDENTIFIER)) { - parse_dtor: - if (CScope_FindTypeName(nspace, tkidentifier, &pr) && !pr.nspace_0) { - if (!is_typesame(pr.type, expr->rtype)) - CError_Error(CErrorStr146); - tk = lex(); - goto parsed; - } - } - } - } - } else if (tk >= TK_AUTO && tk <= TK_BYREF) { - memclrw(&di, sizeof(DeclInfo)); - CParser_GetDeclSpecs(&di, 0); - if (di.storageclass || di.qual || !is_typesame(di.thetype, expr->rtype)) - CError_Error(CErrorStr146); - if (tk == TK_COLON_COLON && ((tk = lex()) == '~')) { - is_tilde: - if ((tk = lex()) == TK_IDENTIFIER) - goto parse_dtor; - memclrw(&di, sizeof(DeclInfo)); - CParser_GetDeclSpecs(&di, 0); - if (di.storageclass || !is_typesame(di.thetype, expr->rtype)) - CError_Error(CErrorStr146); - goto parsed; - } - } - - CError_Error(CErrorStr141); - return NULL; - -parsed: - if (tk == '(') { - if ((tk = lex()) != ')') - CError_Error(CErrorStr115); - else - tk = lex(); - } else { - CError_Error(CErrorStr114); - } - - expr = makemonadicnode(expr, ETYPCON); - expr->rtype = &stvoid; - return expr; -} - -static ENode *postfix_expression(Boolean flag) { - NameResult pr; - Conversion conv; - ENode *expr; - ENode *subexpr; - ENode *funcexpr; - ENodeList *args; - ENode *copy; - ENode *tmp; - StructMember *member; - - if (copts.cplusplus) { - switch (tk) { - case TK_VOID: - case TK_CHAR: - case TK_SHORT: - case TK_INT: - case TK_LONG: - case TK_FLOAT: - case TK_DOUBLE: - case TK_SIGNED: - case TK_UNSIGNED: - case TK_UNK_113: - case TK_UNK_114: - case TK_UNK_115: - case TK_UNK_116: - case TK_UNK_117: - case TK_UNK_118: - case TK_UNK_119: - case TK_UNK_11A: - case TK_UU_TYPEOF_UU: - case TK_BOOL: - case TK_WCHAR_T: - case TK_TYPENAME: - expr = CExpr_SimpleExplicitConversion(); - break; - default: - expr = primary_expression(flag); - break; - case TK_CONST_CAST: - expr = CRTTI_Parse_const_cast(); - break; - case TK_DYNAMIC_CAST: - expr = CRTTI_Parse_dynamic_cast(); - break; - case TK_REINTERPRET_CAST: - expr = CRTTI_Parse_reinterpret_cast(); - break; - case TK_STATIC_CAST: - expr = CRTTI_Parse_static_cast(); - break; - case TK_TYPEID: - expr = CRTTI_ParseTypeID(); - break; - } - } else { - expr = primary_expression(flag); - } - -loop: - switch (tk) { - case '[': - expr = pointer_generation(expr); - tk = lex(); - subexpr = expression(); - if (copts.cplusplus && CExpr_CheckOperator('[', expr, subexpr, &conv)) { - if ((expr = conv.x0)) { - if (tk != ']') - CError_ErrorSkip(CErrorStr125); - else - tk = lex(); - goto loop; - } - - CError_ASSERT(2753, expr = conv.left); - CError_ASSERT(2754, subexpr = conv.right); - } - - if (IS_TYPE_POINTER(expr->rtype)) { - expr = padd(expr, subexpr); - } else if (IS_TYPE_POINTER(subexpr->rtype)) { - expr = padd(subexpr, expr); - } else { - CError_Error(CErrorStr148); - goto dont_do_indirect; - } - expr = makemonadicnode(expr, EINDIRECT); - expr->rtype = TPTR_TARGET(expr->rtype); - dont_do_indirect: - if (tk != ']') - CError_ErrorSkip(CErrorStr125); - else - tk = lex(); - goto loop; - - case '(': - funcexpr = CExpr_PointerGeneration(expr); - if (copts.cplusplus) { - if (CExpr_CheckOperator('(', funcexpr, NULL, &conv)) { - CError_ASSERT(2775, expr = conv.x0); - goto loop; - } - if (ENODE_IS(funcexpr, EMFPOINTER)) { - expr = checkreference(call_ptmf(funcexpr)); - goto loop; - } - } - - tk = lex(); - args = CExpr_ScanExpressionList(1); - if (tk != ')') - CError_Error(CErrorStr115); - - if (ENODE_IS(funcexpr, ETEMPLDEP)) { - expr = CExpr_NewENode(EFUNCCALL); - expr->rtype = &sttemplexpr; - expr->data.funccall.funcref = funcexpr; - expr->data.funccall.args = args; - expr->data.funccall.functype = &rt_func; - tk = lex(); - } else { - expr = checkreference(CExpr_MakeFunctionCall(funcexpr, args)); - tk = lex(); - } - goto loop; - - case TK_ARROW: - expr = pointer_generation(expr); - if (copts.cplusplus) { - while (IS_TYPE_CLASS(expr->rtype) && CExpr_CheckOperator(TK_ARROW, expr, NULL, &conv)) { - CError_ASSERT(2810, subexpr = conv.x0); - expr = pointer_generation(subexpr); - } - } - - if (!IS_TYPE_POINTER(expr->rtype)) { - CError_ErrorSkip(CErrorStr148); - return expr; - } - - if (copts.cplusplus && copts.objective_c && CObjC_IsType_id(expr->rtype)) { - expr = makemonadicnode(expr, EINDIRECT); - expr->rtype = TPTR_TARGET(expr->rtype); - if ((subexpr = CObjC_CheckModernSendMessage(NULL, expr))) - return subexpr; - } else { - expr = makemonadicnode(expr, EINDIRECT); - expr->rtype = TPTR_TARGET(expr->rtype); - } - case '.': - expr = pointer_generation(expr); - if (IS_TYPE_CLASS(expr->rtype)) { - CDecl_CompleteType(expr->rtype); - if (TYPE_CLASS(expr->rtype)->objcinfo && copts.cplusplus && (subexpr = CObjC_CheckModernSendMessage(TYPE_CLASS(expr->rtype), expr))) - return subexpr; - - if (!(TYPE_CLASS(expr->rtype)->flags & CLASS_COMPLETED)) - CError_Error(CErrorStr136, expr->rtype, 0); - - if ((tk = lex()) == TK_TEMPLATE && (tk = lex()) != TK_IDENTIFIER) - CError_Error(CErrorStr107); - - if (CScope_ParseMemberName(TYPE_CLASS(expr->rtype), &pr, 0)) { - if (pr.x1C) { - if ((tk = lex()) == '(') { - if ((tk = lex()) != ')') - CError_Error(CErrorStr115); - else - tk = lex(); - } else { - CError_Error(CErrorStr114); - } - - expr = makemonadicnode(expr, ETYPCON); - expr->rtype = &stvoid; - } else { - expr = checkreference(CExpr_ParseNameResultExpr(&pr, expr, 0, 0)); - } - } - goto loop; - } - if (!IS_TYPE_STRUCT(expr->rtype) || TYPE_STRUCT(expr->rtype)->stype > STRUCT_TYPE_MAX) { - if (copts.cplusplus && (subexpr = CExpr_DummyDestr(expr))) - return subexpr; - CError_ErrorSkip(CErrorStr149); - return expr; - } - if (!ENODE_IS(expr, EINDIRECT)) { - subexpr = CExpr_NewETEMPNode(expr->rtype, 1); - copy = lalloc(sizeof(ENode)); - *copy = *subexpr; - - tmp = makemonadicnode(subexpr, EINDIRECT); - tmp->rtype = expr->rtype; - - tmp = makediadicnode(tmp, expr, EASS); - tmp = makediadicnode(tmp, copy, ECOMMA); - tmp->rtype = copy->rtype; - - tmp = makemonadicnode(tmp, EINDIRECT); - tmp->rtype = expr->rtype; - expr = tmp; - } - if ((tk = lex()) != TK_IDENTIFIER) { - CError_Error(CErrorStr107); - return expr; - } - - member = ismember(TYPE_STRUCT(expr->rtype), tkidentifier); - if (!member) { - if (!expr->rtype->size) - CError_Error(CErrorStr136, expr->rtype, 0); - else - CError_Error(CErrorStr150, tkidentifier->name); - return expr; - } - - if (!IS_TYPE_POINTER(expr->data.monadic->rtype)) { - CError_ErrorSkip(CErrorStr149); - return expr; - } - - expr = checkreference(CClass_AccessMember(expr, member->type, member->qual, member->offset)); - tk = lex(); - goto loop; - - case TK_INCREMENT: - tmp = pointer_generation(expr); - if (copts.cplusplus && CExpr_CheckOperator(TK_INCREMENT, tmp, nullnode(), &conv)) { - if ((expr = conv.x0)) { - tk = lex(); - goto loop; - } - CError_ASSERT(2952, tmp = conv.left); - } - tmp = CExpr_LValue(tmp, 1, 1); - if (tmp->rtype == TYPE(&stbool)) { - expr = CExpr_TempModifyExpr(tmp); - tk = lex(); - } else { - checkadditive(tmp); - expr = makemonadicnode(tmp, EPOSTINC); - tk = lex(); - } - goto loop; - - case TK_DECREMENT: - tmp = pointer_generation(expr); - if (copts.cplusplus && CExpr_CheckOperator(TK_DECREMENT, tmp, nullnode(), &conv)) { - if ((expr = conv.x0)) { - tk = lex(); - goto loop; - } - CError_ASSERT(2976, tmp = conv.left); - } - tmp = CExpr_LValue(tmp, 1, 1); - checkadditive(tmp); - expr = makemonadicnode(tmp, EPOSTDEC); - tk = lex(); - goto loop; - } - - return expr; -} - -static ENode *CExpr_ParseSizeof(void) { - Type *type; - ENode *expr; - - type = CExpr_ParseTypeExpression(NULL); - if (IS_TYPE_CLASS(type) && TYPE_CLASS(type)->sominfo) - CError_Error(CErrorStr286); - - if (CTemplTool_IsTemplateArgumentDependentType(type)) { - expr = CExpr_NewTemplDepENode(TDE_SIZEOF); - expr->data.templdep.u.typeexpr.type = type; - return expr; - } - - if (type->size == 0) { - if (copts.gcc_extensions && (IS_TYPE_FUNC(type) || IS_TYPE_VOID(type))) - return intconstnode(CABI_GetSizeTType(), 1); - - if (IS_TYPE_CLASS(type) || IS_TYPE_STRUCT(type)) - CError_Error(CErrorStr136, type, 0); - else - CError_Error(CErrorStr146); - } - - return intconstnode(CABI_GetSizeTType(), type->size); -} - -SInt32 scansizeof(void) { - ENode *expr; - - expr = CExpr_ParseSizeof(); - if (!ENODE_IS(expr, EINTCONST)) { - CError_Error(CErrorStr190); - return 0; - } - - return CInt64_GetULong(&expr->data.intval); -} - -static ENode *CExpr_ParseAlignof(void) { - Type *type; - ENode *expr; - SInt16 align; - - type = CExpr_ParseTypeExpression(NULL); - if (IS_TYPE_CLASS(type) && TYPE_CLASS(type)->sominfo) - CError_Error(CErrorStr364); - - if (CTemplTool_IsTemplateArgumentDependentType(type)) { - expr = CExpr_NewTemplDepENode(TDE_ALIGNOF); - expr->data.templdep.u.typeexpr.type = type; - return expr; - } - - if (type->size == 0) { - if (IS_TYPE_CLASS(type) || IS_TYPE_STRUCT(type)) - CError_Error(CErrorStr136, type, 0); - else - CError_Error(CErrorStr146); - } - - align = CMach_GetTypeAlign(type); - if (align == 0) - align = 1; - - return intconstnode(CABI_GetSizeTType(), align); -} - -SInt32 scanalignof(void) { - ENode *expr; - - expr = CExpr_ParseAlignof(); - if (!ENODE_IS(expr, EINTCONST)) { - CError_Error(CErrorStr190); - return 0; - } - - return CInt64_GetULong(&expr->data.intval); -} - -static ENode *logicalexpression(ENode *expr) { - if (copts.cplusplus && copts.booltruefalse) - expr->rtype = TYPE(&stbool); - else - expr->rtype = TYPE(&stsignedint); - return expr; -} - -ENode *getnodeaddress(ENode *expr, Boolean flag) { - ENode *result; - Object *obj; - - if (!ENODE_IS(expr, EINDIRECT)) { - expr = CExpr_LValue(expr, flag, flag); - if (!ENODE_IS(expr, EINDIRECT)) { - if (!flag) - CError_Error(CErrorStr142); - return nullnode(); - } - } else { - if (flag && - 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(CErrorStr189); - } - - result = lalloc(sizeof(ENode)); - *result = *expr; -restart: - switch (result->data.monadic->type) { - case EPOSTINC: - case EPOSTDEC: - case EPREINC: - case EPREDEC: - result->type = ETYPCON; - if (IS_TYPE_POINTER_ONLY(result->rtype)) - result->flags = TPTR_QUAL(result->rtype) & ENODE_FLAG_QUALS; - result->rtype = CDecl_NewPointerType(result->rtype); - return result; - case EOBJREF: - obj = result->data.monadic->data.objref; - if (obj->datatype == DALIAS) { - CExpr_AliasTransform(result->data.monadic); - goto restart; - } - if (obj->datatype == DINLINEFUNC) - CError_Error(CErrorStr175); - obj->flags = obj->flags | OBJECT_FLAGS_2; - if (flag && !copts.cplusplus && obj->sclass == TK_REGISTER) - CError_Error(CErrorStr163); - break; - case EFUNCCALL: - if (flag && !IS_TYPE_POINTER_ONLY(result->data.monadic->data.funccall.functype->functype)) - CError_Warning(CErrorStr142); - break; - case EBITFIELD: - CError_Error(CErrorStr144); - return nullnode(); - } - - switch (result->rtype->type) { - case TYPEPOINTER: - result->data.monadic->rtype = CDecl_NewPointerType(result->rtype); - result->data.monadic->flags = result->flags; - break; - default: - result->data.monadic->rtype = CDecl_NewPointerType(result->rtype); - result->data.monadic->flags = result->flags; - } - - return result->data.monadic; -} - -static ENode *CExpr_MakeStaticMemberList(NameSpaceObjectList *list) { - NameSpaceObjectList *newlist; - NameSpaceObjectList *n; - ENode *result; - - newlist = NULL; - while (list) { - if (list->object->otype == OT_OBJECT && IS_TYPE_STATIC_METHOD(OBJECT(list->object)->type)) { - n = galloc(sizeof(NameSpaceObjectList)); - *n = *list; - n->next = newlist; - newlist = n; - } - list = list->next; - } - - if (!newlist) { - CError_Warning(CErrorStr331); - return nullnode(); - } - - result = CExpr_NewENode(EOBJLIST); - result->rtype = OBJECT(newlist->object)->type; - result->data.objlist.list = newlist; - return result; -} - -static ENode *CExpr_MakePTDM(ENode *expr) { - ENode *result; - - CError_ASSERT(3414, ENODE_IS(expr, EMEMBER) && expr->data.emember->list->object->otype == OT_MEMBERVAR); - - result = nullnode(); - result->rtype = CExpr_NewPTMType(expr->data.emember, NULL); - CInt64_SetLong(&result->data.intval, OBJ_MEMBER_VAR(expr->data.emember->list->object)->offset + 1); - return result; -} - -ENode *getpointertomemberfunc(ENode *expr, Type *type, Boolean flag) { - NameSpaceObjectList *list; - Object *obj; - Object *dataobj; - Type *ptmtype; - TypeMemberFunc *tmethod; - OLinkList *olist; - SInt32 data[3]; - - CError_ASSERT(3442, ENODE_IS(expr, EMEMBER)); - - if (expr->data.emember->expr && !copts.cpp_extensions) - CError_Error(CErrorStr141); - - if (!copts.cpp_extensions) { - if (!(expr->data.emember->x11 && expr->data.emember->pr_1D)) { - if (type && IS_TYPE_MEMBERPOINTER(type)) - CError_Warning(CErrorStr331); - } - } - - if (expr->data.emember->list->next) { - if (type) { - if (IS_TYPE_MEMBERPOINTER(type)) { - type = TYPE_MEMBER_POINTER(type)->ty1; - for (list = expr->data.emember->list; list; list = list->next) { - if (list->object->otype == OT_OBJECT && is_memberpointerequal(OBJECT(list->object)->type, type)) { - obj = OBJECT(list->object); - break; - } - } - if (!list) { - CError_Error(CErrorStr146); - return nullnode(); - } - } else { - return CExpr_MakeStaticMemberList(expr->data.emember->list); - } - } else { - obj = OBJECT(expr->data.emember->list->object); - } - } else { - obj = OBJECT(expr->data.emember->list->object); - } - - while (obj->datatype == DALIAS) - obj = obj->u.alias.object; - - CError_ASSERT(3503, obj->otype == OT_OBJECT && IS_TYPE_NONSTATIC_METHOD(obj->type)); - - if (TYPE_FUNC(obj->type)->flags & FUNC_IS_TEMPL) - CError_Error(CErrorStr190); - - ptmtype = CExpr_NewPTMType(expr->data.emember, obj); - tmethod = TYPE_METHOD(obj->type); - dataobj = CParser_NewGlobalDataObject(NULL); - dataobj->name = CParser_GetUniqueName(); - dataobj->nspace = cscope_root; - dataobj->type = ptmtype; - dataobj->sclass = TK_STATIC; - - if (flag) { - data[0] = 0; - if (obj->datatype == DVFUNC) { - olist = NULL; - data[1] = tmethod->vtbl_index; - data[2] = tmethod->theclass->vtable->offset; - } else { - data[1] = -1; - data[2] = 0; - olist = galloc(sizeof(OLinkList)); - olist->next = NULL; - olist->obj = obj; - olist->somevalue = 0; - olist->offset = 8; - } - CInit_DeclareData(dataobj, data, olist, dataobj->type->size); - } - - return create_objectnode(dataobj); -} - -static ENode *getpointertomember(ENode *expr) { - CError_ASSERT(3554, ENODE_IS(expr, EMEMBER)); - - if (expr->data.emember->expr) - CError_Error(CErrorStr141); - - expr->data.emember->x11 = 1; - if (!expr->data.emember->list->next) { - if (expr->data.emember->list->object->otype == OT_MEMBERVAR) - return CExpr_MakePTDM(expr); - else - return getpointertomemberfunc(expr, NULL, 1); - } - - return expr; -} - -ENode *CExpr_New_ELOGNOT_Node(ENode *input) { - ENode *expr; - Conversion conv; - - if (IS_TYPE_TEMPLDEPEXPR(input->rtype)) - return CTempl_MakeTemplDepExpr(NULL, ELOGNOT, input); - - expr = pointer_generation(input); - if (copts.cplusplus && CExpr_CheckOperator('!', expr, NULL, &conv)) { - if ((input = conv.x0)) - return input; - CError_ASSERT(3593, expr = conv.left); - } - - switch (expr->rtype->type) { - case TYPEINT: - case TYPEFLOAT: - case TYPEPOINTER: - case TYPEARRAY: - break; - case TYPEENUM: - expr = forceintegral(expr); - break; - case TYPEMEMBERPOINTER: - expr = CExpr_ConvertToCondition(expr); - break; - default: - CError_Error(CErrorStr144); - return expr; - } - - switch (expr->type) { - case EINTCONST: - expr->data.intval = CInt64_Not(expr->data.intval); - break; - case EFLOATCONST: - expr->type = EINTCONST; - CInt64_SetLong(&expr->data.intval, CMach_FloatIsZero(expr->data.floatval)); - break; - default: - expr = makemonadicnode(expr, ELOGNOT); - } - - return logicalexpression(expr); -} - -ENode *CExpr_New_EMONMIN_Node(ENode *input) { - ENode *expr; - Conversion conv; - - if (IS_TYPE_TEMPLDEPEXPR(input->rtype)) - return CTempl_MakeTemplDepExpr(NULL, EMONMIN, input); - - expr = pointer_generation(input); - if (copts.cplusplus && CExpr_CheckOperator('-', expr, NULL, &conv)) { - if ((input = conv.x0)) - return input; - CError_ASSERT(3652, expr = conv.left); - } - - switch (expr->rtype->type) { - case TYPEINT: - case TYPEENUM: - expr = integralpromote(expr); - if (ENODE_IS(expr, EINTCONST)) { - expr->data.intval = CMach_CalcIntMonadic(expr->rtype, '-', expr->data.intval); - return expr; - } - return makemonadicnode(expr, EMONMIN); - case TYPEFLOAT: - if (ENODE_IS(expr, EFLOATCONST)) { - expr->data.floatval = CMach_CalcFloatMonadic(expr->rtype, '-', expr->data.floatval); - return expr; - } - return CExpr_UnaryFloatExpression(makemonadicnode(expr, EMONMIN)); - default: - CError_Error(CErrorStr144); - return expr; - } -} - -ENode *CExpr_New_EBINNOT_Node(ENode *input) { - ENode *expr; - Conversion conv; - - if (IS_TYPE_TEMPLDEPEXPR(input->rtype)) - return CTempl_MakeTemplDepExpr(NULL, EBINNOT, input); - - expr = pointer_generation(input); - if (copts.cplusplus && CExpr_CheckOperator('~', expr, NULL, &conv)) { - if ((input = conv.x0)) - return input; - CError_ASSERT(3702, expr = conv.left); - } - - expr = integralpromote(expr); - - if (ENODE_IS(expr, EINTCONST)) { - expr->data.intval = CMach_CalcIntMonadic(expr->rtype, '~', expr->data.intval); - return expr; - } - return makemonadicnode(expr, EBINNOT); -} - -ENode *unary_expression(void) { - ENode *expr; - ENode *tmp; - Conversion conv; - - switch (tk) { - case TK_COLON_COLON: - switch (lookahead()) { - case TK_NEW: - tk = lex(); - return scannew(1); - case TK_DELETE: - tk = lex(); - return scandelete(1); - } - return postfix_expression(0); - - case TK_NEW: - return scannew(0); - case TK_DELETE: - return scandelete(0); - case TK_INCREMENT: - tk = lex(); - if (copts.cplusplus) { - expr = pointer_generation(cast_expression()); - if (CExpr_CheckOperator(TK_INCREMENT, expr, NULL, &conv)) { - if (conv.x0) - return conv.x0; - CError_ASSERT(3748, expr = conv.left); - } - } else { - expr = pointer_generation(unary_expression()); - } - expr = CExpr_LValue(expr, 1, 1); - if (expr->rtype == TYPE(&stbool)) { - tmp = nullnode(); - tmp->rtype = TYPE(&stbool); - CInt64_SetLong(&tmp->data.intval, 1); - return makediadicnode(expr, tmp, EASS); - } else { - checkadditive(expr); - return makemonadicnode(expr, EPREINC); - } - case TK_DECREMENT: - tk = lex(); - if (copts.cplusplus) { - expr = pointer_generation(cast_expression()); - if (CExpr_CheckOperator(TK_DECREMENT, expr, NULL, &conv)) { - if (conv.x0) - return conv.x0; - CError_ASSERT(3776, expr = conv.left); - } - } else { - expr = pointer_generation(unary_expression()); - } - expr = CExpr_LValue(expr, 1, 1); - checkadditive(expr); - return makemonadicnode(expr, EPREDEC); - - case '&': - if (copts.cplusplus) { - switch ((tk = lex())) { - case TK_IDENTIFIER: - case TK_INHERITED: - case TK_COLON_COLON: - expr = postfix_expression(1); - if (ENODE_IS(expr, EMEMBER)) - return getpointertomember(expr); - break; - default: - expr = cast_expression(); - } - - if (CExpr_CheckOperator('&', expr, NULL, &conv)) { - CError_ASSERT(3809, conv.x0); - return conv.x0; - } - } else { - tk = lex(); - expr = cast_expression(); - } - - if (copts.mpwc_relax && !copts.cplusplus && IS_TYPE_ARRAY(expr->rtype) && ENODE_IS(expr, EINDIRECT)) - return pointer_generation(expr); - if (ENODE_IS(expr, EOBJLIST)) - return expr; - - if (IS_TYPE_TEMPLDEPEXPR(expr->rtype)) { - tmp = CExpr_NewTemplDepENode(TDE_ADDRESS_OF); - tmp->data.templdep.u.monadic = expr; - return tmp; - } - - return getnodeaddress(expr, 1); - - case '*': - tk = lex(); - expr = pointer_generation(cast_expression()); - if (copts.cplusplus && CExpr_CheckOperator('*', expr, NULL, &conv)) { - if (conv.x0) - return conv.x0; - CError_ASSERT(3840, expr = conv.left); - } - - if (!IS_TYPE_POINTER(expr->rtype)) { - CError_Error(CErrorStr148); - return expr; - } - - tmp = makemonadicnode(expr, EINDIRECT); - CDecl_CompleteType(tmp->rtype = TPTR_TARGET(tmp->rtype)); - return tmp; - - case '+': - tk = lex(); - expr = pointer_generation(cast_expression()); - if (copts.cplusplus && CExpr_CheckOperator('+', expr, NULL, &conv)) { - if (conv.x0) - return conv.x0; - CError_ASSERT(3852, expr = conv.left); - } - - switch (expr->rtype->type) { - case TYPEINT: - case TYPEENUM: - return integralpromote(expr); - case TYPEFLOAT: - case TYPEPOINTER: - case TYPEARRAY: - return expr; - default: - CError_Error(CErrorStr144); - return expr; - } - - case '-': - tk = lex(); - return CExpr_New_EMONMIN_Node(cast_expression()); - case '~': - tk = lex(); - return CExpr_New_EBINNOT_Node(cast_expression()); - case '!': - tk = lex(); - return CExpr_New_ELOGNOT_Node(cast_expression()); - - case TK_SIZEOF: - return CExpr_ParseSizeof(); - case TK_UU_ALIGNOF_UU: - return CExpr_ParseAlignof(); - - case TK_LOGICAL_AND: - if (copts.ANSIstrict) - break; - - if ((tk = lex()) != TK_IDENTIFIER) { - CError_Error(CErrorStr107); - return nullnode(); - } - - expr = lalloc(sizeof(ENode)); - expr->type = ELABEL; - expr->cost = 0; - expr->flags = 0; - expr->rtype = TYPE(&void_ptr); - expr->data.label = findlabel(); - if (!expr->data.label) { - expr->data.label = newlabel(); - expr->data.label->name = tkidentifier; - expr->data.label->next = Labels; - Labels = expr->data.label; - } - tk = lex(); - return expr; - } - - return postfix_expression(0); -} - -ENode *do_castnullcheck(ENode *condexpr, ENode *nullcheckexpr) { - ENode *result; - - if (isnotzero(nullcheckexpr)) - return condexpr; - - result = lalloc(sizeof(ENode)); - *result = *condexpr; - result->type = ENULLCHECK; - result->data.nullcheck.nullcheckexpr = lalloc(sizeof(ENode)); - *result->data.nullcheck.nullcheckexpr = *nullcheckexpr; - result->data.nullcheck.condexpr = condexpr; - result->data.nullcheck.precompid = CParser_GetUniqueID(); - - nullcheckexpr->type = EPRECOMP; - nullcheckexpr->data.precompid = result->data.nullcheck.precompid; - - return result; -} - -ENode *CExpr_SafeClassPointerCast(ENode *expr, TypeClass *a, TypeClass *b, Boolean typconflag, Boolean pathcheckflag) { - ENode *result; - - result = CClass_ClassPointerCast(expr, a, b, typconflag, 1, pathcheckflag); - if (result != expr) { - if (!(ENODE_IS(result, ETYPCON) && result->data.monadic == expr)) - result = do_castnullcheck(result, expr); - } - return result; -} - -ENode *PointerToMemberCast(ENode *expr, TypeMemberPointer *tm1, TypeMemberPointer *tm2, Boolean flag) { - BClassList *path; - Boolean negate; - short depth; - Boolean isambig; - SInt32 pathoffset; - CInt64 pathoffset64; - ENode *tmp; - - CError_ASSERT(3984, IS_TYPE_CLASS(tm1->ty2)); - CError_ASSERT(3985, IS_TYPE_CLASS(tm2->ty2)); - - if (tm1->ty2 == tm2->ty2) { - expr->rtype = TYPE(tm2); - return expr; - } - - negate = 0; - path = CClass_GetBasePath(TYPE_CLASS(tm2->ty2), TYPE_CLASS(tm1->ty2), &depth, &isambig); - if (!path) { - path = CClass_GetBasePath(TYPE_CLASS(tm1->ty2), TYPE_CLASS(tm2->ty2), &depth, &isambig); - if (!path) - goto failed; - negate = 1; - } - - if (isambig) - CError_Error(CErrorStr188); - - if ((pathoffset = CClass_GetPathOffset(path)) < 0) - goto failed; - if (negate) - pathoffset = -pathoffset; - - if (flag) - CClass_CheckPathAccess(path, NULL, ACCESSPUBLIC); - - if (tm1->size != tm2->size) { - failed: - CError_Error(CErrorStr247, tm1, 0, tm2, 0); - return nullnode(); - } - - if (!pathoffset) { - expr->rtype = TYPE(tm2); - return expr; - } - - if (tm1->size == 4u) { - if (ENODE_IS(expr, EINTCONST)) { - if (!CInt64_IsZero(&expr->data.intval)) { - CInt64_SetLong(&pathoffset64, pathoffset); - expr->data.intval = CInt64_Add(expr->data.intval, pathoffset64); - } - expr->rtype = TYPE(tm2); - return expr; - } else { - expr->rtype = TYPE(&stunsignedlong); - tmp = intconstnode(TYPE(&stunsignedlong), pathoffset); - tmp = makediadicnode(expr, tmp, EADD); - tmp = makemonadicnode(tmp, ETYPCON); - tmp->rtype = TYPE(tm2); - return do_castnullcheck(tmp, expr); - } - } else { - tmp = create_temp_node(TYPE(&ptmstruct)); - expr = getnodeaddress(expr, 0); - tmp = funccallexpr(rt_ptmf_cast, intconstnode(TYPE(&stsignedlong), pathoffset), expr, tmp, NULL); - tmp = makemonadicnode(tmp, EINDIRECT); - tmp->rtype = TYPE(tm2); - return tmp; - } -} - -ENode *CExpr_MemberPointerConversion(ENode *expr, TypeMemberPointer *type, Boolean flag1) { - if (ENODE_IS(expr, EINTCONST) && CInt64_IsZero(&expr->data.intval)) { - if (IS_TYPE_FUNC(type->ty1)) - expr = create_objectnode(rt_ptmf_null); - expr->rtype = TYPE(type); - } else if (ENODE_IS(expr, EMEMBER)) { - expr = getpointertomemberfunc(expr, TYPE(type), flag1); - } - - return expr; -} - -static ENode *CExpr_MemberPointerCast(ENode *expr, TypeMemberPointer *type, UInt32 qual) { - if (!IS_TYPE_MEMBERPOINTER(expr->rtype)) - expr = CExpr_MemberPointerConversion(expr, type, 1); - - if (!IS_TYPE_MEMBERPOINTER(expr->rtype)) { - CError_Error(CErrorStr164); - return nullnode(); - } - - expr = PointerToMemberCast(expr, TYPE_MEMBER_POINTER(expr->rtype), type, 0); - expr->flags = qual & ENODE_FLAG_QUALS; - return expr; -} - -ENode *do_typecast(ENode *expr, Type *type, UInt32 qual) { - TypePointer *tptr; - ENode *tmp; - short flags; - - if (!copts.old_argmatch) - return CExpr_Convert(expr, type, qual, 1, 0); - - if (copts.cpp_extensions && is_typesame(expr->rtype, type) && !ENODE_IS(expr, EOBJLIST)) { - expr->rtype = type; - expr->flags &= ~ENODE_FLAG_QUALS; - expr->flags |= qual & ENODE_FLAG_QUALS; - return expr; - } - - switch (type->type) { - case TYPEARRAY: - CError_Error(CErrorStr247, expr->rtype, ENODE_QUALS(expr), type, qual); - return expr; - case TYPEMEMBERPOINTER: - if (!IS_TYPE_CLASS(expr->rtype)) - return CExpr_MemberPointerCast(expr, TYPE_MEMBER_POINTER(type), qual); - } - - flags = qual & ENODE_FLAG_QUALS; - - if (ENODE_IS(expr, EOBJLIST)) - return CExpr_AssignmentPromotion(expr, type, qual & ENODE_FLAG_QUALS, 1); - - if (ENODE_IS(expr, EOBJREF) && IS_TYPE_NONSTATIC_METHOD(expr->data.objref->type)) { - CError_Error(CErrorStr221); - return nullnode(); - } - - if (type == &stvoid) { - expr = makemonadicnode(expr, ETYPCON); - expr->rtype = type; - expr->flags = flags; - return expr; - } - - if (IS_TYPE_REFERENCE(type)) { - tmp = getnodeaddress(expr, 0); - tptr = galloc(sizeof(TypePointer)); - *tptr = *TYPE_POINTER(type); - tptr->qual &= ~Q_REFERENCE; - - tmp = do_typecast(tmp, TYPE(tptr), qual); - tmp = makemonadicnode(tmp, EINDIRECT); - tmp->rtype = TPTR_TARGET(type); - tmp->flags = flags; - return tmp; - } - - if (IS_TYPE_CLASS(expr->rtype) || IS_TYPE_CLASS(type)) { - if (expr->rtype->size == 0) - CDecl_CompleteType(expr->rtype); - - if (expr->rtype == type && !CClass_CopyConstructor(TYPE_CLASS(type))) - return expr; - - if (user_assign_check(expr, type, qual, 1, 1, 1)) { - assign_node->flags = flags; - return assign_node; - } - - CError_Error(CErrorStr247, expr->rtype, ENODE_QUALS(expr), type, qual); - return nullnode(); - } - - if (IS_TYPE_STRUCT(type) && copts.cplusplus && is_typesame(expr->rtype, type)) { - expr->rtype = type; - expr->flags = flags; - return expr; - } - - if (type == TYPE(&stbool)) { - expr = CExpr_ConvertToBool(expr, 1); - expr->flags = flags; - return expr; - } - - if (IS_TYPE_ENUM(type)) { - tmp = do_typecast(expr, TYPE_ENUM(type)->enumtype, qual); - if (!ENODE_IS(tmp, EINTCONST)) - tmp = makemonadicnode(tmp, ETYPCON); - tmp->rtype = type; - tmp->flags = flags; - return tmp; - } - - if (IS_TYPE_INT_OR_FLOAT(type)) { - if (ENODE_IS(expr, ETYPCON) && expr->rtype->type == type->type && expr->rtype->size == type->size) { - if (is_unsigned(expr->rtype) == is_unsigned(type) && ENODE_QUALS(expr) == qual) { - expr->rtype = type; - expr->flags = expr->flags | ENODE_FLAG_80; - return expr; - } - } - - if (IS_TYPE_ENUM(expr->rtype)) - expr = forceintegral(expr); - - if (IS_TYPE_INT_OR_FLOAT(expr->rtype)) { - expr = promote(expr, type); - expr->flags = flags; - return expr; - } - - if (!(IS_TYPE_POINTER_ONLY(expr->rtype) && !IS_TYPE_FLOAT(type))) - CError_Error(CErrorStr247, expr->rtype, ENODE_QUALS(expr), type, qual); - - if (ENODE_IS(expr, ETYPCON) && ENODE_IS(tmp = expr->data.monadic, EINTCONST)) { - tmp->rtype = type; - tmp->flags = flags; - tmp->data.intval = CExpr_IntConstConvert(type, TYPE(&stunsignedlong), tmp->data.intval); - return tmp; - } - - if (type->size != 4) { - expr = makemonadicnode(expr, ETYPCON); - expr->rtype = TYPE(&stunsignedlong); - } - - expr = makemonadicnode(expr, ETYPCON); - expr->rtype = type; - expr->flags = flags; - return expr; - } - - if (IS_TYPE_POINTER(type)) { - if (IS_TYPE_POINTER(expr->rtype)) { - if (IS_TYPE_CLASS(TPTR_TARGET(expr->rtype)) && IS_TYPE_CLASS(TPTR_TARGET(type))) - expr = CExpr_SafeClassPointerCast(expr, TYPE_CLASS(TPTR_TARGET(expr->rtype)), TYPE_CLASS(TPTR_TARGET(type)), 1, 0); - - if (!ENODE_IS(expr, ETYPCON)) - expr = makemonadicnode(expr, ETYPCON); - - expr->rtype = type; - expr->flags = flags; - return expr; - } - - if (!IS_TYPE_INT(expr->rtype)) { - if (!IS_TYPE_ENUM(expr->rtype)) { - CError_Error(CErrorStr247, expr->rtype, ENODE_QUALS(expr), type, qual); - return expr; - } - expr = forceintegral(expr); - } - - if (expr->rtype->size != 4) { - if (!ENODE_IS(expr, EINTCONST)) - expr = makemonadicnode(expr, ETYPCON); - expr->rtype = TYPE(&stunsignedlong); - } - - expr = makemonadicnode(expr, ETYPCON); - expr->rtype = type; - expr->flags = flags; - return expr; - } - - if ((tmp = CodeGen_HandleTypeCast(expr, type, qual))) - return tmp; - - CError_Error(CErrorStr247, expr->rtype, ENODE_QUALS(expr), type, qual); - return nullnode(); -} - -static Boolean isvectorconst(ENode *node) { - if (ENODE_IS3(node, ECOMMA, EINTCONST, EFLOATCONST)) - return 1; - else - return 0; -} - -ENode *cast_expression(void) { - ENode *expr; - ENode *tmp; - ENodeList *args; - MWVector128 vec; - DeclInfo di; - - if (!(tk == '(' && islookaheaddeclaration())) - return unary_expression(); - tk = lex(); - - memclrw(&di, sizeof(DeclInfo)); - CParser_GetDeclSpecs(&di, 0); - scandeclarator(&di); - - if (tk != ')') - CError_ErrorSkip(CErrorStr115); - else - tk = lex(); - - if (di.name) - CError_Error(CErrorStr164); - - if (copts.altivec_model && tk == '(' && IS_TYPE_VECTOR(di.thetype)) { - tk = lex(); - expr = s_expression(); - if (tk != ')') - CError_ErrorSkip(CErrorStr115); - else - tk = lex(); - - if (CodeGen_CollapseVectorExpression(expr, &vec, di.thetype)) { - tmp = lalloc(sizeof(ENode)); - tmp->type = EVECTOR128CONST; - if ((tmp->cost = expr->cost) == 0) - tmp->cost = 1; - tmp->flags = ENODE_QUALS(expr); - tmp->rtype = di.thetype; - tmp->data.vector128val = vec; - } else { - tmp = makemonadicnode(expr, ETYPCON); - } - tmp->rtype = di.thetype; - tmp->flags = expr->flags; - return tmp; - } - - if (tk == '{' && (!copts.ANSIstrict || copts.c9x) && !IS_TYPE_VECTOR(di.thetype)) - return CInit_AutoObject(NULL, di.thetype, di.qual); - - expr = cast_expression(); - if (copts.cplusplus && (CTemplTool_IsTemplateArgumentDependentType(di.thetype) || - CTemplTool_IsTemplateArgumentDependentExpression(expr))) { - args = lalloc(sizeof(ENodeList)); - args->next = NULL; - args->node = expr; - return CExpr_TemplArgDepCast(di.thetype, di.qual, args); - } - - if (!IS_TYPE_REFERENCE(di.thetype)) - expr = pointer_generation(expr); - return do_typecast(expr, di.thetype, di.qual); -} - -static ENode *pm_expression(void) { - ENode *left; - ENode *right; - ENode *tmp; - Type *type; - UInt32 qual; - short flags; - Conversion conv; - - left = cast_expression(); -restart: - switch (tk) { - case TK_ARROW_STAR: - left = pointer_generation(left); - tk = lex(); - right = pointer_generation(cast_expression()); - - if (CExpr_CheckOperator(TK_ARROW_STAR, left, right, &conv)) { - CError_ASSERT(4457, left = conv.x0); - goto restart; - } - - if (!IS_TYPE_POINTER(left->rtype)) { - CError_Error(CErrorStr148); - return left; - } - - left = makemonadicnode(left, EINDIRECT); - left->rtype = TPTR_TARGET(left->rtype); - goto common_part; - case TK_DOT_STAR: - left = pointer_generation(left); - tk = lex(); - right = pointer_generation(cast_expression()); - if (!ENODE_IS(left, EINDIRECT)) { - CError_Error(CErrorStr142); - return left; - } - common_part: - if (!IS_TYPE_CLASS(left->rtype)) { - CError_Error(CErrorStr149); - return left; - } - if (!IS_TYPE_MEMBERPOINTER(right->rtype)) { - CError_Error(CErrorStr144); - return left; - } - if (left->rtype != TYPE_MEMBER_POINTER(right->rtype)->ty2) { - if (CClass_IsBaseClass(TYPE_CLASS(left->rtype), TYPE_CLASS(TYPE_MEMBER_POINTER(right->rtype)->ty2), NULL, 1, 1)) { - left->data.monadic = CClass_ClassPointerCast( - left->data.monadic, - TYPE_CLASS(left->rtype), - TYPE_CLASS(TYPE_MEMBER_POINTER(right->rtype)->ty2), - 0, 1, 1); - left->rtype = TYPE_MEMBER_POINTER(right->rtype)->ty2; - } else { - CError_Error(CErrorStr146); - return left; - } - } - type = CClass_CombineClassAccessQualifiers( - TYPE_MEMBER_POINTER(right->rtype)->ty1, - ENODE_QUALS(right), - left->flags, - &qual); - flags = qual; - if (!IS_TYPE_FUNC(type)) { - if (!ENODE_IS(right, EINTCONST)) { - if (!canadd(left->data.monadic, -1)) { - left->data.monadic = makediadicnode(left->data.monadic, nullnode(), EADD); - CInt64_SetLong(&left->data.monadic->data.diadic.right->data.intval, -1); - optimizecomm(left->data.monadic); - } - right->rtype = TYPE(&stunsignedlong); - left->data.monadic = makediadicnode(left->data.monadic, right, EADD); - optimizecomm(left->data.monadic); - } else { - right->data.intval = CInt64_Sub(right->data.intval, cint64_one); - if (!canadd2(left->data.monadic, right->data.intval)) { - right->rtype = TYPE(&stunsignedlong); - left->data.monadic = makediadicnode(left->data.monadic, right, EADD); - optimizecomm(left->data.monadic); - } - } - - if (IS_TYPE_BITFIELD(type)) { - left->data.monadic = makemonadicnode(left->data.monadic, EBITFIELD); - left->data.monadic->rtype = type; - left->rtype = TYPE_BITFIELD(type)->bitfieldtype; - } else { - left->rtype = type; - } - left->flags = flags; - left = checkreference(left); - goto restart; - } else { - CError_ASSERT(4535, ENODE_IS(right, EINDIRECT)); - tmp = lalloc(sizeof(ENode)); - tmp->type = EMFPOINTER; - tmp->cost = 4; - tmp->flags = 0; - tmp->rtype = &stvoid; - tmp->data.mfpointer.accessnode = left; - tmp->data.mfpointer.mfpointer = right; - return tmp; - } - default: - return left; - } -} - -ENode *CExpr_New_EMUL_Node(ENode *left, ENode *right) { - Conversion conv; - - if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) - return CTempl_MakeTemplDepExpr(left, EMUL, right); - - left = pointer_generation(left); - right = pointer_generation(right); - if (copts.cplusplus && CExpr_CheckOperator('*', left, right, &conv)) { - if (conv.x0) - return conv.x0; - CError_ASSERT(4566, left = conv.left); - CError_ASSERT(4567, right = conv.right); - } - - return makemultnode(left, right); -} - -ENode *CExpr_New_EDIV_Node(ENode *left, ENode *right, Boolean no_warning) { - Conversion conv; - - if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) - return CTempl_MakeTemplDepExpr(left, EDIV, right); - - left = pointer_generation(left); - right = pointer_generation(right); - if (copts.cplusplus && CExpr_CheckOperator('/', left, right, &conv)) { - if (conv.x0) - return conv.x0; - CError_ASSERT(4592, left = conv.left); - CError_ASSERT(4593, right = conv.right); - } - - return makedivnode(left, right, no_warning); -} - -ENode *CExpr_New_EMODULO_Node(ENode *left, ENode *right, Boolean no_warning) { - Conversion conv; - - if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) - return CTempl_MakeTemplDepExpr(left, EMODULO, right); - - left = pointer_generation(left); - right = pointer_generation(right); - if (copts.cplusplus && CExpr_CheckOperator('%', left, right, &conv)) { - if (conv.x0) - return conv.x0; - CError_ASSERT(4618, left = conv.left); - CError_ASSERT(4619, right = conv.right); - } - - left = integralpromote(left); - right = integralpromote(right); - CExpr_ArithmeticConversion(&left, &right); - - if (iszero(right)) { - if (!no_warning) - CError_Warning(CErrorStr139); - return left; - } - - if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { - left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, '%', right->data.intval); - return left; - } - - if (iszero(left)) - return makediadicnode(right, left, ECOMMA); - - if (CExpr_IsOne(right)) { - right = nullnode(); - right->rtype = left->rtype; - return makediadicnode(left, right, ECOMMA); - } - - return makediadicnode(left, right, EMODULO); -} - -ENode *CExpr_New_EADD_Node(ENode *left, ENode *right) { - Conversion conv; - - if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) - return CTempl_MakeTemplDepExpr(left, EADD, right); - - left = pointer_generation(left); - right = pointer_generation(right); - if (copts.cplusplus && CExpr_CheckOperator('+', left, right, &conv)) { - if (conv.x0) - return conv.x0; - CError_ASSERT(4665, left = conv.left); - CError_ASSERT(4666, right = conv.right); - } - - return makeaddnode(left, right); -} - -ENode *CExpr_New_ESUB_Node(ENode *left, ENode *right) { - Conversion conv; - - if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) - return CTempl_MakeTemplDepExpr(left, ESUB, right); - - left = pointer_generation(left); - right = pointer_generation(right); - if (copts.cplusplus && CExpr_CheckOperator('-', left, right, &conv)) { - if (conv.x0) - return conv.x0; - CError_ASSERT(4690, left = conv.left); - CError_ASSERT(4691, right = conv.right); - } - - return makesubnode(left, right); -} - -ENode *CExpr_New_ESHL_Node(ENode *left, ENode *right) { - Conversion conv; - - if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) - return CTempl_MakeTemplDepExpr(left, ESHL, right); - - left = pointer_generation(left); - right = pointer_generation(right); - if (copts.cplusplus && CExpr_CheckOperator(TK_SHL, left, right, &conv)) { - if (conv.x0) - return conv.x0; - CError_ASSERT(4715, left = conv.left); - CError_ASSERT(4716, right = conv.right); - } - - left = integralpromote(left); - right = integralpromote(right); - - if (iszero(left) || iszero(right)) { - return left; - } - - if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { - left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, TK_SHL, right->data.intval); - return left; - } - - return makediadicnode(left, right, ESHL); -} - -ENode *CExpr_New_ESHR_Node(ENode *left, ENode *right) { - Conversion conv; - - if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) - return CTempl_MakeTemplDepExpr(left, ESHR, right); - - left = pointer_generation(left); - right = pointer_generation(right); - if (copts.cplusplus && CExpr_CheckOperator(TK_SHR, left, right, &conv)) { - if (conv.x0) - return conv.x0; - CError_ASSERT(4752, left = conv.left); - CError_ASSERT(4753, right = conv.right); - } - - left = integralpromote(left); - right = integralpromote(right); - - if (iszero(left) || iszero(right)) { - return left; - } - - if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { - left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, TK_SHR, right->data.intval); - return left; - } - - return makediadicnode(left, right, ESHR); -} - -static ENode *pointercompare(ENodeType nt, ENode *left, ENode *right) { - Type *ltype; - Type *rtype; - - ltype = left->rtype; - rtype = right->rtype; - if (IS_TYPE_POINTER_ONLY(ltype) && IS_TYPE_POINTER_ONLY(rtype)) { - ltype = TPTR_TARGET(left->rtype); - rtype = TPTR_TARGET(right->rtype); - if (IS_TYPE_CLASS(ltype) && IS_TYPE_CLASS(rtype)) { - if (ltype != rtype) { - if (ltype == TPTR_TARGET(left->rtype)) { - if (CClass_IsBaseClass(TYPE_CLASS(ltype), TYPE_CLASS(rtype), NULL, 0, 1)) { - left = CExpr_SafeClassPointerCast(left, TYPE_CLASS(ltype), TYPE_CLASS(rtype), 0, 1); - } else if (CClass_IsBaseClass(TYPE_CLASS(rtype), TYPE_CLASS(ltype), NULL, 0, 1)) { - right = CExpr_SafeClassPointerCast(right, TYPE_CLASS(rtype), TYPE_CLASS(ltype), 0, 1); - } else { - CError_Error(CErrorStr245, left->rtype, ENODE_QUALS(left), right->rtype, ENODE_QUALS(right)); - } - } else { - CError_Error(CErrorStr245, left->rtype, ENODE_QUALS(left), right->rtype, ENODE_QUALS(right)); - } - } - } else if (!is_typeequal(left->rtype, right->rtype)) { - if (!copts.objective_c || !CObjC_IsCompatibleType(left->rtype, right->rtype)) { - CError_Error(CErrorStr245, left->rtype, ENODE_QUALS(left), right->rtype, ENODE_QUALS(right)); - } - } - } else if (nt == EEQU || nt == ENOTEQU) { - if (IS_TYPE_INT(ltype)) { - if (!(ENODE_IS(left, EINTCONST) && CInt64_IsZero(&left->data.intval))) - CError_Error(CErrorStr144); - CError_ASSERT(4847, IS_TYPE_POINTER_ONLY(rtype)); - left->rtype = TYPE(&stunsignedlong); - } else if (IS_TYPE_INT(rtype)) { - if (!(ENODE_IS(right, EINTCONST) && CInt64_IsZero(&right->data.intval))) - CError_Error(CErrorStr144); - CError_ASSERT(4855, IS_TYPE_POINTER_ONLY(ltype)); - right->rtype = TYPE(&stunsignedlong); - } else if (!is_typeequal(ltype, rtype)) { - CError_Error(CErrorStr245, left->rtype, ENODE_QUALS(left), right->rtype, ENODE_QUALS(right)); - } - } else { - if (!is_typeequal(ltype, rtype)) - CError_Error(CErrorStr245, left->rtype, ENODE_QUALS(left), right->rtype, ENODE_QUALS(right)); - } - - return logicalexpression(makediadicnode(left, right, nt)); -} - -static ENode *unsigncheck(ENode *expr, Boolean flag1, Boolean flag2) { - if (is_unsigned(expr->data.diadic.left->rtype)) { - if (ENODE_IS(expr->data.diadic.left, EINTCONST) && CInt64_IsZero(&expr->data.diadic.left->data.intval)) { - flag1 = !flag1; - } else if (!(ENODE_IS(expr->data.diadic.right, EINTCONST) && CInt64_IsZero(&expr->data.diadic.right->data.intval))) { - return logicalexpression(expr); - } - - if (flag1 && flag2) { - expr->type = EEQU; - return logicalexpression(expr); - } - if (!flag1 && !flag2) { - expr->type = ENOTEQU; - return logicalexpression(expr); - } - return CExpr_ConstResult(logicalexpression(expr), !flag1); - } - return logicalexpression(expr); -} - -ENode *CExpr_New_ELESS_Node(ENode *left, ENode *right) { - Conversion conv; - - if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) - return CTempl_MakeTemplDepExpr(left, ELESS, right); - - left = pointer_generation(left); - right = pointer_generation(right); - if (copts.cplusplus && CExpr_CheckOperator('<', left, right, &conv)) { - if (conv.x0) - return conv.x0; - CError_ASSERT(4929, left = conv.left); - CError_ASSERT(4930, right = conv.right); - } - - if (IS_TYPE_POINTER(left->rtype) || IS_TYPE_POINTER(right->rtype)) - return pointercompare(ELESS, left, right); - - CExpr_CompareConvert(&left, "<", &right, 0); - if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { - left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, '<', right->data.intval); - left->rtype = CParser_GetBoolType(); - } else if (ENODE_IS(left, EFLOATCONST) && ENODE_IS(right, EFLOATCONST)) { - CInt64_SetLong(&left->data.intval, CMach_CalcFloatDiadicBool(left->rtype, left->data.floatval, '<', right->data.floatval)); - left->type = EINTCONST; - left->rtype = CParser_GetBoolType(); - } else { - left = unsigncheck(makediadicnode(left, right, ELESS), 1, 0); - } - - return left; -} - -ENode *CExpr_New_ELESSEQU_Node(ENode *left, ENode *right) { - Conversion conv; - - if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) - return CTempl_MakeTemplDepExpr(left, ELESSEQU, right); - - left = pointer_generation(left); - right = pointer_generation(right); - if (copts.cplusplus && CExpr_CheckOperator(TK_LESS_EQUAL, left, right, &conv)) { - if (conv.x0) - return conv.x0; - CError_ASSERT(4976, left = conv.left); - CError_ASSERT(4977, right = conv.right); - } - - if (IS_TYPE_POINTER(left->rtype) || IS_TYPE_POINTER(right->rtype)) - return pointercompare(ELESSEQU, left, right); - - CExpr_CompareConvert(&left, "<=", &right, 0); - if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { - left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, TK_LESS_EQUAL, right->data.intval); - left->rtype = CParser_GetBoolType(); - } else if (ENODE_IS(left, EFLOATCONST) && ENODE_IS(right, EFLOATCONST)) { - CInt64_SetLong(&left->data.intval, CMach_CalcFloatDiadicBool(left->rtype, left->data.floatval, TK_LESS_EQUAL, right->data.floatval)); - left->type = EINTCONST; - left->rtype = CParser_GetBoolType(); - } else { - left = unsigncheck(makediadicnode(left, right, ELESSEQU), 1, 1); - } - - return left; -} - -ENode *CExpr_New_EGREATER_Node(ENode *left, ENode *right) { - Conversion conv; - - if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) - return CTempl_MakeTemplDepExpr(left, EGREATER, right); - - left = pointer_generation(left); - right = pointer_generation(right); - if (copts.cplusplus && CExpr_CheckOperator('>', left, right, &conv)) { - if (conv.x0) - return conv.x0; - CError_ASSERT(5023, left = conv.left); - CError_ASSERT(5024, right = conv.right); - } - - if (IS_TYPE_POINTER(left->rtype) || IS_TYPE_POINTER(right->rtype)) - return pointercompare(EGREATER, left, right); - - CExpr_CompareConvert(&left, ">", &right, 0); - if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { - left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, '>', right->data.intval); - left->rtype = CParser_GetBoolType(); - } else if (ENODE_IS(left, EFLOATCONST) && ENODE_IS(right, EFLOATCONST)) { - CInt64_SetLong(&left->data.intval, CMach_CalcFloatDiadicBool(left->rtype, left->data.floatval, '>', right->data.floatval)); - left->type = EINTCONST; - left->rtype = CParser_GetBoolType(); - } else { - left = unsigncheck(makediadicnode(left, right, EGREATER), 0, 0); - } - - return left; -} - -ENode *CExpr_New_EGREATEREQU_Node(ENode *left, ENode *right) { - Conversion conv; - - if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) - return CTempl_MakeTemplDepExpr(left, EGREATEREQU, right); - - left = pointer_generation(left); - right = pointer_generation(right); - if (copts.cplusplus && CExpr_CheckOperator(TK_GREATER_EQUAL, left, right, &conv)) { - if (conv.x0) - return conv.x0; - CError_ASSERT(5070, left = conv.left); - CError_ASSERT(5071, right = conv.right); - } - - if (IS_TYPE_POINTER(left->rtype) || IS_TYPE_POINTER(right->rtype)) - return pointercompare(EGREATEREQU, left, right); - - CExpr_CompareConvert(&left, ">=", &right, 0); - if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { - left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, TK_GREATER_EQUAL, right->data.intval); - left->rtype = CParser_GetBoolType(); - } else if (ENODE_IS(left, EFLOATCONST) && ENODE_IS(right, EFLOATCONST)) { - CInt64_SetLong(&left->data.intval, CMach_CalcFloatDiadicBool(left->rtype, left->data.floatval, TK_GREATER_EQUAL, right->data.floatval)); - left->type = EINTCONST; - left->rtype = CParser_GetBoolType(); - } else { - left = unsigncheck(makediadicnode(left, right, EGREATEREQU), 0, 1); - } - - return left; -} - -ENode *memberpointercompare(ENodeType nt, ENode *left, ENode *right) { - Object *func; - ENodeList *arg; - - if (!IS_TYPE_MEMBERPOINTER(left->rtype)) { - if (!(IS_TYPE_INT(left->rtype) && ENODE_IS(left, EINTCONST) && CInt64_IsZero(&left->data.intval))) { - CError_Error(CErrorStr144); - return nullnode(); - } - } else if (!IS_TYPE_MEMBERPOINTER(right->rtype)) { - if (!(IS_TYPE_INT(right->rtype) && ENODE_IS(right, EINTCONST) && CInt64_IsZero(&right->data.intval))) { - CError_Error(CErrorStr144); - return nullnode(); - } - } else if (!is_typeequal(left->rtype, right->rtype)) { - left = PointerToMemberCast(left, TYPE_MEMBER_POINTER(left->rtype), TYPE_MEMBER_POINTER(right->rtype), 1); - } - - if ((ENODE_IS(left, EINTCONST) || !IS_TYPE_FUNC(TYPE_MEMBER_POINTER(left->rtype)->ty1)) && (ENODE_IS(right, EINTCONST) || !IS_TYPE_FUNC(TYPE_MEMBER_POINTER(right->rtype)->ty1))) { - left->rtype = TYPE(&stunsignedlong); - right->rtype = TYPE(&stunsignedlong); - return logicalexpression(makediadicnode(left, right, nt)); - } - - arg = lalloc(sizeof(ENodeList)); - if (ENODE_IS(left, EINTCONST) || ENODE_IS(right, EINTCONST)) { - func = rt_ptmf_test; - if (ENODE_IS(left, EINTCONST)) - arg->node = getnodeaddress(right, 0); - else - arg->node = getnodeaddress(left, 0); - arg->next = NULL; - } else { - func = rt_ptmf_cmpr; - arg->next = lalloc(sizeof(ENodeList)); - arg->node = getnodeaddress(left, 0); - arg->next->node = getnodeaddress(right, 0); - arg->next->next = NULL; - } - - left = lalloc(sizeof(ENode)); - left->type = EFUNCCALL; - left->rtype = TYPE(&stsignedlong); - left->cost = 4; - left->data.funccall.funcref = create_objectrefnode(func); - left->data.funccall.args = arg; - left->data.funccall.functype = TYPE_FUNC(func->type); - left->flags = TYPE_FUNC(func->type)->qual & ENODE_FLAG_QUALS; - - if (nt == EEQU) - left = makemonadicnode(left, ELOGNOT); - - return left; -} - -ENode *CExpr_New_EEQU_Node(ENode *left, ENode *right) { - Conversion conv; - - if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) - return CTempl_MakeTemplDepExpr(left, EEQU, right); - - left = pointer_generation(left); - right = pointer_generation(right); - if (copts.cplusplus && CExpr_CheckOperator(TK_LOGICAL_EQ, left, right, &conv)) { - if (conv.x0) - return conv.x0; - CError_ASSERT(5201, left = conv.left); - CError_ASSERT(5202, right = conv.right); - } - - if (IS_TYPE_POINTER(left->rtype) || IS_TYPE_POINTER(right->rtype)) - return pointercompare(EEQU, left, right); - if (IS_TYPE_MEMBERPOINTER(left->rtype) || IS_TYPE_MEMBERPOINTER(right->rtype)) - return memberpointercompare(EEQU, left, right); - - CExpr_CompareConvert(&left, "==", &right, 1); - if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { - left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, TK_LOGICAL_EQ, right->data.intval); - left->rtype = CParser_GetBoolType(); - } else if (ENODE_IS(left, EFLOATCONST) && ENODE_IS(right, EFLOATCONST)) { - left->type = EINTCONST; - CInt64_SetLong(&left->data.intval, CMach_CalcFloatDiadicBool(left->rtype, left->data.floatval, TK_LOGICAL_EQ, right->data.floatval)); - left->type = EINTCONST; - left->rtype = CParser_GetBoolType(); - } else { - left = makediadicnode(left, right, EEQU); - optimizecomm(left); - } - - return logicalexpression(left); -} - -ENode *CExpr_New_ENOTEQU_Node(ENode *left, ENode *right) { - Conversion conv; - - if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) - return CTempl_MakeTemplDepExpr(left, ENOTEQU, right); - - left = pointer_generation(left); - right = pointer_generation(right); - if (copts.cplusplus && CExpr_CheckOperator(TK_LOGICAL_NE, left, right, &conv)) { - if (conv.x0) - return conv.x0; - CError_ASSERT(5261, left = conv.left); - CError_ASSERT(5262, right = conv.right); - } - - if (IS_TYPE_POINTER(left->rtype) || IS_TYPE_POINTER(right->rtype)) - return pointercompare(ENOTEQU, left, right); - if (IS_TYPE_MEMBERPOINTER(left->rtype) || IS_TYPE_MEMBERPOINTER(right->rtype)) - return memberpointercompare(ENOTEQU, left, right); - - CExpr_CompareConvert(&left, "!=", &right, 1); - if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { - left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, TK_LOGICAL_NE, right->data.intval); - left->rtype = CParser_GetBoolType(); - } else if (ENODE_IS(left, EFLOATCONST) && ENODE_IS(right, EFLOATCONST)) { - CInt64_SetLong(&left->data.intval, CMach_CalcFloatDiadicBool(left->rtype, left->data.floatval, TK_LOGICAL_NE, right->data.floatval)); - left->type = EINTCONST; - left->rtype = CParser_GetBoolType(); - } else { - left = makediadicnode(left, right, ENOTEQU); - optimizecomm(left); - } - - return logicalexpression(left); -} - -ENode *CExpr_New_EAND_Node(ENode *left, ENode *right) { - Conversion conv; - - if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) - return CTempl_MakeTemplDepExpr(left, EAND, right); - - left = pointer_generation(left); - right = pointer_generation(right); - if (copts.cplusplus && CExpr_CheckOperator('&', left, right, &conv)) { - if (conv.x0) - return conv.x0; - CError_ASSERT(5321, left = conv.left); - CError_ASSERT(5322, right = conv.right); - } - - left = integralpromote(left); - right = integralpromote(right); - CExpr_ArithmeticConversion(&left, &right); - - if (iszero(left) || CExpr_AllBitsSet(right)) - return left; - if (iszero(right) || CExpr_AllBitsSet(left)) - return right; - - if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { - left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, '&', right->data.intval); - return left; - } - - left = makediadicnode(left, right, EAND); - optimizecomm(left); - return left; -} - -ENode *CExpr_New_EXOR_Node(ENode *left, ENode *right) { - Conversion conv; - - if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) - return CTempl_MakeTemplDepExpr(left, EXOR, right); - - left = pointer_generation(left); - right = pointer_generation(right); - if (copts.cplusplus && CExpr_CheckOperator('^', left, right, &conv)) { - if (conv.x0) - return conv.x0; - CError_ASSERT(5360, left = conv.left); - CError_ASSERT(5361, right = conv.right); - } - - left = integralpromote(left); - right = integralpromote(right); - CExpr_ArithmeticConversion(&left, &right); - - if (iszero(right)) - return left; - if (iszero(left)) - return right; - - if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { - left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, '^', right->data.intval); - return left; - } - - left = makediadicnode(left, right, EXOR); - optimizecomm(left); - return left; -} - -ENode *CExpr_New_EOR_Node(ENode *left, ENode *right) { - Conversion conv; - - if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) - return CTempl_MakeTemplDepExpr(left, EOR, right); - - left = pointer_generation(left); - right = pointer_generation(right); - if (copts.cplusplus && CExpr_CheckOperator('|', left, right, &conv)) { - if (conv.x0) - return conv.x0; - CError_ASSERT(5399, left = conv.left); - CError_ASSERT(5400, right = conv.right); - } - - left = integralpromote(left); - right = integralpromote(right); - CExpr_ArithmeticConversion(&left, &right); - - if (iszero(right) || CExpr_AllBitsSet(left)) - return left; - if (iszero(left) || CExpr_AllBitsSet(right)) - return right; - - if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { - left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, '|', right->data.intval); - return left; - } - - left = makediadicnode(left, right, EOR); - optimizecomm(left); - return left; -} - -ENode *CExpr_New_ELAND_Node(ENode *left, ENode *right) { - Conversion conv; - - if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) - return CTempl_MakeTemplDepExpr(left, ELAND, right); - - left = pointer_generation(left); - right = pointer_generation(right); - if (copts.cplusplus && CExpr_CheckOperator(TK_LOGICAL_AND, left, right, &conv)) { - if (conv.x0) - return conv.x0; - CError_ASSERT(5438, left = conv.left); - CError_ASSERT(5439, right = conv.right); - } - - switch (left->rtype->type) { - case TYPEINT: - case TYPEFLOAT: - case TYPEPOINTER: - case TYPEARRAY: - break; - case TYPEENUM: - case TYPEMEMBERPOINTER: - left = CExpr_ConvertToCondition(left); - break; - default: - CError_Error(CErrorStr144); - left = nullnode(); - } - switch (right->rtype->type) { - case TYPEINT: - case TYPEFLOAT: - case TYPEPOINTER: - case TYPEARRAY: - break; - case TYPEENUM: - case TYPEMEMBERPOINTER: - right = CExpr_ConvertToCondition(right); - break; - default: - CError_Error(CErrorStr144); - right = nullnode(); - } - - if (iszero(left)) { - left->type = EINTCONST; - left->rtype = CParser_GetBoolType(); - CInt64_SetLong(&left->data.intval, 0); - return left; - } - - if (isnotzero(left)) { - if (iszero(right)) { - left->type = EINTCONST; - left->rtype = CParser_GetBoolType(); - CInt64_SetLong(&left->data.intval, 0); - return left; - } else if (isnotzero(right)) { - left->type = EINTCONST; - left->rtype = CParser_GetBoolType(); - CInt64_SetLong(&left->data.intval, 1); - return left; - } else { - left = makemonadicnode(right, ELOGNOT); - left->rtype = CParser_GetBoolType(); - return makemonadicnode(left, ELOGNOT); - } - } else { - if (isnotzero(right)) { - left = makemonadicnode(left, ELOGNOT); - left->rtype = CParser_GetBoolType(); - return makemonadicnode(left, ELOGNOT); - } else if (iszero(right)) { - right->type = EINTCONST; - right->rtype = CParser_GetBoolType(); - CInt64_SetLong(&right->data.intval, 0); - return makecommaexpression(left, right); - } else { - left = makediadicnode(left, right, ELAND); - left->rtype = CParser_GetBoolType(); - return left; - } - } -} - -ENode *CExpr_New_ELOR_Node(ENode *left, ENode *right) { - Conversion conv; - - if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) - return CTempl_MakeTemplDepExpr(left, ELOR, right); - - left = pointer_generation(left); - right = pointer_generation(right); - if (copts.cplusplus && CExpr_CheckOperator(TK_LOGICAL_OR, left, right, &conv)) { - if (conv.x0) - return conv.x0; - CError_ASSERT(5543, left = conv.left); - CError_ASSERT(5544, right = conv.right); - } - - switch (left->rtype->type) { - case TYPEINT: - case TYPEFLOAT: - case TYPEPOINTER: - case TYPEARRAY: - break; - case TYPEENUM: - case TYPEMEMBERPOINTER: - left = CExpr_ConvertToCondition(left); - break; - default: - CError_Error(CErrorStr144); - left = nullnode(); - } - switch (right->rtype->type) { - case TYPEINT: - case TYPEFLOAT: - case TYPEPOINTER: - case TYPEARRAY: - break; - case TYPEENUM: - case TYPEMEMBERPOINTER: - right = CExpr_ConvertToCondition(right); - break; - default: - CError_Error(CErrorStr144); - right = nullnode(); - } - - if (isnotzero(left)) { - left->type = EINTCONST; - left->rtype = CParser_GetBoolType(); - CInt64_SetLong(&left->data.intval, 1); - return left; - } - - if (iszero(left)) { - if (iszero(right)) { - left->type = EINTCONST; - left->rtype = CParser_GetBoolType(); - CInt64_SetLong(&left->data.intval, 0); - return left; - } else if (isnotzero(right)) { - left->type = EINTCONST; - left->rtype = CParser_GetBoolType(); - CInt64_SetLong(&left->data.intval, 1); - return left; - } else { - left = makemonadicnode(right, ELOGNOT); - left->rtype = CParser_GetBoolType(); - return makemonadicnode(left, ELOGNOT); - } - } else { - if (isnotzero(right)) { - right->type = EINTCONST; - right->rtype = CParser_GetBoolType(); - CInt64_SetLong(&right->data.intval, 1); - } else if (iszero(right)) { - left = makemonadicnode(left, ELOGNOT); - left->rtype = CParser_GetBoolType(); - return makemonadicnode(left, ELOGNOT); - } - left = makediadicnode(left, right, ELOR); - left->rtype = CParser_GetBoolType(); - return left; - } -} - -ENode *CExpr_NewDyadicNode(ENode *left, ENodeType nt, ENode *right) { - switch (nt) { - default: - CError_FATAL(5642); - case EADD: return CExpr_New_EADD_Node(left, right); - case ESUB: return CExpr_New_ESUB_Node(left, right); - case EMUL: return CExpr_New_EMUL_Node(left, right); - case EDIV: return CExpr_New_EDIV_Node(left, right, 1); - case EMODULO: return CExpr_New_EMODULO_Node(left, right, 1); - case EAND: return CExpr_New_EAND_Node(left, right); - case EXOR: return CExpr_New_EXOR_Node(left, right); - case EOR: return CExpr_New_EOR_Node(left, right); - case ESHL: return CExpr_New_ESHL_Node(left, right); - case ESHR: return CExpr_New_ESHR_Node(left, right); - case ELESS: return CExpr_New_ELESS_Node(left, right); - case EGREATER: return CExpr_New_EGREATER_Node(left, right); - case ELESSEQU: return CExpr_New_ELESSEQU_Node(left, right); - case EGREATEREQU: return CExpr_New_EGREATEREQU_Node(left, right); - case EEQU: return CExpr_New_EEQU_Node(left, right); - case ENOTEQU: return CExpr_New_ENOTEQU_Node(left, right); - case ELAND: return CExpr_New_ELAND_Node(left, right); - case ELOR: return CExpr_New_ELOR_Node(left, right); - } -} - -typedef struct DyadicInfo { - ENodeType t; - UInt8 prec; -} DyadicInfo; - -static Boolean CExpr_GetDyadicInfo(short token, DyadicInfo *info) { - switch (token) { - case '*': - info->t = EMUL; - info->prec = 20; - return 1; - case '/': - info->t = EDIV; - info->prec = 20; - return 1; - case '%': - info->t = EMODULO; - info->prec = 20; - return 1; - case '+': - info->t = EADD; - info->prec = 19; - return 1; - case '-': - info->t = ESUB; - info->prec = 19; - return 1; - case TK_SHL: - info->t = ESHL; - info->prec = 18; - return 1; - case TK_SHR: - info->t = ESHR; - info->prec = 18; - return 1; - case '<': - info->t = ELESS; - info->prec = 17; - return 1; - case TK_LESS_EQUAL: - info->t = ELESSEQU; - info->prec = 17; - return 1; - case '>': - if (disallowgreaterthan) - return 0; - info->t = EGREATER; - info->prec = 17; - return 1; - case TK_GREATER_EQUAL: - info->t = EGREATEREQU; - info->prec = 17; - return 1; - case TK_LOGICAL_EQ: - info->t = EEQU; - info->prec = 16; - return 1; - case TK_LOGICAL_NE: - info->t = ENOTEQU; - info->prec = 16; - return 1; - case '&': - info->t = EAND; - info->prec = 15; - return 1; - case '^': - info->t = EXOR; - info->prec = 14; - return 1; - case '|': - info->t = EOR; - info->prec = 13; - return 1; - case TK_LOGICAL_AND: - info->t = ELAND; - info->prec = 12; - return 1; - case TK_LOGICAL_OR: - info->t = ELOR; - info->prec = 11; - return 1; - default: - return 0; - } -} - -static ENode *CExpr_ParseDyadicExpression(ENode *left, UInt8 prec, Boolean no_warning) { - ENode *right; - Boolean is_eland_or_elor; - Boolean save_dgt; - Boolean cont; - DyadicInfo left_info; - DyadicInfo right_info; - - save_dgt = disallowgreaterthan; - if (!left) { - disallowgreaterthan = 0; - left = pm_expression(); - disallowgreaterthan = save_dgt; - } - - do { - if (!CExpr_GetDyadicInfo(tk, &left_info)) - return left; - - switch (left_info.t) { - case ELAND: - CExpr_CheckUnwantedAssignment(left); - if (iszero(left)) - no_warning = 1; - is_eland_or_elor = 1; - break; - case ELOR: - CExpr_CheckUnwantedAssignment(left); - if (isnotzero(left)) - no_warning = 1; - is_eland_or_elor = 1; - break; - default: - is_eland_or_elor = 0; - } - - tk = lex(); - disallowgreaterthan = 0; - right = pm_expression(); - disallowgreaterthan = save_dgt; - inner_loop: - if (CExpr_GetDyadicInfo(tk, &right_info)) { - if (left_info.prec >= right_info.prec) { - cont = (prec >= right_info.prec); - } else { - right = CExpr_ParseDyadicExpression(right, left_info.prec, no_warning); - goto inner_loop; - } - } else { - cont = 1; - } - - if (is_eland_or_elor) - CExpr_CheckUnwantedAssignment(right); - - switch (left_info.t) { - case EDIV: - left = CExpr_New_EDIV_Node(left, right, no_warning); - break; - case EMODULO: - left = CExpr_New_EMODULO_Node(left, right, no_warning); - break; - default: - left = CExpr_NewDyadicNode(left, left_info.t, right); - } - } while (!cont); - - return left; -} - -static Boolean CExpr_IsBlockMoveType(Type *type) { - switch (type->type) { - case TYPESTRUCT: - case TYPECLASS: - return 1; - case TYPEMEMBERPOINTER: - return type->size != 4; - default: - return 0; - } -} - -ENode *CExpr_New_ECOND_Node(ENode *cond, ENode *expr1, ENode *expr2) { - ENode *result; - ENodeList *args; - short cost; - Conversion conv; - - cond = CExpr_ConvertToCondition(pointer_generation(cond)); - expr1 = pointer_generation(expr1); - expr2 = pointer_generation(expr2); - - if (!IS_TYPE_INT_OR_FLOAT(cond->rtype) && !IS_TYPE_POINTER_ONLY(cond->rtype)) { - CError_Error(CErrorStr144); - return nullnode(); - } - - cost = cond->cost + 1; - if (expr1->cost > expr2->cost) - cost += expr1->cost; - else - cost += expr2->cost; - if (expr2->cost > cost) - cost = expr2->cost; - if (cost > 200) - cost = 200; - - result = CExpr_NewENode(ECOND); - result->cost = cost; - result->rtype = expr1->rtype; - result->flags = expr1->flags | expr2->flags; - result->data.cond.cond = cond; - if (ENODE_IS(expr1, EFUNCCALL) && expr1->rtype == &stvoid && (expr1->flags & ENODE_FLAG_VOLATILE) != 0) { - result->rtype = expr2->rtype; - result->flags = expr2->flags; - result->data.cond.expr1 = expr1; - result->data.cond.expr2 = expr2; - return result; - } - if (ENODE_IS(expr2, EFUNCCALL) && expr2->rtype == &stvoid && (expr2->flags & ENODE_FLAG_VOLATILE) != 0) { - result->rtype = expr1->rtype; - result->flags = expr1->flags; - result->data.cond.expr1 = expr1; - result->data.cond.expr2 = expr2; - return result; - } - - if ( - ENODE_IS(expr1, EINDIRECT) && - ENODE_IS(expr2, EINDIRECT) && - is_typesame(expr1->rtype, expr2->rtype) && - ENODE_QUALS(expr1) == ENODE_QUALS(expr2) && - CExpr_IsBlockMoveType(expr1->rtype) && - !ENODE_IS(expr1->data.monadic, EBITFIELD) && - !ENODE_IS(expr2->data.monadic, EBITFIELD) - ) { - if (isnotzero(cond)) - return expr1; - if (iszero(cond)) - return expr2; - result->data.cond.expr1 = getnodeaddress(expr1, 0); - result->data.cond.expr2 = getnodeaddress(expr2, 0); - result->rtype = result->data.cond.expr1->rtype; - result = makemonadicnode(result, EINDIRECT); - result->rtype = TPTR_TARGET(result->rtype); - return result; - } - - if ((IS_TYPE_CLASS(expr1->rtype) || IS_TYPE_CLASS(expr2->rtype)) && !is_typesame(expr1->rtype, expr2->rtype)) { - if (!copts.old_argmatch) { - if (CExpr_CondOperatorMatch(expr1, expr2, &conv)) { - CError_ASSERT(6246, !conv.x0); - expr1 = conv.left; - expr2 = conv.right; - } else if (CExpr_CanImplicitlyConvert(expr1, expr2->rtype, ENODE_QUALS(expr2))) { - if (CExpr_CanImplicitlyConvert(expr2, expr1->rtype, ENODE_QUALS(expr1))) - CError_Error(CErrorStr188); - expr1 = CExpr_Convert(expr1, expr2->rtype, ENODE_QUALS(expr2), 0, 1); - } else if (CExpr_CanImplicitlyConvert(expr2, expr1->rtype, ENODE_QUALS(expr1))) { - expr2 = CExpr_Convert(expr2, expr1->rtype, ENODE_QUALS(expr1), 0, 1); - } else { - goto failed; - } - - result->rtype = expr1->rtype; - } else { - args = lalloc(sizeof(ENodeList)); - args->node = expr1; - args->next = lalloc(sizeof(ENodeList)); - args->next->node = expr2; - args->next->next = NULL; - - if (CExpr_CheckOperatorConversion(':', expr1, expr2, args, &conv)) { - CError_ASSERT(6274, !conv.x0); - expr1 = conv.left; - expr2 = conv.right; - } - - result->rtype = expr1->rtype; - } - } - - switch (expr1->rtype->type) { - case TYPEENUM: - if (expr1->rtype == expr2->rtype) - break; - expr1 = forceintegral(expr1); - case TYPEINT: - if (IS_TYPE_POINTER_ONLY(expr2->rtype) || IS_TYPE_MEMBERPOINTER(expr2->rtype)) { - expr1 = CExpr_Convert(expr1, expr2->rtype, ENODE_QUALS(expr2), 0, 1); - result->rtype = expr2->rtype; - break; - } - case TYPEFLOAT: - if (expr1->rtype != expr2->rtype) { - CExpr_ArithmeticConversion(&expr1, &expr2); - result->rtype = expr1->rtype; - } - break; - case TYPEPOINTER: - if (ENODE_IS(expr2, EINTCONST) && CInt64_IsZero(&expr2->data.intval)) { - expr2->rtype = TYPE(&stunsignedlong); - break; - } - if (IS_TYPE_POINTER_ONLY(expr2->rtype)) { - if (IS_TYPE_CLASS(TPTR_TARGET(expr1->rtype)) && IS_TYPE_CLASS(TPTR_TARGET(expr2->rtype))) { - if (TPTR_TARGET(expr1->rtype) != TPTR_TARGET(expr2->rtype)) { - if (CClass_IsBaseClass(TYPE_CLASS(TPTR_TARGET(expr1->rtype)), TYPE_CLASS(TPTR_TARGET(expr2->rtype)), NULL, 0, 1)) { - expr1 = CExpr_SafeClassPointerCast( - expr1, - TYPE_CLASS(TPTR_TARGET(expr1->rtype)), - TYPE_CLASS(TPTR_TARGET(expr2->rtype)), - 0, 1); - expr1->rtype = expr2->rtype; - } else if (CClass_IsBaseClass(TYPE_CLASS(TPTR_TARGET(expr2->rtype)), TYPE_CLASS(TPTR_TARGET(expr1->rtype)), NULL, 0, 1)) { - expr2 = CExpr_SafeClassPointerCast( - expr2, - TYPE_CLASS(TPTR_TARGET(expr2->rtype)), - TYPE_CLASS(TPTR_TARGET(expr1->rtype)), - 0, 1); - expr2->rtype = expr1->rtype; - } else { - goto failed; - } - } - result->rtype = expr1->rtype; - break; - } - if (TPTR_TARGET(expr2->rtype) == &stvoid) - result->rtype = expr2->rtype; - } - if (!is_typeequal(expr1->rtype, expr2->rtype)) { - if (!copts.objective_c) - goto failed; - if (!CObjC_IsCompatibleType(expr1->rtype, expr2->rtype)) - goto failed; - expr1->rtype = expr2->rtype = CObjC_GetObjCType_id(1); - } - break; - case TYPEVOID: - if (!is_typeequal(expr1->rtype, expr2->rtype)) - goto failed; - break; - case TYPESTRUCT: - case TYPECLASS: - if (!is_typeequal(expr1->rtype, expr2->rtype)) - goto failed; - result->rtype = expr1->rtype; - break; - case TYPEMEMBERPOINTER: - if (IS_TYPE_MEMBERPOINTER(expr2->rtype) && TYPE_MEMBER_POINTER(expr1->rtype)->ty2 == TYPE_MEMBER_POINTER(expr2->rtype)->ty2) { - expr2 = CExpr_Convert(expr2, expr1->rtype, ENODE_QUALS(expr1), 0, 1); - } else if (CExpr_CanImplicitlyConvert(expr1, expr2->rtype, ENODE_QUALS(expr2))) { - if (CExpr_CanImplicitlyConvert(expr2, expr1->rtype, ENODE_QUALS(expr1))) - CError_Error(CErrorStr188); - expr1 = CExpr_Convert(expr1, expr2->rtype, ENODE_QUALS(expr2), 0, 1); - } else if (CExpr_CanImplicitlyConvert(expr2, expr1->rtype, ENODE_QUALS(expr1))) { - expr2 = CExpr_Convert(expr2, expr1->rtype, ENODE_QUALS(expr1), 0, 1); - } else { - goto failed; - } - result->rtype = expr1->rtype; - break; - default: - failed: - CError_Error(CErrorStr245, expr1->rtype, ENODE_QUALS(expr1), expr2->rtype, ENODE_QUALS(expr2)); - return nullnode(); - } - - result->data.cond.expr1 = expr1; - result->data.cond.expr2 = expr2; - if (isnotzero(cond)) - result = expr1; - else if (iszero(cond)) - result = expr2; - return result; -} - -static ENode *conditional_expression(void) { - ENode *cond; - ENode *expr1; - ENode *expr2; - ENode *result; - Boolean is_templdep_cond; - - is_templdep_cond = 0; - cond = CExpr_ParseDyadicExpression(NULL, 0, 0); - if (tk != '?') - return cond; - - cond = pointer_generation(cond); - if (!IS_TYPE_TEMPLDEPEXPR(cond->rtype)) { - cond = CExpr_ConvertToCondition(cond); - if (!IS_TYPE_INT_OR_FLOAT(cond->rtype) && !IS_TYPE_POINTER_ONLY(cond->rtype)) { - CError_Error(CErrorStr144); - return nullnode(); - } - } else { - is_templdep_cond = 1; - } - - tk = lex(); - expr1 = expression(); - if (tk != ':') - CError_ErrorSkip(CErrorStr141); - else - tk = lex(); - - expr2 = (copts.cplusplus && !copts.ARMconform) ? assignment_expression() : conditional_expression(); - - if (is_templdep_cond || IS_TYPE_TEMPLDEPEXPR(expr1->rtype) || IS_TYPE_TEMPLDEPEXPR(expr2->rtype)) { - result = CExpr_NewENode(ECOND); - result->rtype = &sttemplexpr; - result->data.cond.cond = cond; - result->data.cond.expr1 = expr1; - result->data.cond.expr2 = expr2; - return result; - } - - return CExpr_New_ECOND_Node(cond, expr1, expr2); -} - -static ENode *CExpr_MakeOpAssNode(ENode *left, ENode *right, ENodeType nt) { - if (left->rtype != right->rtype) { - switch (right->rtype->type) { - case TYPEINT: - case TYPEFLOAT: - break; - case TYPEENUM: - right->rtype = TYPE_ENUM(right->rtype)->enumtype; - break; - default: - right = CExpr_AssignmentPromotion(right, left->rtype, 0, 1); - } - if (IS_TYPE_FLOAT(left->rtype)) { - if (IS_TYPE_INT(right->rtype) || (IS_TYPE_FLOAT(right->rtype) && left->rtype->size >= right->rtype->size)) - right = CExpr_AssignmentPromotion(right, left->rtype, 0, 1); - } else if (IS_TYPE_INT(left->rtype)) { - if (IS_TYPE_INT(right->rtype) && (left->rtype->size > right->rtype->size || (left->rtype->size == right->rtype->size && is_unsigned(left->rtype) == is_unsigned(right->rtype)))) - right = CExpr_AssignmentPromotion(right, left->rtype, 0, 1); - } - } - - return makediadicnode(left, right, nt); -} - -static ENode *makeassignmentnode(ENode *left, ENodeType nt, short token) { - ENode *right; - ENode *tmp; - ENode *funcexpr; - ENodeList *args; - Conversion conv; - - tk = lex(); - right = assignment_expression(); - if (copts.cplusplus) { - if (copts.old_argmatch && !ENODE_IS(right, EMEMBER)) - right = pointer_generation(right); - if (CExpr_CheckOperator(token, left, right, &conv)) { - if (!conv.x0) { - if (nt == EASS) - goto continue_anyway; - CError_FATAL(6531); - } - return conv.x0; - } - if (IS_TYPE_CLASS(left->rtype) && CClass_AssignmentOperator(TYPE_CLASS(left->rtype))) - CError_Error(CErrorStr144); - } -continue_anyway: - if (IS_TYPE_ARRAY(left->rtype)) { - if (copts.gcc_extensions && nt == EASS && is_typesame(left->rtype, right->rtype)) { - tmp = makediadicnode(left, right, nt); - tmp->flags = left->flags; - return tmp; - } - CError_Error(CErrorStr144); - return nullnode(); - } - - left = CExpr_LValue(pointer_generation(left), 1, 1); - if (nt != EASS) { - if (!IS_TYPE_INT(right->rtype)) { - if (!IS_TYPE_ENUM(right->rtype)) { - CError_Error(CErrorStr144); - return left; - } - right = forceintegral(right); - } - if (!IS_TYPE_INT(left->rtype)) { - if (copts.cplusplus) { - CError_Error(CErrorStr144); - return left; - } - left = forceintegral(left); - if (!IS_TYPE_INT(left->rtype)) { - CError_Error(CErrorStr144); - return left; - } - } - return CExpr_MakeOpAssNode(left, right, nt); - } - - if (IS_TYPE_CLASS(left->rtype) && TYPE_CLASS(left->rtype)->sominfo) { - CError_Error(CErrorStr285); - return left; - } - - if (copts.warn_implicitconv && ENODE_IS(left, EINDIRECT) && ENODE_IS(left->data.monadic, EBITFIELD) && !ENODE_IS(right, EINTCONST)) { - copts.warn_implicitconv = 0; - right = CExpr_AssignmentPromotion(right, left->rtype, left->flags, 1); - copts.warn_implicitconv = 1; - } else { - right = CExpr_AssignmentPromotion(right, left->rtype, left->flags, 1); - } - - tmp = right; - if (IS_TYPE_FLOAT(right->rtype) && ENODE_IS(right, ETYPCON) && right->rtype->size == right->data.monadic->rtype->size) - tmp = right->data.monadic; - - if ( - ENODE_IS(left, EINDIRECT) && - ENODE_IS(left->data.monadic, EOBJREF) && - ENODE_IS(tmp, EINDIRECT) && - (ENODE_IS(funcexpr = right->data.monadic, EFUNCCALL) || ENODE_IS(funcexpr, EFUNCCALLP)) && - left->rtype == funcexpr->data.funccall.functype->functype && - CMach_GetFunctionResultClass(funcexpr->data.funccall.functype) == 1 && - (args = funcexpr->data.funccall.args) - ) { - switch (CABI_GetStructResultArgumentIndex(funcexpr->data.funccall.functype)) { - case 0: - break; - case 1: - if ((args = args->next)) - break; - CError_FATAL(6625); - default: - CError_FATAL(6626); - } - if (ENODE_IS(args->node, ETEMP)) { - if (!(IS_TYPE_CLASS(left->rtype) && CClass_Destructor(TYPE_CLASS(left->rtype)))) { - args->node = getnodeaddress(left, 0); - return right; - } - } - } - - right = makediadicnode(left, right, nt); - right->flags = left->flags; - return right; -} - -static ENode *makepassignmentnode(ENode *left, ENodeType nt, short token) { - ENode *right; - Boolean is_array; - Conversion conv; - - is_array = IS_TYPE_ARRAY(left->rtype); - left = pointer_generation(left); - if (copts.cplusplus) { - tk = lex(); - right = pointer_generation(assignment_expression()); - if (CExpr_CheckOperator(token, left, right, &conv)) { - CError_ASSERT(6669, conv.x0); - return conv.x0; - } - left = CExpr_LValue(left, 1, 1); - } else { - left = CExpr_LValue(left, 1, 1); - tk = lex(); - right = pointer_generation(assignment_expression()); - } - - if (is_array) - CError_Error(CErrorStr144); - - switch (left->rtype->type) { - case TYPEINT: - case TYPEFLOAT: - case TYPEPOINTER: - break; - case TYPEENUM: - if (copts.cplusplus) { - CError_Error(CErrorStr144); - return left; - } - left = forceintegral(left); - break; - default: - CError_Error(CErrorStr144); - return left; - } - - if (IS_TYPE_ENUM(right->rtype)) - right = forceintegral(right); - - if (iszero(right)) - return left; - - if (IS_TYPE_POINTER_ONLY(left->rtype)) { - if (IS_TYPE_INT(right->rtype)) { - if (nt == ESUBASS) { - left = psub(left, right); - if (ENODE_IS(left, ESUB)) - left->type = ESUBASS; - return left; - } else { - left = padd(left, right); - if (ENODE_IS(left, EADD)) - left->type = EADDASS; - return left; - } - } - CError_Error(CErrorStr144); - return left; - } else { - return CExpr_MakeOpAssNode(left, right, nt); - } -} - -static ENode *makemulassignmentnode(ENode *left, ENodeType nt, short token) { - ENode *right; - Boolean is_array; - Conversion conv; - - is_array = IS_TYPE_ARRAY(left->rtype); - left = pointer_generation(left); - if (copts.cplusplus) { - tk = lex(); - right = pointer_generation(assignment_expression()); - if (CExpr_CheckOperator(token, left, right, &conv)) { - CError_ASSERT(6753, conv.x0); - return conv.x0; - } - if (!IS_TYPE_INT(left->rtype) && !(IS_TYPE_FLOAT(left->rtype) && nt != EMODASS)) { - CError_Error(CErrorStr144); - return nullnode(); - } - left = CExpr_LValue(left, 1, 1); - } else { - if (IS_TYPE_ENUM(left->rtype)) - left = forceintegral(left); - if (!IS_TYPE_INT(left->rtype) && !(IS_TYPE_FLOAT(left->rtype) && nt != EMODASS)) { - CError_Error(CErrorStr144); - return nullnode(); - } - - left = CExpr_LValue(left, 1, 1); - tk = lex(); - right = pointer_generation(assignment_expression()); - } - - if (is_array) - CError_Error(CErrorStr144); - - if (IS_TYPE_ENUM(right->rtype)) - right = forceintegral(right); - - if (IS_TYPE_INT(left->rtype) && IS_TYPE_FLOAT(right->rtype) && nt == EMODASS) { - CError_Error(CErrorStr144); - return nullnode(); - } - - return CExpr_MakeOpAssNode(left, right, nt); -} - -static ENode *CExpr_TransformOpAssign(ENode *expr) { - switch (expr->type) { - case EMULASS: - case EDIVASS: - case EMODASS: - case EADDASS: - case ESUBASS: - case ESHLASS: - case ESHRASS: - case EANDASS: - case EXORASS: - case EORASS: - if (expr->rtype == TYPE(&stbool)) { - expr = CIRTrans_TransformOpAss(expr); - if (ENODE_IS(expr, EASS)) { - expr->data.diadic.right = makemonadicnode(expr->data.diadic.right, ELOGNOT); - expr->data.diadic.right->rtype = TYPE(&stbool); - expr->data.diadic.right = makemonadicnode(expr->data.diadic.right, ELOGNOT); - } - } - } - - return expr; -} - -ENode *assignment_expression(void) { - ENode *expr; - - if (tk == TK_THROW) - return CExcept_ScanThrowExpression(); - - expr = conditional_expression(); - switch (tk) { - case '=': - return makeassignmentnode(expr, EASS, tk); - case TK_ADD_ASSIGN: - return CExpr_TransformOpAssign(makepassignmentnode(expr, EADDASS, tk)); - case TK_SUB_ASSIGN: - return CExpr_TransformOpAssign(makepassignmentnode(expr, ESUBASS, tk)); - case TK_MULT_ASSIGN: - expr = makemulassignmentnode(expr, EMULASS, tk); - if (ENODE_IS(expr, EMULASS) && CExpr_IsOne(expr->data.diadic.right)) - return expr->data.diadic.left; - return CExpr_TransformOpAssign(expr); - case TK_DIV_ASSIGN: - expr = makemulassignmentnode(expr, EDIVASS, tk); - if (ENODE_IS(expr, EDIVASS)) { - if (iszero(expr->data.diadic.right) && !IS_TYPE_FLOAT(expr->rtype)) { - CError_Warning(CErrorStr139); - return expr->data.diadic.left; - } - if (CExpr_IsOne(expr->data.diadic.right)) - return expr->data.diadic.left; - } - return CExpr_TransformOpAssign(expr); - case TK_MOD_ASSIGN: - expr = makemulassignmentnode(expr, EMODASS, tk); - if (ENODE_IS(expr, EMODASS)) { - if (iszero(expr->data.diadic.right)) { - CError_Warning(CErrorStr139); - return expr->data.diadic.left; - } - } - return CExpr_TransformOpAssign(expr); - case TK_SHL_ASSIGN: - expr = makeassignmentnode(expr, ESHLASS, tk); - if (ENODE_IS(expr, ESHLASS) && iszero(expr->data.diadic.right)) - return expr->data.diadic.left; - return CExpr_TransformOpAssign(expr); - case TK_SHR_ASSIGN: - expr = makeassignmentnode(expr, ESHRASS, tk); - if (ENODE_IS(expr, ESHRASS) && iszero(expr->data.diadic.right)) - return expr->data.diadic.left; - return CExpr_TransformOpAssign(expr); - case TK_AND_ASSIGN: - expr = makeassignmentnode(expr, EANDASS, tk); - if (ENODE_IS(expr, EANDASS) && CExpr_AllBitsSet(expr->data.diadic.right)) - return expr->data.diadic.left; - return expr; - case TK_XOR_ASSIGN: - expr = makeassignmentnode(expr, EXORASS, tk); - if (ENODE_IS(expr, EXORASS) && iszero(expr->data.diadic.right)) - return expr->data.diadic.left; - return CExpr_TransformOpAssign(expr); - case TK_OR_ASSIGN: - expr = makeassignmentnode(expr, EORASS, tk); - if (ENODE_IS(expr, EORASS) && iszero(expr->data.diadic.right)) - return expr->data.diadic.left; - return CExpr_TransformOpAssign(expr); - default: - return expr; - } -} - -ENode *conv_assignment_expression(void) { - return pointer_generation(assignment_expression()); -} - -static Boolean CExpr_HasSideEffect(ENode *expr) { - switch (expr->type) { - case EMONMIN: - case EBINNOT: - case ELOGNOT: - case EMUL: - case EDIV: - case EMODULO: - 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 EROTL: - case EROTR: - case EBITFIELD: - case EINTCONST: - case EFLOATCONST: - case ESTRINGCONST: - case EOBJREF: - case ETEMP: - case EARGOBJ: - case ELOCOBJ: - case EOBJLIST: - case EMEMBER: - case EVECTOR128CONST: - return 0; - case ETYPCON: - return IS_TYPE_VOID(expr->rtype); - case EINDIRECT: - switch (expr->data.monadic->type) { - case EFUNCCALL: - case EFUNCCALLP: - return 1; - default: - return 0; - } - case ECOMMA: - return CInline_ExpressionHasSideEffect(expr->data.diadic.right); - case ECOND: - return CInline_ExpressionHasSideEffect(expr->data.cond.expr1) || CInline_ExpressionHasSideEffect(expr->data.cond.expr2); - case EPOSTINC: - case EPOSTDEC: - case EPREINC: - case EPREDEC: - case EFORCELOAD: - case EASS: - case EMULASS: - case EDIVASS: - case EMODASS: - case EADDASS: - case ESUBASS: - case ESHLASS: - case ESHRASS: - case EANDASS: - case EXORASS: - case EORASS: - case EFUNCCALL: - case EFUNCCALLP: - case EMFPOINTER: - case ENULLCHECK: - case EPRECOMP: - case ELABEL: - case ENEWEXCEPTION: - case ENEWEXCEPTIONARRAY: - case EINITTRYCATCH: - case EINSTRUCTION: - return 1; - default: - CError_FATAL(7056); - return 0; - } -} - -void CExpr_CheckUnusedExpression(ENode *expr) { - ENode *scan; - ENodeList *arg; - - if (copts.warn_possunwant) { - scan = expr; - while (ENODE_IS(scan, ETYPCON)) - scan = scan->data.monadic; - if (ENODE_IS(scan, EEQU)) { - CError_Warning(CErrorStr208); - return; - } - } - - if (copts.warn_no_side_effect) { - if (!CExpr_HasSideEffect(expr)) { - CError_Warning(CErrorStr369); - return; - } - } - - if (copts.warn_resultnotused) { - scan = expr; - if (IS_TYPE_VOID(expr->rtype)) - return; - if (ENODE_IS(expr, EINDIRECT)) - scan = expr->data.monadic; - - switch (scan->type) { - case EFUNCCALL: - case EFUNCCALLP: - if (ENODE_IS(scan->data.funccall.funcref, EOBJREF) && scan->data.funccall.funcref->data.objref->name == asop_name_node) - return; - if (CMach_GetFunctionResultClass(scan->data.funccall.functype) == 1 && (arg = scan->data.funccall.args)) { - switch (CABI_GetStructResultArgumentIndex(scan->data.funccall.functype)) { - case 0: - break; - case 1: - if ((arg = arg->next)) - break; - CError_FATAL(7110); - default: - CError_FATAL(7111); - } - - if (!ENODE_IS(arg->node, ETEMP)) - return; - } - CError_Warning(CErrorStr370); - } - } -} - -ENode *s_expression(void) { - ENode *left; - ENode *right; - Conversion conv; - - left = assignment_expression(); - while (tk == ',') { - left = pointer_generation(left); - tk = lex(); - right = pointer_generation(assignment_expression()); - - if (copts.cplusplus && CExpr_CheckOperator(',', left, right, &conv)) { - CError_ASSERT(7143, left = conv.x0); - } else { - CExpr_CheckUnusedExpression(left); - left = makecommaexpression(left, right); - left->rtype = right->rtype; - } - } - - return left; -} - -ENode *expression(void) { - return pointer_generation(s_expression()); -} - -CInt64 CExpr_IntegralConstExprType(Type **tint) { - ENode *expr; - - expr = pointer_generation(conditional_expression()); - if (ENODE_IS(expr, EINTCONST)) { - switch (expr->rtype->type) { - case TYPEINT: - *tint = expr->rtype; - return expr->data.intval; - case TYPEENUM: - *tint = TYPE_ENUM(expr->rtype)->enumtype; - return expr->data.intval; - } - } - - CError_Error(CErrorStr124); - *tint = TYPE(&stchar); - return cint64_zero; -} - -ENode *CExpr_IntegralConstOrDepExpr(void) { - ENode *expr; - - expr = pointer_generation(conditional_expression()); - if (ENODE_IS(expr, EINTCONST)) { - switch (expr->rtype->type) { - case TYPEINT: - return expr; - case TYPEENUM: - expr->rtype = TYPE_ENUM(expr->rtype)->enumtype; - return expr; - default: - CError_FATAL(7209); - } - } - - if (CTemplTool_IsTemplateArgumentDependentExpression(expr)) - return expr; - - CError_Error(CErrorStr124); - expr = nullnode(); - expr->rtype = TYPE(&stchar); - return expr; -} - -CInt64 CExpr_IntegralConstExpr(void) { - Type *throwaway; - return CExpr_IntegralConstExprType(&throwaway); -} - -void CExpr_CheckUnwantedAssignment(ENode *expr) { - if (copts.warn_possunwant) { - if (ENODE_IS(expr, EASS) && !(expr->flags & ENODE_FLAG_80)) - CError_Warning(CErrorStr207); - } -} - -Boolean CExpr_ParseAsmExpr(Object **objptr, CInt64 *valptr) { - ENode *expr; - - if (objptr) - *objptr = NULL; - *valptr = cint64_zero; - - expr = pointer_generation(assignment_expression()); - if (ENODE_IS(expr, EINTCONST)) { - *valptr = expr->data.intval; - return 1; - } - - if (objptr) { - switch (expr->type) { - case EINDIRECT: - if (CInit_RelocInitCheck(expr->data.monadic, objptr, valptr, 1)) - return 1; - break; - case EOBJREF: - *objptr = expr->data.objref; - while ((*objptr)->datatype == DALIAS) - *objptr = (*objptr)->u.alias.object; - return 1; - case EMEMBER: - if (expr->data.emember->list->object->otype == OT_OBJECT) { - if (expr->data.emember->list->next && expr->data.emember->list->next->object->otype == OT_OBJECT) - CError_Error(CErrorStr199); - *objptr = OBJECT(expr->data.emember->list->object); - while ((*objptr)->datatype == DALIAS) - *objptr = (*objptr)->u.alias.object; - return 1; - } - break; - case EOBJLIST: - CError_Error(CErrorStr199); - return 0; - } - } - - CError_Error(CErrorStr155); - return 0; -} |