summaryrefslogtreecommitdiff
path: root/compiler_and_linker/unsorted/CExprConvMatch.c
diff options
context:
space:
mode:
authorAsh Wolf <ninji@wuffs.org>2023-01-26 11:30:47 +0000
committerAsh Wolf <ninji@wuffs.org>2023-01-26 11:30:47 +0000
commit094b96ca1df4a035b5f93c351f773306c0241f3f (patch)
tree95ce05e3ebe816c7ee7996206bb37ea17d8ca33c /compiler_and_linker/unsorted/CExprConvMatch.c
parentfc0c4c0df7b583b55a08317cf1ef6a71d27c0440 (diff)
downloadMWCC-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/CExprConvMatch.c')
-rw-r--r--compiler_and_linker/unsorted/CExprConvMatch.c2518
1 files changed, 0 insertions, 2518 deletions
diff --git a/compiler_and_linker/unsorted/CExprConvMatch.c b/compiler_and_linker/unsorted/CExprConvMatch.c
deleted file mode 100644
index 5cc145f..0000000
--- a/compiler_and_linker/unsorted/CExprConvMatch.c
+++ /dev/null
@@ -1,2518 +0,0 @@
-#include "compiler/CExpr.h"
-#include "compiler/CABI.h"
-#include "compiler/CClass.h"
-#include "compiler/CDecl.h"
-#include "compiler/CError.h"
-#include "compiler/CInt64.h"
-#include "compiler/CFunc.h"
-#include "compiler/CMachine.h"
-#include "compiler/CMangler.h"
-#include "compiler/CObjC.h"
-#include "compiler/CParser.h"
-#include "compiler/CScope.h"
-#include "compiler/CTemplateFunc.h"
-#include "compiler/CodeGen.h"
-#include "compiler/CompilerTools.h"
-#include "compiler/objects.h"
-#include "compiler/scopes.h"
-#include "compiler/templates.h"
-
-#ifdef __MWERKS__
-#pragma options align=mac68k
-#endif
-typedef struct StandardConv {
- Type *type1;
- Type *type2;
- UInt32 qual1;
- UInt32 qual2;
- Boolean x10; // unknown
- Boolean x11;
- Boolean x12;
- Boolean x13;
- Boolean x14;
- Boolean x15;
-} StandardConv;
-
-typedef enum EImplicitConvType {
- ICT_0,
- ICT_1,
- ICT_2,
- ICT_3
-} EImplicitConvType;
-
-typedef struct ImplicitConv {
- EImplicitConvType type;
- union {
- struct {
- Object *x2;
- StandardConv standardConv;
- } ic2;
- struct {
- StandardConv standardConv;
- } ic3;
- } u;
-} ImplicitConv;
-
-typedef struct ConversionTypeList {
- struct ConversionTypeList *next;
- Object *func;
- Type *type;
- UInt32 qual;
-} ConversionTypeList;
-
-typedef struct Match {
- struct Match *next;
- Object *object;
- Object *specialfunc;
- Type *type;
- UInt32 qual;
- Type *type2;
- UInt32 qual2;
- ImplicitConv conv[3];
-} Match;
-#ifdef __MWERKS__
-#pragma options align=reset
-#endif
-
-// forward decls
-static ENode *CExpr_DerivedToBase(ENode *expr, Type *type2, UInt32 qual2, Boolean flag1, Boolean flag2, Boolean flag3);
-
-static Type *CExpr_GetImplictObjectParamType(Object *object, UInt32 *qual) {
- Type *type;
-
- CError_ASSERT(98, IS_TYPE_FUNC(object->type));
- CError_ASSERT(99, TYPE_FUNC(object->type)->flags & FUNC_METHOD);
- CError_ASSERT(100, !TYPE_METHOD(object->type)->is_static);
- CError_ASSERT(101, TYPE_METHOD(object->type)->args);
-
- type = CDecl_NewRefPointerType(TYPE(TYPE_METHOD(object->type)->theclass));
- *qual = TYPE_METHOD(object->type)->args->qual & Q_CV;
- return type;
-}
-
-static Type *CExpr_GetParamType(Object *object, int index, UInt32 *qual) {
- FuncArg *arg;
-
- CError_ASSERT(120, IS_TYPE_FUNC(object->type));
- CError_ASSERT(121, arg = TYPE_FUNC(object->type)->args);
- if (IS_TYPEFUNC_NONSTATIC_METHOD(TYPE_FUNC(object->type)))
- CError_ASSERT(125, arg = arg->next);
-
- while (index > 0) {
- CError_ASSERT(129, arg = arg->next);
- index--;
- }
-
- *qual = arg->qual & Q_CV;
- return arg->type;
-}
-
-static Boolean CExpr_HasNParams(Object *object, int count) {
- FuncArg *arg;
- int i;
-
- CError_ASSERT(146, IS_TYPE_FUNC(object->type));
- CError_ASSERT(147, arg = TYPE_FUNC(object->type)->args);
- if (IS_TYPEFUNC_NONSTATIC_METHOD(TYPE_FUNC(object->type)))
- arg = arg->next;
-
- i = 0;
- while (arg) {
- arg = arg->next;
- i++;
- }
-
- return i == count;
-}
-
-typedef enum TypeCompareMode {
- TCM_0,
- TCM_1,
- TCM_2
-} TypeCompareMode;
-
-static Boolean CExpr_TypeCompare(Type *typeA, UInt32 qualA, Type *typeB, UInt32 qualB, TypeCompareMode mode) {
- if (typeA->type != typeB->type)
- return 0;
-
- switch (mode) {
- case TCM_0:
- while (1) {
- switch (typeA->type) {
- case TYPEPOINTER:
- typeA = TPTR_TARGET(typeA);
- typeB = TPTR_TARGET(typeB);
- if (typeA->type != typeB->type)
- return 0;
- continue;
-
- case TYPEMEMBERPOINTER:
- if (!is_typesame(TYPE_MEMBER_POINTER(typeA)->ty2, TYPE_MEMBER_POINTER(typeB)->ty2))
- return 0;
- typeA = TYPE_MEMBER_POINTER(typeA)->ty1;
- typeB = TYPE_MEMBER_POINTER(typeB)->ty1;
- if (typeA->type != typeB->type)
- return 0;
- continue;
- }
- break;
- }
- break;
-
- case TCM_1:
- switch (typeA->type) {
- case TYPEPOINTER:
- if ((qualA & Q_CV) != (qualB & Q_CV))
- return 0;
-
- typeA = TPTR_TARGET(typeA);
- typeB = TPTR_TARGET(typeB);
- break;
-
- case TYPEMEMBERPOINTER:
- if ((qualA & Q_CV) != (qualB & Q_CV))
- return 0;
-
- if (!is_typesame(TYPE_MEMBER_POINTER(typeA)->ty2, TYPE_MEMBER_POINTER(typeB)->ty2))
- return 0;
- typeA = TYPE_MEMBER_POINTER(typeA)->ty1;
- typeB = TYPE_MEMBER_POINTER(typeB)->ty1;
- break;
- }
- break;
-
- case TCM_2:
- if ((qualA & Q_CV) != (qualB & Q_CV))
- return 0;
- break;
- }
-
- return is_typesame(typeA, typeB);
-}
-
-static int CExpr_IsReferenceCompatible(Type *typeA, UInt32 qualA, Type *typeB, UInt32 qualB) {
- if (CParser_IsSameOrMoreCVQualified(CParser_GetCVTypeQualifiers(typeA, qualA), CParser_GetCVTypeQualifiers(typeB, qualB))) {
- if (CExpr_TypeCompare(typeA, qualA, typeB, qualB, TCM_1))
- return 1;
-
- if (IS_TYPE_CLASS(typeB) && IS_TYPE_CLASS(typeA)) {
- short depth;
- Boolean isambigbase;
- if (CClass_GetBasePath(TYPE_CLASS(typeB), TYPE_CLASS(typeA), &depth, &isambigbase))
- return 2;
- }
- }
-
- return 0;
-}
-
-static Boolean CExpr_IsBaseOf(TypeClass *baseclass, TypeClass *superclass) {
- ClassList *base;
-
- for (base = superclass->bases; base; base = base->next) {
- if (base->base == baseclass || CExpr_IsBaseOf(baseclass, base->base))
- return 1;
- }
-
- return 0;
-}
-
-static Boolean CExpr_IsBetterClassConversion(TypeClass *a, TypeClass *b, TypeClass *c, TypeClass *d) {
- if (a == c)
- return CExpr_IsBaseOf(d, b);
- if (b == d)
- return CExpr_IsBaseOf(a, c);
- return 0;
-}
-
-CW_INLINE Boolean Inline_501D40(Type *a, Type *b) {
- return (a == TYPE(&stbool)) && (IS_TYPE_POINTER_ONLY(b) || IS_TYPE_MEMBERPOINTER(b));
-}
-
-static Boolean CExpr_IsBetterStandardConv(StandardConv *a, StandardConv *b) {
- Boolean flag10;
- Boolean flag3;
-
- flag10 = 1;
- flag3 = 0;
-
- if (b->x11) {
- if (!a->x11)
- flag3 = 1;
- } else {
- if (a->x11)
- flag10 = 0;
- }
-
- if (b->x12) {
- if (!a->x12)
- flag3 = 1;
- } else {
- if (a->x12)
- flag10 = 0;
- }
-
- if (b->x13) {
- if (a->x13) {
- if (Inline_501D40(b->type2, b->type1)) {
- if (!Inline_501D40(a->type2, a->type1))
- return 1;
- } else {
- if (Inline_501D40(a->type2, a->type1))
- return 0;
- }
- } else {
- flag3 = 1;
- }
- } else {
- if (a->x13)
- flag10 = 0;
- }
-
- if (flag10 && flag3)
- return 1;
-
- if (!a->x13) {
- if (b->x13)
- return 1;
-
- if (a->x12) {
- if (!b->x12)
- return 0;
- } else {
- if (b->x12)
- return 1;
- }
- } else {
- if (!b->x13)
- return 0;
- }
-
- if (
- IS_TYPE_POINTER_ONLY(a->type1) &&
- IS_TYPE_CLASS(TPTR_TARGET(a->type1)) &&
- IS_TYPE_POINTER_ONLY(a->type2) &&
- IS_TYPE_POINTER_ONLY(b->type1) &&
- IS_TYPE_CLASS(TPTR_TARGET(b->type1)) &&
- IS_TYPE_POINTER_ONLY(b->type2)
- )
- {
- if (TPTR_TARGET(b->type2) == &stvoid) {
- if (TPTR_TARGET(a->type2) == &stvoid) {
- if (CExpr_IsBaseOf(TYPE_CLASS(TPTR_TARGET(a->type1)), TYPE_CLASS(TPTR_TARGET(b->type1))))
- return 1;
- } else {
- if (TPTR_TARGET(a->type1) == TPTR_TARGET(b->type1) && IS_TYPE_CLASS(TPTR_TARGET(a->type2)))
- return 1;
- }
- } else if (IS_TYPE_CLASS(TPTR_TARGET(a->type2)) && IS_TYPE_CLASS(TPTR_TARGET(b->type2))) {
- if (CExpr_IsBetterClassConversion(
- TYPE_CLASS(TPTR_TARGET(a->type1)),
- TYPE_CLASS(TPTR_TARGET(a->type2)),
- TYPE_CLASS(TPTR_TARGET(b->type1)),
- TYPE_CLASS(TPTR_TARGET(b->type2))
- ))
- return 1;
- }
- }
-
- if (
- IS_TYPE_CLASS(a->type1) &&
- IS_TYPE_CLASS(a->type2) &&
- IS_TYPE_CLASS(b->type1) &&
- IS_TYPE_CLASS(b->type2) &&
- CExpr_IsBetterClassConversion(
- TYPE_CLASS(a->type1),
- TYPE_CLASS(a->type2),
- TYPE_CLASS(b->type1),
- TYPE_CLASS(b->type2)
- )
- )
- return 1;
-
- if (
- IS_TYPE_MEMBERPOINTER(a->type1) &&
- IS_TYPE_MEMBERPOINTER(a->type2) &&
- IS_TYPE_MEMBERPOINTER(b->type1) &&
- IS_TYPE_MEMBERPOINTER(b->type2) &&
- IS_TYPE_CLASS(TYPE_MEMBER_POINTER(a->type1)->ty2) &&
- IS_TYPE_CLASS(TYPE_MEMBER_POINTER(a->type2)->ty2) &&
- IS_TYPE_CLASS(TYPE_MEMBER_POINTER(b->type1)->ty2) &&
- IS_TYPE_CLASS(TYPE_MEMBER_POINTER(b->type2)->ty2) &&
- CExpr_IsBetterClassConversion(
- TYPE_CLASS(TYPE_MEMBER_POINTER(b->type1)->ty2),
- TYPE_CLASS(TYPE_MEMBER_POINTER(b->type2)->ty2),
- TYPE_CLASS(TYPE_MEMBER_POINTER(a->type1)->ty2),
- TYPE_CLASS(TYPE_MEMBER_POINTER(a->type2)->ty2)
- )
- )
- return 1;
-
- if (
- a->x14 &&
- b->x14 &&
- CExpr_TypeCompare(a->type2, a->qual2, b->type2, b->qual2, TCM_1) &&
- CParser_IsMoreCVQualified(
- CParser_GetTypeQualifiers(b->type2, b->qual2),
- CParser_GetTypeQualifiers(a->type2, a->qual2)
- )
- )
- return 1;
-
- return 0;
-}
-
-static Boolean CExpr_IsBetterImplicitConv(ImplicitConv *a, ImplicitConv *b) {
- if (a->type > b->type)
- return 1;
- if (a->type != b->type)
- return 0;
-
- if (a->type == ICT_3)
- return CExpr_IsBetterStandardConv(&a->u.ic3.standardConv, &b->u.ic3.standardConv);
-
- if (a->type == ICT_2 && a->u.ic2.x2 == b->u.ic2.x2 && CExpr_IsBetterStandardConv(&a->u.ic2.standardConv, &b->u.ic2.standardConv))
- return 1;
-
- return 0;
-}
-
-typedef enum SSCRMode {
- SSCR_0,
- SSCR_1,
- SSCR_2
-} SSCRMode;
-
-static Boolean CExpr_SetupStandardConversionResult(ENode *expr, Type *type2, UInt32 qual2, SSCRMode mode, Boolean x14, Boolean refFlag, StandardConv *result) {
- UInt32 cv1;
- UInt32 cv2;
-
- if (x14) {
- if (!CParser_IsConst(type2, qual2)) {
- if (!refFlag && !CExpr_IsLValue(expr))
- return 0;
- if (mode != SSCR_0 && !IS_TYPE_CLASS(type2))
- return 0;
- }
-
- cv2 = CParser_GetTypeQualifiers(type2, qual2) & Q_CV;
- cv1 = CParser_GetTypeQualifiers(expr->rtype, ENODE_QUALS(expr)) & Q_CV;
- if (cv2 != cv1 && !CParser_IsMoreCVQualified(cv2, cv1))
- return 0;
- }
-
- memclrw(result, sizeof(StandardConv));
- result->type2 = type2;
- result->qual2 = qual2;
- result->type1 = expr->rtype;
- result->qual1 = ENODE_QUALS(expr);
- result->x14 = x14;
-
- switch (mode) {
- case SSCR_0:
- break;
- case SSCR_1:
- result->x12 = 1;
- break;
- case SSCR_2:
- result->x13 = 1;
- break;
- default:
- CError_FATAL(581);
- }
-
- return 1;
-}
-
-typedef enum MysteryEnum {
- ME_0,
- ME_1,
- ME_255 = 255
-} MysteryEnum;
-
-CW_INLINE MysteryEnum Inline_501FF0(UInt32 qual1, UInt32 qual2) {
- if ((qual1 & Q_CV) == (qual2 & Q_CV))
- return ME_0;
-
- if (((qual2 & Q_CONST) && !(qual1 & Q_CONST)) || ((qual2 & Q_VOLATILE) && !(qual1 & Q_VOLATILE)))
- return ME_255;
-
- return ME_1;
-}
-
-static Boolean CExpr_SetQualConversionResult(Type *type1, UInt32 qual1, Type *type2, UInt32 qual2, StandardConv *result) {
- Boolean flag = 1;
- UInt32 cv1;
- UInt32 cv2;
-
- while (1) {
- cv1 = CParser_GetCVTypeQualifiers(type1, qual1);
- cv2 = CParser_GetCVTypeQualifiers(type2, qual2);
-
- switch (Inline_501FF0(cv1, cv2)) {
- case ME_0:
- break;
-
- case ME_1:
- result->x11 = 1;
- if (!flag)
- return 0;
- break;
-
- default:
- return 0;
- }
-
- if (!(cv1 & Q_CONST))
- flag = 0;
-
- if (IS_TYPE_POINTER_ONLY(type1)) {
- CError_ASSERT(635, IS_TYPE_POINTER_ONLY(type2));
- type1 = TPTR_TARGET(type1);
- type2 = TPTR_TARGET(type2);
- } else {
- if (!IS_TYPE_MEMBERPOINTER(type1))
- return 1;
-
- CError_ASSERT(642, IS_TYPE_MEMBERPOINTER(type2));
- type1 = TYPE_MEMBER_POINTER(type1)->ty1;
- type2 = TYPE_MEMBER_POINTER(type2)->ty1;
- }
- }
-}
-
-static Boolean CExpr_OverloadFuncMatch(NameSpaceObjectList *list, TemplArg *templargs, Type *type, ENode **outExpr) {
- Object *object;
- TemplFuncInstance *inst;
- ENode *expr;
- FuncArg *arg;
- int i;
- ObjectList *objlist;
- Object *object26;
- ObjectList *objlist25;
- ObjectList *objlist24;
- Boolean flag23;
-
- if (!IS_TYPE_POINTER_ONLY(type) || !IS_TYPE_FUNC(type = TPTR_TARGET(type)))
- return 0;
-
- object26 = NULL;
- objlist25 = NULL;
- objlist24 = NULL;
- flag23 = 0;
-
- while (list) {
- object = OBJECT(list->object);
- if (object->otype == OT_OBJECT) {
- if (IS_TEMPL_FUNC(object->type)) {
- if (!flag23 && CTempl_CanDeduceFunc(object, TYPE_FUNC(type), templargs)) {
- CError_ASSERT(685, inst = CTempl_DeduceFunc(object, TYPE_FUNC(type), templargs, NULL, 0));
- if (is_typesame(inst->object->type, type)) {
- objlist = lalloc(sizeof(ObjectList));
- objlist->next = objlist24;
- objlist->object = object;
- objlist24 = objlist;
-
- if (object26 && object26 != inst->object) {
- objlist = lalloc(sizeof(ObjectList));
- objlist->next = objlist25;
- objlist->object = inst->object;
- objlist25 = objlist;
- } else {
- object26 = inst->object;
- }
- }
- }
- } else if (is_typesame(object->type, type)) {
- if (object26 && flag23) {
- Object *checkA, *checkB;
- checkA = object;
- if (checkA->datatype == DALIAS)
- checkA = checkA->u.alias.object;
- checkB = object26;
- if (checkB->datatype == DALIAS)
- checkB = checkB->u.alias.object;
- if (checkA != checkB) {
- objlist = lalloc(sizeof(ObjectList));
- objlist->next = objlist25;
- objlist->object = object;
- objlist25 = objlist;
- }
- } else {
- objlist25 = NULL;
- object26 = object;
- }
- flag23 = 1;
- }
- }
- list = list->next;
- }
-
- if (object26) {
- if (outExpr) {
- if (objlist25) {
- i = 0;
- for (arg = TYPE_FUNC(object->type)->args; arg; arg = arg->next)
- i++;
-
- if (!flag23 && (object = CTempl_PartialOrdering(objlist24->object, objlist24->next, i))) {
- CError_ASSERT(741, inst = CTempl_DeduceFunc(object, TYPE_FUNC(type), templargs, NULL, 0));
- object26 = inst->object;
- } else {
- CError_OverloadedFunctionError(object26, objlist25);
- }
- }
-
- expr = CExpr_MakeObjRefNode(object26, 1);
- *outExpr = expr;
- expr->rtype = CDecl_NewPointerType(object26->type);
- expr->flags = object->qual & ENODE_FLAG_QUALS;
- object26->flags |= OBJECT_USED;
- if (object26->datatype == DINLINEFUNC)
- CError_Error(CErrorStr175);
- }
-
- return 1;
- }
-
- return 0;
-}
-
-static Boolean CExpr_StandardConversionMatch(ENode *expr, Type *type2, UInt32 qual2, Boolean x14, StandardConv *result) {
- Type *type1;
- UInt32 qual1;
- Boolean refFlag;
- Type *inner2;
- Type *inner1;
- SSCRMode mode;
- NameSpaceObjectList list;
-
- if (IS_TYPE_REFERENCE(type2)) {
- type2 = TPTR_TARGET(type2);
- if (IS_TYPE_POINTER_ONLY(type2))
- expr = pointer_generation(expr);
- refFlag = 1;
- } else {
- if (
- (IS_TYPE_ARRAY(expr->rtype) && !IS_TYPE_ARRAY(type2)) ||
- (IS_TYPE_FUNC(expr->rtype) && !IS_TYPE_FUNC(type2))
- )
- expr = pointer_generation(expr);
- refFlag = 0;
- }
-
- type1 = expr->rtype;
- qual1 = ENODE_QUALS(expr);
-
- if (IS_TYPE_POINTER_ONLY(type2)) {
- if (ENODE_IS(expr, EINTCONST) && CInt64_IsZero(&expr->data.intval)) {
- if (IS_TYPE_INT(type1) || (!copts.cplusplus && IS_TYPE_ENUM(type1)))
- return CExpr_SetupStandardConversionResult(expr, type2, qual2, SSCR_2, x14, refFlag, result);
- }
-
- if (
- IS_TYPE_INT(expr->rtype) &&
- ENODE_IS_INDIRECT_TO(expr, EOBJREF) &&
- (expr->data.monadic->data.objref->qual & Q_INLINE_DATA) &&
- CInt64_IsZero(&expr->data.monadic->data.objref->u.data.u.intconst)
- )
- return CExpr_SetupStandardConversionResult(expr, type2, qual2, SSCR_2, x14, refFlag, result);
-
- if (ENODE_IS(expr, EOBJLIST))
- return CExpr_OverloadFuncMatch(expr->data.objlist.list, expr->data.objlist.templargs, type2, NULL) &&
- CExpr_SetupStandardConversionResult(expr, type2, qual2, SSCR_0, refFlag, x14, result);
-
- if (ENODE_IS(expr, EOBJREF) && IS_TEMPL_FUNC(expr->data.objref->type)) {
- list.next = NULL;
- list.object = OBJ_BASE(expr->data.objref);
- return CExpr_OverloadFuncMatch(&list, NULL, type2, NULL) &&
- CExpr_SetupStandardConversionResult(expr, type2, qual2, SSCR_0, refFlag, x14, result);
- }
-
- if (IS_TYPE_POINTER_ONLY(type1)) {
- if (
- ENODE_IS(expr, ESTRINGCONST) &&
- TPTR_TARGET(type2) == TPTR_TARGET(type1) &&
- !(qual2 & Q_CONST) &&
- (
- TPTR_TARGET(type2) == TYPE(&stchar) ||
- TPTR_TARGET(type2) == TYPE(&stunsignedchar) ||
- TPTR_TARGET(type2) == CParser_GetWCharType()
- )
- )
- {
- if (
- CExpr_SetupStandardConversionResult(expr, type2, qual2, SSCR_0, refFlag, x14, result) &&
- CExpr_SetQualConversionResult(TPTR_TARGET(type2), qual2, TPTR_TARGET(type1), qual1 & ~Q_CONST, result)
- )
- {
- result->x11 = 1;
- return 1;
- } else {
- return 0;
- }
- }
-
- if (copts.objective_c && CObjC_IsCompatibleType(expr->rtype, type2))
- return CExpr_SetupStandardConversionResult(expr, type2, qual2, SSCR_2, x14, refFlag, result);
-
- if (IS_TYPE_VOID(TPTR_TARGET(type2)) || (!copts.cplusplus && IS_TYPE_VOID(TPTR_TARGET(type1)))) {
- if (CExpr_SetupStandardConversionResult(expr, type2, qual2, IS_TYPE_VOID(TPTR_TARGET(type1)) ? SSCR_0 : SSCR_2, refFlag, x14, result)) {
- switch (Inline_501FF0(qual2, CParser_GetCVTypeQualifiers(TPTR_TARGET(type1), qual1))) {
- case ME_1:
- result->x11 = 1;
- case ME_0:
- return 1;
- default:
- return 0;
- }
- } else {
- return 0;
- }
- }
-
- inner2 = TPTR_TARGET(type2);
- inner1 = TPTR_TARGET(type1);
- while (1) {
- if (inner2->type != inner1->type)
- break;
-
- switch (inner2->type) {
- case TYPEPOINTER:
- inner2 = TPTR_TARGET(inner2);
- inner1 = TPTR_TARGET(inner1);
- continue;
- case TYPEMEMBERPOINTER:
- if (!is_typesame(TYPE_MEMBER_POINTER(inner2)->ty2, TYPE_MEMBER_POINTER(inner1)->ty2))
- break;
-
- inner2 = TYPE_MEMBER_POINTER(inner2)->ty1;
- inner1 = TYPE_MEMBER_POINTER(inner1)->ty1;
- if (!IS_TYPE_POINTER_ONLY(inner2) && !IS_TYPE_MEMBERPOINTER(inner2)) {
- if (!is_memberpointerequal(inner2, inner1))
- break;
-
- if (CExpr_SetupStandardConversionResult(expr, type2, qual2, SSCR_0, refFlag, x14, result))
- return CExpr_SetQualConversionResult(TPTR_TARGET(type2), qual2, TPTR_TARGET(type1), qual1, result);
- else
- return 0;
- }
- continue;
- default:
- if (!is_typesame(inner2, inner1))
- break;
-
- if (CExpr_SetupStandardConversionResult(expr, type2, qual2, SSCR_0, refFlag, x14, result))
- return CExpr_SetQualConversionResult(TPTR_TARGET(type2), qual2, TPTR_TARGET(type1), qual1, result);
- else
- return 0;
- }
-
- break;
- }
-
- if (IS_TYPE_CLASS(TPTR_TARGET(type2)) && IS_TYPE_CLASS(TPTR_TARGET(type1))) {
- short depth;
- Boolean isambigbase;
- if (CClass_GetBasePath(TYPE_CLASS(TPTR_TARGET(type1)), TYPE_CLASS(TPTR_TARGET(type2)), &depth, &isambigbase)) {
- if (CExpr_SetupStandardConversionResult(expr, type2, qual2, SSCR_2, refFlag, x14, result))
- return CExpr_SetQualConversionResult(TPTR_TARGET(type2), qual2, TPTR_TARGET(type1), qual1, result);
- else
- return 0;
- }
- }
- }
-
- if (copts.mpwc_relax && !copts.cplusplus && IS_TYPE_POINTER_ONLY(type1)) {
- if (CExpr_SetupStandardConversionResult(expr, type2, qual2, SSCR_2, refFlag, x14, result))
- return 1;
- }
-
- return 0;
- }
-
- if (is_typesame(type2, type1))
- return CExpr_SetupStandardConversionResult(expr, type2, qual2, SSCR_0, refFlag, x14, result);
-
- if (type2 == TYPE(&stbool)) {
- switch (type1->type) {
- case TYPEINT:
- case TYPEFLOAT:
- case TYPEENUM:
- case TYPEMEMBERPOINTER:
- case TYPEPOINTER:
- return CExpr_SetupStandardConversionResult(expr, type2, qual2, SSCR_2, refFlag, x14, result);
- default:
- return 0;
- }
- }
-
- if (IS_TYPE_MEMBERPOINTER(type2)) {
- if (ENODE_IS(expr, EINTCONST) && CInt64_IsZero(&expr->data.intval)) {
- if (IS_TYPE_INT(type1) || (!copts.cplusplus && IS_TYPE_ENUM(type1)))
- return CExpr_SetupStandardConversionResult(expr, type2, qual2, SSCR_2, refFlag, x14, result);
- }
-
- if (ENODE_IS(expr, EMEMBER)) {
- expr = getpointertomemberfunc(expr, type2, 0);
- type1 = expr->rtype;
- }
-
- if (IS_TYPE_MEMBERPOINTER(type1)) {
- short depth;
- Boolean isambigbase;
-
- CError_ASSERT(996, IS_TYPE_CLASS(TYPE_MEMBER_POINTER(type2)->ty2) && IS_TYPE_CLASS(TYPE_MEMBER_POINTER(type1)->ty2));
- if (!is_memberpointerequal(TYPE_MEMBER_POINTER(type2)->ty1, TYPE_MEMBER_POINTER(type1)->ty1))
- return 0;
-
- if (
- TYPE_MEMBER_POINTER(type2)->ty2 == TYPE_MEMBER_POINTER(type1)->ty2 ||
- CClass_GetBasePath(TYPE_CLASS(TYPE_MEMBER_POINTER(type2)->ty2), TYPE_CLASS(TYPE_MEMBER_POINTER(type1)->ty2), &depth, &isambigbase)
- )
- {
- if (CExpr_SetupStandardConversionResult(expr, type2, qual2, SSCR_2, refFlag, x14, result))
- return CExpr_SetQualConversionResult(TYPE_MEMBER_POINTER(type2)->ty1, qual2, TYPE_MEMBER_POINTER(type1)->ty1, qual1, result);
- else
- return 0;
- }
- }
-
- return 0;
- }
-
- mode = SSCR_2;
- switch (type1->type) {
- case TYPEINT:
- switch (type2->type) {
- case TYPEINT:
- if (TYPE_INTEGRAL(type1)->integral < IT_INT) {
- if (type2 == TYPE(&stsignedint)) {
- if (type1->size < type2->size || !is_unsigned(type1))
- mode = SSCR_1;
- } else if (type2 == TYPE(&stunsignedint)) {
- if (type2->size == type1->size && is_unsigned(type1))
- mode = SSCR_1;
- }
- }
- break;
- case TYPEFLOAT:
- break;
- case TYPEENUM:
- if (copts.cplusplus)
- return 0;
- break;
- default:
- return 0;
- }
- break;
-
- case TYPEFLOAT:
- switch (type2->type) {
- case TYPEINT:
- break;
- case TYPEFLOAT:
- if (type2 == TYPE(&stdouble)) {
- if (type1 == TYPE(&stfloat) || type1 == TYPE(&stshortdouble))
- mode = SSCR_1;
- }
- break;
- case TYPEENUM:
- if (copts.cplusplus)
- return 0;
- break;
- default:
- return 0;
- }
- break;
-
- case TYPEENUM:
- switch (type2->type) {
- case TYPEINT:
- if (TYPE_INTEGRAL(TYPE_ENUM(expr->rtype)->enumtype)->integral < IT_INT) {
- if (type1->size == type2->size && is_unsigned(TYPE_ENUM(type1)->enumtype)) {
- if (type2 == TYPE(&stunsignedint))
- mode = SSCR_1;
- } else {
- if (type2 == TYPE(&stsignedint))
- mode = SSCR_1;
- }
- } else {
- if (TYPE_ENUM(type1)->enumtype == type2)
- mode = SSCR_1;
- }
- break;
- case TYPEFLOAT:
- break;
- case TYPEENUM:
- if (copts.cplusplus)
- return 0;
- break;
- default:
- return 0;
- }
- break;
-
- case TYPECLASS: {
- short depth;
- Boolean isambigbase;
-
- if (!IS_TYPE_CLASS(type1) || !CClass_GetBasePath(TYPE_CLASS(type1), TYPE_CLASS(type2), &depth, &isambigbase))
- return 0;
- break;
- }
-
- default:
- return 0;
- }
-
- return CExpr_SetupStandardConversionResult(expr, type2, qual2, mode, refFlag, x14, result);
-}
-
-static ENode *CExpr_UserConversion(ENode *expr, Type *type2, UInt32 qual2, ImplicitConv *result, Boolean flag1, Boolean isExplicit, Boolean flag3) {
- Object *object28;
- Object *object27;
- Object *object26;
- ObjectList *objlist25;
- ObjectList *objlist24;
- ObjectList *objlist;
- TypeFunc *tfunc23;
- Type *tmptype23;
- NameSpaceObjectList *list22;
- Boolean flag22;
- Boolean flag21;
- FuncArg *arg21;
- Boolean flag20;
- ENode *newExpr;
- ENode *funcref;
- ENode *tmpExpr;
- ENodeList *arglist;
- UInt32 q1;
- UInt32 q2;
- StandardConv sc3;
- StandardConv sc2;
- StandardConv sc1;
- ConversionIterator convIter;
- ENodeList myarglist;
- ObjectList myobjlist;
- BClassList path;
-
- object28 = NULL;
- object27 = NULL;
- objlist25 = NULL;
- objlist24 = NULL;
-
- if (type2->size == 0)
- CDecl_CompleteType(type2);
- if (expr->rtype->size == 0)
- CDecl_CompleteType(expr->rtype);
-
- if (IS_TYPE_CLASS(expr->rtype)) {
- CExpr_ConversionIteratorInit(&convIter, TYPE_CLASS(expr->rtype));
- flag22 = 1;
- while ((object26 = CExpr_ConversionIteratorNext(&convIter))) {
- tfunc23 = TYPE_FUNC(object26->type);
- if (tfunc23->flags & FUNC_IS_TEMPL) {
- object26 = CTempl_DeduceFromConversion(object26, type2, qual2);
- if (!object26)
- continue;
- tfunc23 = TYPE_FUNC(object26->type);
- }
-
- if (flag3) {
- if (
- !IS_TYPE_REFERENCE(tfunc23->functype) ||
- !CExpr_IsReferenceCompatible(type2, qual2, TPTR_TARGET(tfunc23->functype), tfunc23->qual)
- )
- continue;
- }
-
- CError_ASSERT(1230, tfunc23->args && IS_TYPE_POINTER_ONLY(tfunc23->args->type));
-
- q1 = ENODE_QUALS(expr);
- q2 = tfunc23->args->qual;
- if ((q1 & Q_CV) != (q2 & Q_CV)) {
- if (!flag22)
- continue;
- if ((q1 & Q_CONST) && !(q2 & Q_CONST))
- continue;
- if ((q1 & Q_VOLATILE) && !(q2 & Q_VOLATILE))
- continue;
- flag21 = 1;
- } else {
- flag21 = 0;
- }
-
- newExpr = CExpr_NewENode(ETEMP);
- newExpr->rtype = tfunc23->functype;
- newExpr->flags = tfunc23->qual & ENODE_FLAG_QUALS;
- flag20 = 0;
-
- if (IS_TYPE_REFERENCE(newExpr->rtype)) {
- newExpr->rtype = TPTR_TARGET(newExpr->rtype);
- if (!CParser_IsConst(newExpr->rtype, tfunc23->qual)) {
- newExpr = makemonadicnode(newExpr, EINDIRECT);
- newExpr->data.monadic->rtype = TYPE(&void_ptr);
- newExpr = makemonadicnode(newExpr, EINDIRECT);
- newExpr->data.monadic->rtype = TYPE(&void_ptr);
- flag20 = 1;
- }
- }
-
- if (CExpr_StandardConversionMatch(newExpr, type2, qual2, 0, &sc1)) {
- if (flag22 && !flag21) {
- object28 = NULL;
- objlist25 = NULL;
- flag22 = 0;
- }
-
- if (object28 && object28 != object26) {
- if (CExpr_IsBetterStandardConv(&sc3, &sc1))
- continue;
-
- if (!CExpr_IsBetterStandardConv(&sc1, &sc3)) {
- objlist = lalloc(sizeof(ObjectList));
- objlist->next = objlist25;
- objlist->object = object28;
- objlist25 = objlist;
- } else {
- objlist25 = NULL;
- }
- }
-
- object28 = object26;
- sc3 = sc1;
- sc3.x15 = flag20;
- }
- }
- }
-
- if (!flag3 && IS_TYPE_CLASS(type2) && (list22 = CClass_Constructor(TYPE_CLASS(type2)))) {
- for (; list22; list22 = list22->next) {
- object26 = OBJECT(list22->object);
- if (
- object26->otype == OT_OBJECT &&
- IS_TYPE_FUNC(tfunc23 = TYPE_FUNC(object26->type)) &&
- (isExplicit || !(object26->qual & Q_EXPLICIT))
- )
- {
- if (tfunc23->flags & FUNC_IS_TEMPL) {
- myarglist.next = NULL;
- myarglist.node = expr;
- object26 = CTempl_DeduceFromFunctionCall(object26, NULL, &myarglist);
- if (!object26)
- continue;
- tfunc23 = TYPE_FUNC(object26->type);
- }
-
- if (!(arg21 = tfunc23->args))
- continue;
- if (!(arg21 = arg21->next))
- continue;
- if ((TYPE_CLASS(type2)->flags & CLASS_HAS_VBASES) && !(arg21 = arg21->next))
- continue;
- if (arg21 == &elipsis)
- continue;
- if (arg21->next && !arg21->next->dexpr && arg21->next != &elipsis)
- continue;
-
- tmptype23 = arg21->type;
- if (IS_TYPE_REFERENCE(tmptype23)) {
- tmptype23 = TPTR_TARGET(tmptype23);
- if (!CParser_IsConst(tmptype23, arg21->qual) && !CExpr_IsLValue(expr))
- continue;
- }
-
- if (CExpr_StandardConversionMatch(expr, tmptype23, arg21->qual, 0, &sc1)) {
- if (object27) {
- if (object26->u.func.inst && !object27->u.func.inst)
- continue;
- if (CExpr_IsBetterStandardConv(&sc2, &sc1))
- continue;
-
- if (!CExpr_IsBetterStandardConv(&sc1, &sc2)) {
- if (!object26->u.func.inst && object27->u.func.inst) {
- objlist24 = NULL;
- } else {
- objlist = lalloc(sizeof(ObjectList));
- objlist->next = objlist25;
- objlist->object = object28;
- objlist25 = objlist;
- }
- } else {
- objlist25 = NULL;
- }
- }
-
- object27 = object26;
- sc2 = sc1;
- }
- }
- }
- }
-
- if (object28 && object27) {
- if (!CExpr_IsBetterStandardConv(&sc2, &sc3)) {
- if (!CExpr_IsBetterStandardConv(&sc3, &sc2)) {
- if (result) {
- result->type = ICT_2;
- result->u.ic2.x2 = object28;
- result->u.ic2.standardConv = sc3;
- }
- if (flag1) {
- myobjlist.next = NULL;
- myobjlist.object = object27;
- CError_OverloadedFunctionError(object28, &myobjlist);
- }
- } else {
- object27 = NULL;
- }
- } else {
- object28 = NULL;
- }
- }
-
- if (object28) {
- if (result) {
- result->type = ICT_2;
- result->u.ic2.x2 = object28;
- result->u.ic2.standardConv = sc3;
- }
- if (!flag1)
- return expr;
- if (objlist25)
- CError_OverloadedFunctionError(object28, objlist25);
- tfunc23 = TYPE_FUNC(object28->type);
- CError_ASSERT(1416, IS_TYPEFUNC_METHOD(tfunc23));
-
- funcref = create_objectrefnode(object28);
- object28->flags |= OBJECT_USED;
-
- arglist = lalloc(sizeof(ENodeList));
- arglist->next = NULL;
-
- expr = getnodeaddress(expr, 0);
- arglist->node = CExpr_AssignmentPromotion(
- expr,
- CDecl_NewPointerType(TYPE(TYPE_METHOD(tfunc23)->theclass)),
- expr->flags,
- 0);
-
- newExpr = lalloc(sizeof(ENode));
- newExpr->type = EFUNCCALL;
- newExpr->cost = 4;
- newExpr->rtype = tfunc23->functype;
- newExpr->flags = tfunc23->qual & ENODE_FLAG_QUALS;
- newExpr->data.funccall.funcref = funcref;
- newExpr->data.funccall.args = arglist;
- newExpr->data.funccall.functype = TYPE_FUNC(object28->type);
- newExpr = CExpr_AdjustFunctionCall(newExpr);
- newExpr = checkreference(newExpr);
-
- if (newExpr->rtype != type2) {
- if (flag3) {
- tmpExpr = CExpr_DerivedToBase(newExpr, type2, qual2, 1, 0, 1);
- if (tmpExpr)
- return tmpExpr;
- }
- newExpr = CExpr_Convert(newExpr, type2, qual2, 0, 1);
- }
- return newExpr;
- }
-
- if (object27) {
- if (result) {
- result->type = ICT_2;
- result->u.ic2.x2 = object27;
- result->u.ic2.standardConv = sc2;
- }
- if (!flag1)
- return expr;
- if (objlist24)
- CError_OverloadedFunctionError(object27, objlist24);
-
- arglist = lalloc(sizeof(ENodeList));
- arglist->next = NULL;
- arglist->node = expr;
-
- if (TYPE_CLASS(type2)->flags & CLASS_HAS_VBASES) {
- arglist->next = lalloc(sizeof(ENodeList));
- arglist->next->node = expr;
- arglist->next->next = NULL;
- arglist->node = intconstnode(TYPE(&stsignedshort), 1);
- }
-
- path.next = NULL;
- path.type = type2;
-
- tmpExpr = makemonadicnode(create_temp_node(type2), EINDIRECT);
- tmpExpr->rtype = type2;
-
- newExpr = CExpr_GenericFuncCall(
- &path, tmpExpr, 0, object27, NULL, NULL, arglist, 0, 0, 1
- );
-
- if (ENODE_IS2(newExpr, EFUNCCALL, EFUNCCALLP)) {
- newExpr->rtype = CDecl_NewPointerType(type2);
- newExpr = makemonadicnode(newExpr, EINDIRECT);
- newExpr->rtype = type2;
- }
-
- return newExpr;
- }
-
- return NULL;
-}
-
-static Boolean CExpr_UserConversionMatch(ENode *expr, Type *type2, UInt32 qual2, ImplicitConv *result) {
- Boolean flag;
-
- if (IS_TYPE_REFERENCE(type2)) {
- type2 = TPTR_TARGET(type2);
- flag = !CParser_IsConst(type2, qual2);
- } else {
- expr = pointer_generation(expr);
- flag = 0;
- }
-
- if (CExpr_UserConversion(expr, type2, qual2, result, 0, 0, flag))
- return 1;
-
- return 0;
-}
-
-static Boolean CExpr_ImplicitConversionMatch(ENode *expr, Type *type2, UInt32 qual2, ImplicitConv *result) {
- if (CExpr_StandardConversionMatch(expr, type2, qual2, 0, &result->u.ic3.standardConv)) {
- result->type = ICT_3;
- return 1;
- }
-
- if (IS_TYPE_CLASS(expr->rtype) || IS_TYPE_CLASS(type2) || (IS_TYPE_REFERENCE(type2) && IS_TYPE_CLASS(TPTR_TARGET(type2)))) {
- if (CExpr_UserConversionMatch(expr, type2, qual2, result)) {
- result->type = ICT_2;
- return 1;
- }
- }
-
- return 0;
-}
-
-Boolean CExpr_CanImplicitlyConvert(ENode *expr, Type *type2, UInt32 qual2) {
- ImplicitConv result;
- return CExpr_ImplicitConversionMatch(expr, type2, qual2, &result);
-}
-
-static ENode *CExpr_DerivedToBase(ENode *expr, Type *type2, UInt32 qual2, Boolean flag1, Boolean nullcheckflag, Boolean pathcheckflag) {
- BClassList *path;
- short depth;
- Boolean isambigbase;
-
- if (
- IS_TYPE_CLASS(type2) &&
- IS_TYPE_CLASS(expr->rtype) &&
- (path = CClass_GetBasePath(TYPE_CLASS(expr->rtype), TYPE_CLASS(type2), &depth, &isambigbase))
- )
- {
- if (isambigbase)
- CError_Error(CErrorStr188);
- if (flag1)
- CClass_CheckPathAccess(path, NULL, ACCESSPUBLIC);
-
- if (pathcheckflag) {
- expr = getnodeaddress(expr, 0);
- expr = makemonadicnode(CExpr_ClassPointerCast(path, expr, nullcheckflag), EINDIRECT);
- expr->rtype = type2;
- expr->flags = qual2 & ENODE_FLAG_QUALS;
- }
-
- return expr;
- }
- else {
- return NULL;
- }
-}
-
-static ENode *CExpr_ClassReferenceConversion(ENode *expr, Type *type2, UInt32 qual2, Boolean pathcheckflag) {
- int refcompat;
-
- if (CExpr_IsLValue(expr) && IS_TYPE_CLASS(type2) && IS_TYPE_CLASS(expr->rtype)) {
- refcompat = CExpr_IsReferenceCompatible(type2, 0, expr->rtype, 0);
- if (refcompat > 0) {
- if (refcompat == 2) {
- CError_ASSERT(1668, IS_TYPE_CLASS(type2) && IS_TYPE_CLASS(expr->rtype));
- expr = CExpr_DerivedToBase(expr, type2, qual2, pathcheckflag, 0, 1);
- }
- expr->flags = qual2 & ENODE_FLAG_QUALS;
- return expr;
- }
-
- refcompat = CExpr_IsReferenceCompatible(expr->rtype, 0, type2, 0);
- if (refcompat > 0) {
- expr = CClass_ClassPointerCast(
- getnodeaddress(expr, 0),
- TYPE_CLASS(expr->rtype), TYPE_CLASS(type2),
- 1, 1, pathcheckflag
- );
- CError_ASSERT(1680, IS_TYPE_POINTER_ONLY(expr->rtype));
- expr = makemonadicnode(expr, EINDIRECT);
- expr->rtype = type2;
- expr->flags = qual2 & ENODE_FLAG_QUALS;
- return expr;
- }
- }
-
- if (IS_TYPE_CLASS(expr->rtype)) {
- if ((expr = CExpr_UserConversion(expr, type2, qual2, NULL, 1, 0, 1)))
- return expr;
- }
-
- return NULL;
-}
-
-static ENode *CExpr_BindToReference(ENode *expr, Type *type2, UInt32 qual2) {
- UInt32 cv;
- int refcompat;
- ENode *tmp;
-
- cv = CParser_GetCVTypeQualifiers(type2, qual2);
-
- if (CExpr_IsLValue(expr)) {
- refcompat = CExpr_IsReferenceCompatible(type2, qual2, expr->rtype, ENODE_QUALS(expr));
- if (refcompat > 0) {
- if (refcompat == 2) {
- CError_ASSERT(1718, IS_TYPE_CLASS(type2) && IS_TYPE_CLASS(expr->rtype));
- expr = CExpr_DerivedToBase(expr, type2, qual2, 1, 0, 1);
- }
- return getnodeaddress(expr, 0);
- }
- } else if (IS_TYPE_CLASS(type2) && IS_TYPE_CLASS(expr->rtype)) {
- refcompat = CExpr_IsReferenceCompatible(type2, qual2, expr->rtype, ENODE_QUALS(expr));
- if (refcompat > 0) {
- if (refcompat == 2)
- expr = CExpr_DerivedToBase(expr, type2, qual2, 1, 0, 1);
- return getnodeaddress(expr, 0);
- }
- }
-
- if (IS_TYPE_CLASS(expr->rtype)) {
- if ((tmp = CExpr_UserConversion(expr, type2, qual2, NULL, 1, 0, 1)))
- return getnodeaddress(tmp, 0);
- }
-
- if (!(cv & Q_CONST))
- CError_Error(CErrorStr228);
- if (cv & Q_VOLATILE)
- CError_Error(CErrorStr259);
-
- if (expr->rtype != type2)
- expr = CExpr_Convert(expr, type2, qual2, 0, 1);
-
- if (!CExpr_IsLValue(expr)) {
- expr = CExpr_LValue(expr, 0, 0);
- if (!ENODE_IS(expr, EINDIRECT))
- expr = get_address_of_temp_copy(expr, 1);
- else
- expr = getnodeaddress(expr, 0);
- } else {
- expr = getnodeaddress(expr, 0);
- }
-
- return expr;
-}
-
-ENode *CExpr_Convert(ENode *expr, Type *type, UInt32 qual, Boolean isExplicit, Boolean flag2) {
- UInt32 cv;
- ENode *refExpr;
- ENode *newExpr;
- Type *typeCopy;
- NameSpaceObjectList myList;
-
- cv = qual & Q_CV;
-
- if (copts.cpp_extensions && is_typesame(expr->rtype, type) && !ENODE_IS(expr, EOBJLIST)) {
- expr = CExpr_RewriteConst(expr);
- expr->rtype = type;
- expr->flags &= ~ENODE_FLAG_QUALS;
- expr->flags |= cv;
- return expr;
- }
-
- if (type == TYPE(&stvoid)) {
- expr = makemonadicnode(expr, ETYPCON);
- expr->rtype = type;
- expr->flags = cv;
- return expr;
- }
-
- if (IS_TYPE_REFERENCE(type)) {
- if (isExplicit) {
- refExpr = CExpr_ClassReferenceConversion(expr, TPTR_TARGET(type), qual, flag2);
- if (refExpr)
- return refExpr;
-
- expr = getnodeaddress(expr, 0);
- typeCopy = galloc(sizeof(TypePointer));
- *TYPE_POINTER(typeCopy) = *TYPE_POINTER(type);
- TPTR_QUAL(typeCopy) &= ~Q_REFERENCE;
- expr = CExpr_Convert(expr, typeCopy, qual, 0, flag2);
- expr = makemonadicnode(expr, EINDIRECT);
- expr->rtype = TPTR_TARGET(type);
- expr->flags = cv;
- return expr;
- } else {
- return CExpr_BindToReference(expr, TPTR_TARGET(type), qual);
- }
- }
-
- if (
- (IS_TYPE_ARRAY(expr->rtype) && !IS_TYPE_ARRAY(type)) ||
- (IS_TYPE_FUNC(expr->rtype) && !IS_TYPE_FUNC(type))
- )
- {
- expr = pointer_generation(expr);
- } else {
- expr = CExpr_RewriteConst(expr);
- }
-
- if (ENODE_IS(expr, EOBJLIST)) {
- if (CExpr_OverloadFuncMatch(expr->data.objlist.list, expr->data.objlist.templargs, type, &refExpr))
- return refExpr;
- } else if (ENODE_IS(expr, EOBJREF) && IS_TEMPL_FUNC(expr->data.objref->type)) {
- myList.next = NULL;
- myList.object = OBJ_BASE(expr->data.objref);
- if (CExpr_OverloadFuncMatch(&myList, NULL, type, &refExpr))
- return refExpr;
- } else if (IS_TYPE_CLASS(expr->rtype) || IS_TYPE_CLASS(type)) {
- if (expr->rtype->size == 0)
- CDecl_CompleteType(expr->rtype);
-
- if (IS_TYPE_CLASS(type)) {
- CanAllocObject(type);
- if (!CClass_CopyConstructor(TYPE_CLASS(type)) || CClass_IsTrivialCopyClass(TYPE_CLASS(type))) {
- if (expr->rtype == type)
- return expr;
-
- refExpr = CExpr_DerivedToBase(expr, type, qual, flag2, 0, 1);
- if (refExpr)
- return refExpr;
- }
- }
-
- refExpr = CExpr_UserConversion(expr, type, qual, NULL, 1, isExplicit, 0);
- if (refExpr) {
- refExpr->flags = cv;
- return refExpr;
- }
- } else if (!isExplicit && is_typesame(expr->rtype, type)) {
- if (ENODE_IS(expr, EINDIRECT) && ENODE_QUALS(expr) != cv)
- expr = makemonadicnode(expr, ETYPCON);
- expr->rtype = type;
- expr->flags = cv;
- return expr;
- } else {
- if (
- copts.warn_implicitconv &&
- !isExplicit &&
- IS_TYPE_INT_OR_FLOAT(type) &&
- IS_TYPE_INT_OR_FLOAT(expr->rtype)
- )
- CExpr_CheckArithmConversion(expr, type);
-
- switch (type->type) {
- case TYPEINT:
- if (type == TYPE(&stbool)) {
- switch (expr->rtype->type) {
- case TYPEINT:
- case TYPEFLOAT:
- case TYPEENUM:
- case TYPEMEMBERPOINTER:
- case TYPEPOINTER:
- return CExpr_ConvertToBool(expr, isExplicit);
- }
- } else {
- switch (expr->rtype->type) {
- case TYPEENUM:
- expr->rtype = TYPE_ENUM(expr->rtype)->enumtype;
- case TYPEINT:
- case TYPEFLOAT:
- do_int_float_conversion:
- if (
- ENODE_IS(expr, ETYPCON) &&
- expr->rtype->type == type->type &&
- expr->rtype->size == type->size &&
- is_unsigned(expr->rtype) == is_unsigned(type) &&
- ENODE_QUALS(expr) == qual
- )
- {
- expr->rtype = type;
- expr->flags |= ENODE_FLAG_80;
- return expr;
- } else {
- refExpr = promote(expr, type);
- refExpr->flags = cv;
- return refExpr;
- }
- break;
- case TYPEPOINTER:
- if (expr->rtype->size > type->size && copts.warn_ptr_int_conv)
- CError_Warning(CErrorStr382);
- if (ENODE_IS(expr, ETYPCON)) {
- ENode *inner = expr->data.monadic;
- if (ENODE_IS(inner, EINTCONST)) {
- inner->rtype = type;
- inner->flags = cv;
- inner->data.intval = CExpr_IntConstConvert(type, TYPE(&stunsignedlong), inner->data.intval);
- return inner;
- }
- }
- if (type->size != 4) {
- expr = makemonadicnode(expr, ETYPCON);
- expr->rtype = TYPE(&stunsignedlong);
- }
- expr = makemonadicnode(expr, ETYPCON);
- expr->rtype = type;
- expr->flags = cv;
- return expr;
- }
- }
- break;
-
- case TYPEFLOAT:
- switch (expr->rtype->type) {
- case TYPEENUM:
- expr->rtype = TYPE_ENUM(expr->rtype)->enumtype;
- case TYPEINT:
- case TYPEFLOAT:
- goto do_int_float_conversion;
- }
- break;
-
- case TYPEENUM:
- expr = CExpr_Convert(expr, TYPE_ENUM(type)->enumtype, qual, isExplicit, flag2);
- if (!ENODE_IS(expr, EINTCONST))
- expr = makemonadicnode(expr, ETYPCON);
- expr->rtype = type;
- expr->flags = cv;
- return expr;
-
- case TYPEPOINTER:
- switch (expr->rtype->type) {
- case TYPEENUM:
- expr->rtype = TYPE_ENUM(expr->rtype)->enumtype;
- case TYPEINT:
- 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 = cv;
- return expr;
-
- case TYPEPOINTER:
- 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, flag2);
- if (!ENODE_IS(expr, ETYPCON))
- expr = makemonadicnode(expr, ETYPCON);
- expr->rtype = type;
- expr->flags = cv;
- return expr;
- }
- break;
-
- case TYPEMEMBERPOINTER:
- if (!IS_TYPE_MEMBERPOINTER(expr->rtype))
- expr = CExpr_MemberPointerConversion(expr, TYPE_MEMBER_POINTER(type), 1);
-
- if (IS_TYPE_MEMBERPOINTER(expr->rtype)) {
- expr = PointerToMemberCast(expr, TYPE_MEMBER_POINTER(expr->rtype), TYPE_MEMBER_POINTER(type), flag2);
- expr->flags = cv;
- return expr;
- }
- break;
- }
- }
-
- if (isExplicit) {
- if ((newExpr = CodeGen_HandleTypeCast(expr, type, qual)))
- return newExpr;
- }
-
- CError_Error(
- isExplicit ? CErrorStr247 : CErrorStr209,
- expr->rtype, ENODE_QUALS(expr),
- type, qual);
- return nullnode();
-}
-
-ENode *CExpr_AssignmentPromotion(ENode *expr, Type *type2, UInt32 qual2, Boolean flag) {
- ImplicitConv result;
-
- if (copts.old_argmatch)
- return oldassignmentpromotion(expr, type2, qual2, flag);
-
- if (ENODE_IS(expr, EMEMBER))
- expr = getpointertomemberfunc(expr, type2, 1);
-
- if (!CExpr_ImplicitConversionMatch(expr, type2, qual2, &result)) {
- CError_Error(CErrorStr209, expr->rtype, ENODE_QUALS(expr), type2, qual2);
- return nullnode();
- }
-
- return CExpr_Convert(expr, type2, qual2, 0, flag);
-}
-
-static Boolean CExpr_IsBetterMatch(Match *a, Match *b, int count) {
- ImplicitConv *convA;
- ImplicitConv *convB;
- int i;
- Boolean flag;
-
- convA = a->conv;
- convB = b->conv;
- flag = 0;
-
- if (convA->type != ICT_0 && convB->type != ICT_0) {
- if (CExpr_IsBetterImplicitConv(convB, convA))
- return 0;
- if (CExpr_IsBetterImplicitConv(convA, convB))
- flag = 1;
- }
-
- for (i = 0; i < count; i++) {
- if (CExpr_IsBetterImplicitConv(++convB, ++convA))
- return 0;
- if (CExpr_IsBetterImplicitConv(convA, convB))
- flag = 1;
- }
-
- if (flag)
- return 1;
-
- if (b->object) {
- CError_ASSERT(2165, IS_TYPE_FUNC(b->object->type));
- if (b->object->u.func.inst) {
- if (!a->object)
- return 1;
-
- CError_ASSERT(2169, IS_TYPE_FUNC(a->object->type));
- if (!a->object->u.func.inst)
- return 1;
-
- CError_ASSERT(2174, a->specialfunc && b->specialfunc);
- if (CTempl_FuncIsMoreSpecialized(a->specialfunc, b->specialfunc))
- return 1;
- }
- }
-
- return 0;
-}
-
-static Boolean CExpr_MatchArgs(Object *func, ENodeList *argexprs, ENode *expr, ImplicitConv *convs) {
- FuncArg *args;
- ENode *newExpr;
- Type *type;
-
- args = TYPE_FUNC(func->type)->args;
-
- if (!(TYPE_FUNC(func->type)->flags & FUNC_METHOD)) {
- convs->type = ICT_0;
- } else if (TYPE_METHOD(func->type)->is_static) {
- convs->type = ICT_0;
- } else if (TYPE_FUNC(func->type)->flags & FUNC_IS_CTOR) {
- convs->type = ICT_0;
- args = args->next;
- } else {
- if (!expr)
- return 0;
-
- newExpr = lalloc(sizeof(ENode));
- newExpr->type = EINTCONST;
- newExpr->cost = 0;
- newExpr->flags = expr->flags;
- newExpr->rtype = CDecl_NewPointerType(expr->rtype);
- newExpr->data.intval = cint64_zero;
-
- if (func->datatype == DALIAS) {
- CError_ASSERT(2231, func->u.alias.member);
- type = CDecl_NewPointerType(func->u.alias.member->type);
- } else {
- type = args->type;
- }
-
- if (!CExpr_ImplicitConversionMatch(newExpr, type, args->qual, convs))
- return 0;
- args = args->next;
- }
-
- convs++;
- while (1) {
- if (!args || args->type == &stvoid) {
- if (argexprs)
- return 0;
- else
- return 1;
- }
-
- if (args == &elipsis || args == &oldstyle) {
- while (argexprs) {
- convs->type = ICT_1;
- argexprs = argexprs->next;
- convs++;
- }
- return 1;
- }
-
- if (!argexprs)
- return args->dexpr != NULL;
-
- if (!CExpr_ImplicitConversionMatch(argexprs->node, args->type, args->qual, convs))
- return 0;
-
- argexprs = argexprs->next;
- args = args->next;
- convs++;
- }
-}
-
-static Object *CExpr_GetMatchObject(Match *match, HashNameNode *name) {
- Object *object;
- FuncArg *arg;
- TypeFunc *tfunc;
-
- if (match->object)
- return match->object;
-
- tfunc = lalloc(sizeof(TypeFunc));
- memclrw(tfunc, sizeof(TypeFunc));
- tfunc->type = TYPEFUNC;
- tfunc->functype = &stvoid;
-
- arg = lalloc(sizeof(FuncArg));
- memclrw(arg, sizeof(FuncArg));
- arg->type = match->type;
- arg->qual = match->qual;
- tfunc->args = arg;
-
- if (match->type2) {
- arg = lalloc(sizeof(FuncArg));
- memclrw(arg, sizeof(FuncArg));
- arg->type = match->type2;
- arg->qual = match->qual2;
- tfunc->args->next = arg;
- }
-
- object = lalloc(sizeof(Object));
- memclrw(object, sizeof(Object));
- object->name = name;
- object->datatype = DFUNC;
- object->nspace = cscope_root;
- object->type = TYPE(tfunc);
- return object;
-}
-
-static Match *CExpr_FindBestMatch(Match *matches, int count, HashNameNode *name, ObjectList **outList, ENodeList *argExprs) {
- Match *scan;
- Match *best;
- ObjectList *listHead;
- ObjectList *list;
-
- best = matches;
- for (scan = matches->next; scan; scan = scan->next) {
- if (CExpr_IsBetterMatch(scan, best, count))
- best = scan;
- }
-
- for (scan = matches, listHead = NULL; scan; scan = scan->next) {
- if (scan != best && !CExpr_IsBetterMatch(best, scan, count)) {
- list = lalloc(sizeof(ObjectList));
- list->next = listHead;
- list->object = CExpr_GetMatchObject(scan, name);
- listHead = list;
- }
- }
-
- if (!outList) {
- if (listHead)
- CError_OverloadedFunctionError(CExpr_GetMatchObject(best, name), listHead);
- } else {
- *outList = listHead;
- }
-
- return best;
-}
-
-void CExpr_FuncArgMatch(NameSpaceObjectList *list, TemplArg *templargs, ENodeList *argexprs, Match13 *match13, ENode *expr, Boolean flag) {
- NameSpaceObjectList *i;
- NameSpaceObjectList *j;
- Match *match;
- Match *matches;
- Object *object;
- Object *object2;
- Object *specialfunc;
- ENodeList *argscan;
- int argcount;
-
- for (argscan = argexprs, argcount = 0; argscan; argscan = argscan->next) {
- CDecl_CompleteType(argscan->node->rtype);
- argcount++;
- }
-
- matches = NULL;
- match = lalloc(sizeof(Match) + ((argcount - 2) * sizeof(ImplicitConv)));
-
- for (i = list; i; i = i->next) {
- object = OBJECT(i->object);
- if (
- object->otype == OT_OBJECT &&
- IS_TYPE_FUNC(object->type) &&
- (!flag || !(object->qual & Q_EXPLICIT))
- )
- {
- if (object->datatype == DALIAS && (TYPE_FUNC(object->type)->flags & FUNC_METHOD)) {
- for (j = list; j; j = j->next) {
- if (j == i)
- continue;
-
- object2 = OBJECT(j->object);
- if (
- object2->otype == OT_OBJECT &&
- IS_TYPE_METHOD(object2->type) &&
- (TYPE_FUNC(object2->type)->flags & FUNC_FLAGS_CV) == (TYPE_FUNC(object->type)->flags & FUNC_FLAGS_CV)
- )
- {
- FuncArg *argsA;
- FuncArg *argsB;
- argsA = TYPE_FUNC(object->type)->args;
- if (argsA && !TYPE_METHOD(object->type)->is_static)
- argsA = argsA->next;
- argsB = TYPE_FUNC(object2->type)->args;
- if (argsB && !TYPE_METHOD(object2->type)->is_static)
- argsB = argsB->next;
- if (is_arglistsame(argsA, argsB))
- break;
- }
- }
-
- if (j)
- continue;
- }
-
- if (TYPE_FUNC(object->type)->flags & FUNC_IS_TEMPL) {
- specialfunc = object;
- object = CTempl_DeduceFromFunctionCall(object, templargs, argexprs);
- if (!object)
- continue;
- } else {
- if (templargs)
- continue;
- specialfunc = NULL;
- }
-
- if (CExpr_MatchArgs(object, argexprs, expr, match->conv)) {
- match->object = object;
- match->specialfunc = specialfunc;
- match->next = matches;
- matches = match;
- match = lalloc(sizeof(Match) + ((argcount - 2) * sizeof(ImplicitConv)));
- }
- }
- }
-
- if (matches) {
- matches = CExpr_FindBestMatch(matches, argcount, NULL, &match13->list, argexprs);
- match13->obj = matches->object;
- }
-}
-
-static ConversionTypeList *CExpr_BuildConversionTypeList(ENode *expr) {
- ConversionTypeList *first;
- ConversionTypeList *list;
- Object *object;
- Type *type;
- ConversionIterator convIter;
-
- if (!IS_TYPE_CLASS(expr->rtype)) {
- first = lalloc(sizeof(ConversionTypeList));
- first->next = NULL;
- first->func = NULL;
- first->type = expr->rtype;
- first->qual = ENODE_QUALS(expr);
- if (IS_TYPE_ENUM(first->type))
- first->qual = 0;
- } else {
- first = NULL;
- CExpr_ConversionIteratorInit(&convIter, TYPE_CLASS(expr->rtype));
- while ((object = CExpr_ConversionIteratorNext(&convIter))) {
- type = TYPE_FUNC(object->type)->functype;
- if (IS_TYPE_REFERENCE(type))
- type = TPTR_TARGET(type);
-
- if (!IS_TYPE_CLASS(type)) {
- list = lalloc(sizeof(ConversionTypeList));
- list->next = first;
- list->func = object;
- list->type = type;
- list->qual = TYPE_FUNC(object->type)->qual & Q_CV;
- first = list;
- }
- }
- }
-
- return first;
-}
-
-static Type *CExpr_NextPromotedIntegralType(int *p) {
- switch (++(*p)) {
- case 1: return TYPE(&stsignedint);
- case 2: return TYPE(&stunsignedint);
- case 3: return TYPE(&stsignedlong);
- case 4: return TYPE(&stunsignedlong);
- case 5:
- if (copts.longlong)
- return TYPE(&stsignedlonglong);
- else
- return NULL;
- case 6:
- if (copts.longlong)
- return TYPE(&stunsignedlonglong);
- else
- return NULL;
- }
-
- return NULL;
-}
-
-static Type *CExpr_NextArithmeticType(int *p) {
- switch (++(*p)) {
- case 1: return TYPE(&stbool);
- case 2: return TYPE(&stchar);
- case 3: return TYPE(&stsignedchar);
- case 4: return TYPE(&stunsignedchar);
- case 5: return TYPE(&stwchar);
- case 6: return TYPE(&stsignedshort);
- case 7: return TYPE(&stunsignedshort);
- case 8: return TYPE(&stsignedint);
- case 9: return TYPE(&stunsignedint);
- case 10: return TYPE(&stsignedlong);
- case 11: return TYPE(&stunsignedlong);
- case 12: return TYPE(&stfloat);
- case 13: return TYPE(&stdouble);
- case 14: return TYPE(&stlongdouble);
- case 15:
- if (copts.longlong)
- return TYPE(&stsignedlonglong);
- else
- return NULL;
- case 16:
- if (copts.longlong)
- return TYPE(&stunsignedlonglong);
- else
- return NULL;
- }
-
- return NULL;
-}
-
-static Type *CExpr_NextPromotedArithmeticType(int *p) {
- switch (++(*p)) {
- case 1: return TYPE(&stsignedint);
- case 2: return TYPE(&stunsignedint);
- case 3: return TYPE(&stsignedlong);
- case 4: return TYPE(&stunsignedlong);
- case 5: return TYPE(&stdouble);
- case 6: return TYPE(&stlongdouble);
- case 7:
- if (copts.longlong)
- return TYPE(&stsignedlonglong);
- else
- return NULL;
- case 8:
- if (copts.longlong)
- return TYPE(&stunsignedlonglong);
- else
- return NULL;
- }
-
- return NULL;
-}
-
-static Match *CExpr_MatchBuiltin(Match *matches, ENode *left, Type *leftType, UInt32 leftQual, ENode *right, Type *rightType, UInt32 rightQual) {
- Match *scan;
- Match mymatch;
-
- if (CExpr_ImplicitConversionMatch(left, leftType, leftQual, &mymatch.conv[0])) {
- if (!right || CExpr_ImplicitConversionMatch(right, rightType, rightQual, &mymatch.conv[1])) {
- if (right) {
- for (scan = matches; scan; scan = scan->next) {
- if (
- !scan->object &&
- is_typesame(scan->type, leftType) &&
- scan->qual == leftQual &&
- is_typesame(scan->type2, rightType) &&
- scan->qual2 == rightQual
- )
- return matches;
- }
- }
-
- mymatch.next = matches;
- mymatch.object = NULL;
- mymatch.specialfunc = NULL;
- mymatch.type = leftType;
- mymatch.qual = leftQual;
- mymatch.type2 = rightType;
- mymatch.qual2 = rightQual;
-
- matches = lalloc(sizeof(Match));
- *matches = mymatch;
- }
- }
-
- return matches;
-}
-
-static Match *CExpr_CheckIncDecBuiltin(Match *matches, short token, ENode *expr1, ENode *expr2) {
- Object *object;
- Type *type;
- TypeFunc *tfunc;
- ConversionIterator convIter;
-
- if (IS_TYPE_CLASS(expr1->rtype)) {
- CExpr_ConversionIteratorInit(&convIter, TYPE_CLASS(expr1->rtype));
- while ((object = CExpr_ConversionIteratorNext(&convIter))) {
- tfunc = TYPE_FUNC(object->type);
- if (IS_TYPE_REFERENCE(tfunc->functype)) {
- type = TPTR_TARGET(tfunc->functype);
- switch (type->type) {
- case TYPEINT:
- if (type == TYPE(&stbool) && token == TK_DECREMENT)
- break;
- case TYPEFLOAT:
- case TYPEPOINTER:
- if (!CParser_IsConst(type, tfunc->qual)) {
- matches = CExpr_MatchBuiltin(
- matches,
- expr1, type, tfunc->qual,
- expr2, expr2 ? TYPE(&stsignedint) : NULL, 0
- );
- }
- break;
- }
- }
- }
- }
-
- return matches;
-}
-
-static Match *CExpr_CheckUnaryBuiltin(Match *matches, short token, ENode *expr) {
- ConversionTypeList *typelist;
- Type *type;
- int typenum;
-
- switch (token) {
- case TK_INCREMENT:
- case TK_DECREMENT:
- return CExpr_CheckIncDecBuiltin(matches, token, expr, NULL);
-
- case '!':
- matches = CExpr_MatchBuiltin(matches, expr, TYPE(&stbool), 0, NULL, NULL, 0);
- break;
-
- case '~':
- typenum = 0;
- while ((type = CExpr_NextPromotedIntegralType(&typenum))) {
- matches = CExpr_MatchBuiltin(matches, expr, type, 0, NULL, NULL, 0);
- }
- break;
-
- case '*':
- case '+':
- for (typelist = CExpr_BuildConversionTypeList(expr); typelist; typelist = typelist->next) {
- if (IS_TYPE_POINTER_ONLY(typelist->type))
- matches = CExpr_MatchBuiltin(matches, expr, typelist->type, typelist->qual, NULL, NULL, 0);
- }
- if (token != '+')
- break;
-
- case '-':
- typenum = 0;
- while ((type = CExpr_NextPromotedArithmeticType(&typenum))) {
- matches = CExpr_MatchBuiltin(matches, expr, type, 0, NULL, NULL, 0);
- }
- break;
- }
-
- return matches;
-}
-
-static Match *CExpr_CheckBinaryBuiltin(Match *matches, ENode *left, short token, ENode *right) {
- int typenum1;
- int typenum2;
- Type *type1;
- Type *type2;
- Type *ptrdiff;
- Boolean allowPtrDiffOnRight;
- Boolean allowPtrCV;
- Boolean allowPtrDiffOnLeft;
- Boolean allowMemberPtrs;
- Boolean allowEnum;
- ConversionTypeList *leftList;
- ConversionTypeList *rightList;
- ConversionTypeList *scan;
-
- switch (token) {
- case TK_INCREMENT:
- case TK_DECREMENT:
- return CExpr_CheckIncDecBuiltin(matches, token, left, right);
-
- case '*':
- case '+':
- case '-':
- case '/':
- case ':':
- case '<':
- case '>':
- case TK_LOGICAL_EQ:
- case TK_LOGICAL_NE:
- case TK_LESS_EQUAL:
- case TK_GREATER_EQUAL:
- typenum1 = 0;
- while ((type1 = CExpr_NextPromotedArithmeticType(&typenum1))) {
- typenum2 = 0;
- while ((type2 = CExpr_NextPromotedArithmeticType(&typenum2))) {
- matches = CExpr_MatchBuiltin(matches, left, type1, 0, right, type2, 0);
- }
- }
- break;
-
- case '%':
- case '&':
- case '^':
- case '|':
- case TK_SHL:
- case TK_SHR:
- typenum1 = 0;
- while ((type1 = CExpr_NextPromotedIntegralType(&typenum1))) {
- typenum2 = 0;
- while ((type2 = CExpr_NextPromotedIntegralType(&typenum2))) {
- matches = CExpr_MatchBuiltin(matches, left, type1, 0, right, type2, 0);
- }
- }
- return matches;
-
- case TK_LOGICAL_OR:
- case TK_LOGICAL_AND:
- return CExpr_MatchBuiltin(matches, left, TYPE(&stbool), 0, right, TYPE(&stbool), 0);
- }
-
- allowEnum = 0;
- allowMemberPtrs = 0;
- allowPtrCV = 0;
- allowPtrDiffOnLeft = 0;
- allowPtrDiffOnRight = 0;
-
- switch (token) {
- case '+':
- case '[':
- allowPtrDiffOnLeft = 1;
- allowPtrDiffOnRight = 1;
- break;
- case '-':
- allowPtrCV = 1;
- allowPtrDiffOnRight = 1;
- break;
- case ':':
- case TK_LOGICAL_EQ:
- case TK_LOGICAL_NE:
- allowMemberPtrs = 1;
- case '<':
- case '>':
- case TK_LESS_EQUAL:
- case TK_GREATER_EQUAL:
- allowPtrCV = 1;
- allowEnum = 1;
- break;
- default:
- return matches;
- }
-
- leftList = CExpr_BuildConversionTypeList(left);
- rightList = CExpr_BuildConversionTypeList(right);
- ptrdiff = CABI_GetPtrDiffTType();
-
- for (scan = leftList; ; scan = scan->next) {
- if (!scan) {
- scan = rightList;
- if (!rightList)
- break;
- rightList = NULL;
- }
-
- type1 = scan->type;
- if (IS_TYPE_REFERENCE(type1))
- type1 = TPTR_TARGET(type1);
-
- switch (type1->type) {
- case TYPEENUM:
- if (allowEnum)
- matches = CExpr_MatchBuiltin(matches, left, type1, scan->qual, right, type1, scan->qual);
- break;
-
- case TYPEPOINTER:
- if (allowPtrDiffOnRight)
- matches = CExpr_MatchBuiltin(matches, left, type1, scan->qual, right, ptrdiff, 0);
- if (allowPtrDiffOnLeft)
- matches = CExpr_MatchBuiltin(matches, left, ptrdiff, 0, right, type1, scan->qual);
- if (allowPtrCV) {
- if (IS_TYPE_POINTER_ONLY(TPTR_TARGET(type1))) {
- type2 = galloc(sizeof(TypePointer));
- *TYPE_POINTER(type2) = *TYPE_POINTER(type1);
- TPTR_QUAL(type2) |= Q_CONST | Q_VOLATILE;
- matches = CExpr_MatchBuiltin(matches, left, type2, scan->qual, right, type2, scan->qual);
- } else {
- matches = CExpr_MatchBuiltin(matches, left, type1, Q_CONST | Q_VOLATILE, right, type1, Q_CONST | Q_VOLATILE);
- }
- }
- break;
-
- case TYPEMEMBERPOINTER:
- if (allowMemberPtrs)
- matches = CExpr_MatchBuiltin(matches, left, type1, scan->qual, right, type1, scan->qual);
- break;
- }
- }
-
- return matches;
-}
-
-static Boolean CExpr_MatchOperands(ENode *left, Type *leftType, UInt32 leftQual, ENode *right, Type *rightType, UInt32 rightQual, ImplicitConv *twoResults, Boolean flag) {
- if (flag) {
- if (!CExpr_StandardConversionMatch(left, leftType, leftQual, 1, &twoResults[0].u.ic3.standardConv))
- return 0;
- twoResults[0].type = ICT_3;
- } else {
- if (!CExpr_ImplicitConversionMatch(left, leftType, leftQual, &twoResults[0]))
- return 0;
- }
-
- if (right) {
- if (!CExpr_ImplicitConversionMatch(right, rightType, rightQual, &twoResults[1]))
- return 0;
- }
-
- return 1;
-}
-
-Boolean CExpr_CondOperatorMatch(ENode *left, ENode *right, Conversion *conv) {
- Match *match;
-
- if ((match = CExpr_CheckBinaryBuiltin(NULL, left, ':', right))) {
- match = CExpr_FindBestMatch(match, 1, GetHashNameNode("operator?:"), NULL, NULL);
- CError_ASSERT(2931, !match->object);
-
- conv->x0 = NULL;
- conv->left = CExpr_Convert(left, match->type, match->qual, 0, 1);
- conv->right = CExpr_Convert(right, match->type2, match->qual2, 0, 1);
- return 1;
- }
-
- return 0;
-}
-
-Boolean CExpr_OperatorMatch(short token, ENode *left, ENode *right, Conversion *conv) {
- HashNameNode *name;
- ENodeList *argExprs;
- BClassList *path;
- int hasArg;
- Match *matches;
- Object *object;
- Object *specialfunc;
- NameSpaceObjectList *list;
- Type *leftType;
- UInt32 leftQual;
- Type *rightType;
- UInt32 rightQual;
- NameResult pr;
- NameSpaceObjectList myList;
- Match myMatch;
-
- if (!IS_TYPE_CLASS(left->rtype)) {
- if (!IS_TYPE_ENUM(left->rtype)) {
- if (!right || !(IS_TYPE_CLASS(right->rtype) || IS_TYPE_ENUM(right->rtype)))
- return 0;
- }
- } else {
- CDecl_CompleteType(left->rtype);
- }
-
- name = CMangler_OperatorName(token);
- path = NULL;
-
- argExprs = lalloc(sizeof(ENodeList));
- argExprs->node = left;
- if (right) {
- argExprs->next = lalloc(sizeof(ENodeList));
- argExprs->next->node = right;
- argExprs->next->next = NULL;
- hasArg = 1;
- } else {
- argExprs->next = NULL;
- hasArg = 0;
- }
-
- matches = NULL;
-
- if (IS_TYPE_CLASS(left->rtype) && CScope_FindClassMemberObject(TYPE_CLASS(left->rtype), &pr, name)) {
- if (token != '=' || (pr.bcl_18->type == left->rtype && !pr.bcl_18->next)) {
- if (pr.obj_10) {
- myList.next = NULL;
- myList.object = pr.obj_10;
- pr.nsol_14 = &myList;
- } else {
- CError_ASSERT(3009, pr.nsol_14);
- }
-
- for (list = pr.nsol_14; list; list = list->next) {
- object = OBJECT(list->object);
- if (object->otype == OT_OBJECT && IS_TYPE_FUNC(object->type)) {
- if (TYPE_FUNC(object->type)->flags & FUNC_IS_TEMPL) {
- specialfunc = object;
- object = CTempl_DeduceFromFunctionCall(object, NULL, argExprs->next);
- if (!object)
- continue;
- } else {
- specialfunc = NULL;
- }
-
- leftType = CExpr_GetImplictObjectParamType(object, &leftQual);
- if (right) {
- if (!CExpr_HasNParams(object, 1))
- continue;
- rightType = CExpr_GetParamType(object, 0, &rightQual);
- } else {
- if (!CExpr_HasNParams(object, 0))
- continue;
- }
-
- if (CExpr_MatchOperands(left, leftType, leftQual, right, rightType, rightQual, myMatch.conv, 1)) {
- myMatch.object = object;
- myMatch.specialfunc = specialfunc;
- myMatch.next = matches;
- matches = lalloc(sizeof(Match));
- *matches = myMatch;
- path = pr.bcl_18;
- }
- }
- }
- }
- }
-
- if (CScope_FindNonClassObject(cscope_current, &pr, name)) {
- if (pr.obj_10) {
- myList.next = NULL;
- myList.object = pr.obj_10;
- pr.nsol_14 = &myList;
- }
- } else {
- pr.nsol_14 = NULL;
- }
-
- if (copts.arg_dep_lookup)
- pr.nsol_14 = CScope_ArgumentDependentNameLookup(pr.nsol_14, name, argExprs, 1);
-
- for (list = pr.nsol_14; list; list = list->next) {
- object = OBJECT(list->object);
- if (object->otype == OT_OBJECT && IS_TYPE_NONMETHOD(object->type)) {
- if (TYPE_FUNC(object->type)->flags & FUNC_IS_TEMPL) {
- specialfunc = object;
- object = CTempl_DeduceFromFunctionCall(object, NULL, argExprs);
- if (!object)
- continue;
- } else {
- specialfunc = NULL;
- }
-
- leftType = CExpr_GetParamType(object, 0, &leftQual);
- if (right) {
- if (!CExpr_HasNParams(object, 2))
- continue;
- rightType = CExpr_GetParamType(object, 1, &rightQual);
- } else {
- if (!CExpr_HasNParams(object, 1))
- continue;
- }
-
- if (CExpr_MatchOperands(left, leftType, leftQual, right, rightType, rightQual, myMatch.conv, 0)) {
- myMatch.object = object;
- myMatch.specialfunc = specialfunc;
- myMatch.next = matches;
- matches = lalloc(sizeof(Match));
- *matches = myMatch;
- }
- }
- }
-
- if (right)
- matches = CExpr_CheckBinaryBuiltin(matches, left, token, right);
- else
- matches = CExpr_CheckUnaryBuiltin(matches, token, left);
-
- if (matches) {
- conv->x0 = NULL;
- conv->left = NULL;
- conv->right = NULL;
-
- matches = CExpr_FindBestMatch(matches, hasArg, name, NULL, argExprs);
- object = matches->object;
- if (!object) {
- if (IS_TYPE_CLASS(left->rtype))
- conv->left = CExpr_Convert(left, matches->type, matches->qual, 0, 1);
- else
- conv->left = left;
-
- if (right) {
- if (IS_TYPE_CLASS(right->rtype))
- conv->right = CExpr_Convert(right, matches->type2, matches->qual2, 0, 1);
- else
- conv->right = right;
- }
-
- return 1;
- }
-
- if (IS_TYPEFUNC_NONSTATIC_METHOD(TYPE_FUNC(object->type))) {
- CError_ASSERT(3125, path);
- left = CExpr_GenericFuncCall(path, argExprs->node, 0, object, NULL, NULL, argExprs->next, 0, 0, 1);
- } else {
- left = CExpr_GenericFuncCall(NULL, NULL, 0, object, NULL, NULL, argExprs, 0, 0, 1);
- }
-
- conv->x0 = checkreference(left);
- return 1;
- }
-
- return 0;
-}
-
-static ENode *CExpr_ClassCopyInit(TypeClass *tclass, ENode *expr1, ENode *expr2) {
- Object *best;
- NameSpaceObjectList *list;
- ObjectList *objlist;
- ObjectList *objlistEntry;
- ENodeList *argExprs;
- FuncArg *arg;
- Type *type;
- Object *object;
- ImplicitConv bestConv;
- ImplicitConv conv;
- BClassList path;
- ConversionIterator convIter;
-
- best = NULL;
- objlist = NULL;
-
- for (list = CClass_Constructor(tclass); list; list = list->next) {
- object = OBJECT(list->object);
- if (object->otype == OT_OBJECT && IS_TYPE_FUNC(object->type) && !(object->qual & Q_EXPLICIT)) {
- arg = TYPE_FUNC(object->type)->args;
-
- CError_ASSERT(3199, arg);
- arg = arg->next;
-
- if (tclass->flags & CLASS_HAS_VBASES) {
- CError_ASSERT(3203, arg);
- arg = arg->next;
- }
-
- if (
- arg &&
- arg != &elipsis &&
- (!arg->next || arg->next->dexpr) &&
- CExpr_ImplicitConversionMatch(expr2, arg->type, arg->qual, &conv)
- )
- {
- if (!best || CExpr_IsBetterImplicitConv(&conv, &bestConv)) {
- best = object;
- bestConv = conv;
- objlist = NULL;
- } else if (!CExpr_IsBetterImplicitConv(&bestConv, &conv)) {
- objlistEntry = lalloc(sizeof(ObjectList));
- objlistEntry->next = objlist;
- objlistEntry->object = object;
- objlist = objlistEntry;
- }
- }
- }
- }
-
- if (IS_TYPE_CLASS(expr2->rtype)) {
- CExpr_ConversionIteratorInit(&convIter, TYPE_CLASS(expr2->rtype));
- while ((object = CExpr_ConversionIteratorNext(&convIter))) {
- type = TYPE_FUNC(object->type)->functype;
- if (IS_TYPE_REFERENCE(type))
- type = TPTR_TARGET(type);
-
- if (
- IS_TYPE_CLASS(type) &&
- (tclass == TYPE_CLASS(type) || CClass_IsBaseClass(tclass, TYPE_CLASS(type), NULL, 0, 0))
- )
- {
- CError_ASSERT(3248, TYPE_FUNC(object->type)->args &&
- IS_TYPE_POINTER_ONLY(TYPE_FUNC(object->type)->args->type));
-
- type = galloc(sizeof(TypePointer));
- *TYPE_POINTER(type) = *TYPE_POINTER(TYPE_FUNC(object->type)->args->type);
- TPTR_QUAL(type) = Q_REFERENCE;
- if (CExpr_ImplicitConversionMatch(expr2, type, TYPE_FUNC(object->type)->args->qual, &conv)) {
- if (!best || CExpr_IsBetterImplicitConv(&conv, &bestConv)) {
- best = object;
- bestConv = conv;
- objlist = NULL;
- } else if (!CExpr_IsBetterImplicitConv(&bestConv, &conv)) {
- objlistEntry = lalloc(sizeof(ObjectList));
- objlistEntry->next = objlist;
- objlistEntry->object = object;
- objlist = objlistEntry;
- }
- }
- }
- }
- }
-
- if (objlist)
- CError_OverloadedFunctionError(best, objlist);
-
- if (!best) {
- CError_Error(CErrorStr209, expr2->rtype, ENODE_QUALS(expr2), tclass, 0);
- return expr1;
- }
-
- CError_ASSERT(3284, IS_TYPE_POINTER_ONLY(expr1->rtype));
-
- expr1 = makemonadicnode(expr1, EINDIRECT);
- expr1->rtype = TYPE(tclass);
-
- argExprs = lalloc(sizeof(ENodeList));
- argExprs->node = expr2;
- if (tclass->flags & CLASS_HAS_VBASES) {
- argExprs->next = lalloc(sizeof(ENodeList));
- argExprs->next->next = NULL;
- argExprs->next->node = intconstnode(TYPE(&stsignedshort), 1);
- } else {
- argExprs->next = NULL;
- }
-
- path.next = NULL;
- path.type = TYPE(tclass);
- expr1 = CExpr_GenericFuncCall(&path, expr1, 0, best, NULL, NULL, argExprs, 0, 0, 1);
-
- if (ENODE_IS2(expr1, EFUNCCALL, EFUNCCALLP))
- expr1->rtype = CDecl_NewPointerType(TYPE(tclass));
-
- expr1 = makemonadicnode(expr1, EINDIRECT);
- expr1->rtype = TYPE(tclass);
- return expr1;
-}