summaryrefslogtreecommitdiff
path: root/compiler_and_linker/unsorted/CRTTI.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/CRTTI.c
parentfc0c4c0df7b583b55a08317cf1ef6a71d27c0440 (diff)
downloadMWCC-main.tar.gz
MWCC-main.zip
move lots of source files around to match their actual placement in the original treemain
Diffstat (limited to 'compiler_and_linker/unsorted/CRTTI.c')
-rw-r--r--compiler_and_linker/unsorted/CRTTI.c940
1 files changed, 0 insertions, 940 deletions
diff --git a/compiler_and_linker/unsorted/CRTTI.c b/compiler_and_linker/unsorted/CRTTI.c
deleted file mode 100644
index 3881153..0000000
--- a/compiler_and_linker/unsorted/CRTTI.c
+++ /dev/null
@@ -1,940 +0,0 @@
-#include "compiler/CRTTI.h"
-#include "compiler/CClass.h"
-#include "compiler/CDecl.h"
-#include "compiler/CError.h"
-#include "compiler/CExpr.h"
-#include "compiler/CInit.h"
-#include "compiler/CInt64.h"
-#include "compiler/CMachine.h"
-#include "compiler/CMangler.h"
-#include "compiler/CParser.h"
-#include "compiler/CScope.h"
-#include "compiler/CompilerTools.h"
-#include "compiler/objects.h"
-#include "compiler/scopes.h"
-#include "compiler/types.h"
-#include "compiler/CPrepTokenizer.h"
-#include "compiler/CPrep.h"
-
-typedef struct Offset {
- struct Offset *next;
- SInt32 offset;
-} Offset;
-
-static Offset *crtti_offsets;
-static OLinkList *crtti_olinks;
-
-// forward decls
-static Object *CRTTI_ConstructTypeInfoObject(Type *type, UInt32 qual);
-
-typedef struct RTTISubClassList {
- struct RTTISubClassList *next;
- TypeClass *base;
- SInt32 voffset;
-} RTTISubClassList;
-
-typedef struct RTTIBaseList {
- struct RTTIBaseList *next;
- TypeClass *base;
- RTTISubClassList *subclasses;
- SInt32 voffset;
- short numsubclasses;
- Boolean x12;
- Boolean x13;
-} RTTIBaseList;
-
-static RTTIBaseList *CRTTI_CreateBaseList(TypeClass *tclass, TypeClass *tclassbase, RTTIBaseList *list, SInt32 voffset, Boolean flag) {
- RTTIBaseList *scan;
- ClassList *base;
- Boolean flag27;
- SInt32 newvoffset;
-
- if (tclass != tclassbase) {
- flag27 = 0;
-
- for (scan = list; scan; scan = scan->next) {
- if (scan->base == tclassbase) {
- if (scan->voffset == voffset) {
- if (!flag)
- scan->x12 = 0;
- flag27 = 0;
- } else {
- scan->x13 = 1;
- flag27 = 1;
- }
- break;
- }
- }
-
- if (!scan || flag27) {
- scan = lalloc(sizeof(RTTIBaseList));
- memclrw(scan, sizeof(RTTIBaseList));
-
- scan->next = list;
- list = scan;
- scan->base = tclassbase;
- scan->voffset = voffset;
- scan->x12 = flag;
- scan->x13 = flag27;
- }
- }
-
- for (base = tclassbase->bases; base; base = base->next) {
- if (base->is_virtual)
- newvoffset = CClass_VirtualBaseOffset(tclass, base->base);
- else
- newvoffset = voffset + base->offset;
-
- list = CRTTI_CreateBaseList(tclass, base->base, list, newvoffset, flag || base->access == ACCESSPRIVATE);
- }
-
- return list;
-}
-
-static void CRTTI_CreateSubClassList(TypeClass *tclass, RTTIBaseList *baselist, TypeClass *tclassbase, SInt32 voffset, Boolean flag) {
- ClassList *base;
- RTTISubClassList *scan;
- SInt32 newvoffset;
-
- if (baselist->base != tclassbase) {
- for (scan = baselist->subclasses; scan; scan = scan->next) {
- if (scan->base == tclassbase && scan->voffset == voffset)
- break;
- }
-
- if (!scan) {
- scan = lalloc(sizeof(RTTISubClassList));
- scan->next = baselist->subclasses;
- baselist->subclasses = scan;
-
- scan->base = tclassbase;
- scan->voffset = voffset;
- baselist->numsubclasses++;
- }
- }
-
- for (base = tclassbase->bases; base; base = base->next) {
- if (base->access == ACCESSPUBLIC) {
- if (base->is_virtual) {
- if (!flag)
- continue;
- newvoffset = CClass_VirtualBaseOffset(tclass, base->base);
- } else {
- newvoffset = voffset + base->offset;
- }
-
- CRTTI_CreateSubClassList(tclass, baselist, base->base, newvoffset, flag);
- }
- }
-}
-
-static Object *CRTTI_CreateBaseListObject(TypeClass *tclass) {
- RTTIBaseList *baselist;
- OLinkList *refs;
- Object *object;
- SInt32 *buf;
- SInt32 size;
- short count1;
- short count2;
- short total;
- OLinkList *ref;
- RTTIBaseList *scan;
- RTTISubClassList *subclass;
- SInt32 *work;
- SInt32 *work2;
-
- baselist = CRTTI_CreateBaseList(tclass, tclass, NULL, 0, 0);
- if (!baselist)
- return NULL;
-
- count1 = 0;
- count2 = 0;
- total = 0;
-
- for (scan = baselist; scan; scan = scan->next) {
- if (scan->x13 || scan->x12) {
- CRTTI_CreateSubClassList(tclass, scan, scan->base, scan->voffset, scan->x13 == 0);
- if (scan->numsubclasses) {
- total += scan->numsubclasses;
- count2++;
- }
- } else {
- count1++;
- }
- }
-
- if (!count1 && !count2)
- return NULL;
-
- size = (count1 + total) * 8 + count2 * 12 + 4;
- buf = lalloc(size);
- memclrw(buf, size);
-
- object = CParser_NewCompilerDefDataObject();
- object->name = CParser_GetUniqueName();
- object->type = CDecl_NewStructType(size, 4);
- object->qual = Q_CONST;
- object->sclass = TK_STATIC;
- refs = NULL;
-
- work = buf;
-
- if (count1) {
- for (scan = baselist; scan; scan = scan->next) {
- if (!scan->x12 && !scan->x13) {
- ref = lalloc(sizeof(OLinkList));
- ref->next = refs;
- refs = ref;
-
- ref->obj = CRTTI_ConstructTypeInfoObject(TYPE(scan->base), 0);
- ref->offset = ((char *) work) - ((char *) buf);
- ref->somevalue = 0;
-
- work[1] = CTool_EndianConvertWord32(scan->voffset);
- work += 2;
- }
- }
- }
-
- if (count2) {
- for (scan = baselist; scan; scan = scan->next) {
- if (scan->numsubclasses) {
- ref = lalloc(sizeof(OLinkList));
- ref->next = refs;
- refs = ref;
-
- ref->obj = CRTTI_ConstructTypeInfoObject(TYPE(scan->base), 0);
- ref->offset = ((char *) work) - ((char *) buf);
- ref->somevalue = 0;
-
- work[1] = CTool_EndianConvertWord32(scan->voffset | 0x80000000);
- work[2] = CTool_EndianConvertWord32(scan->numsubclasses);
- work2 = work + 3;
-
- for (subclass = scan->subclasses; subclass; subclass = subclass->next) {
- ref = lalloc(sizeof(OLinkList));
- ref->next = refs;
- refs = ref;
-
- ref->obj = CRTTI_ConstructTypeInfoObject(TYPE(subclass->base), 0);
- ref->offset = ((char *) work2) - ((char *) buf);
- ref->somevalue = 0;
-
- work2[1] = CTool_EndianConvertWord32(subclass->voffset);
- work2 += 2;
- }
-
- work = work2;
- }
- }
- }
-
- CInit_DeclareData(object, buf, refs, object->type->size);
- return object;
-}
-
-static Object *CRTTI_ConstructTypeInfoObject(Type *type, UInt32 qual) {
- Object *baselistobj;
- Object *nameobj;
- HashNameNode *rttiname;
- OLinkList *refs;
- char *namestr;
- int namelen;
- Object *object;
- NameSpaceObjectList *list;
- TypePointer tptr_copy;
- TypeMemberPointer tmemptr_copy;
- UInt32 data[2];
-
- switch (type->type) {
- case TYPEPOINTER:
- if (TPTR_QUAL(type) & (Q_CONST | Q_VOLATILE)) {
- tptr_copy = *TYPE_POINTER(type);
- tptr_copy.qual &= ~(Q_CONST | Q_VOLATILE);
- type = TYPE(&tptr_copy);
- }
- break;
- case TYPEMEMBERPOINTER:
- if (TYPE_MEMBER_POINTER(type)->qual & (Q_CONST | Q_VOLATILE)) {
- tmemptr_copy = *TYPE_MEMBER_POINTER(type);
- tmemptr_copy.qual &= ~(Q_CONST | Q_VOLATILE);
- type = TYPE(&tmemptr_copy);
- }
- break;
- default:
- qual = 0;
- }
-
- if (IS_TYPE_CLASS(type) && type->size == 0) {
- CDecl_CompleteType(type);
- if (!(TYPE_CLASS(type)->flags & CLASS_COMPLETED))
- CError_Error(CErrorStr136, type, 0);
- }
-
- rttiname = CMangler_RTTIObjectName(type, qual);
- list = CScope_FindName(cscope_root, rttiname);
-
- if (!list || (object = OBJECT(list->object))->otype != OT_OBJECT || object->datatype != DDATA) {
- namestr = CError_GetTypeName(type, qual, 0);
- namelen = strlen(namestr) + 1;
- nameobj = CInit_DeclareString(namestr, namelen, 0, 0);
-
- baselistobj = NULL;
- if (IS_TYPE_CLASS(type))
- baselistobj = CRTTI_CreateBaseListObject(TYPE_CLASS(type));
-
- memclrw(data, sizeof(data));
-
- object = CParser_NewCompilerDefDataObject();
- object->name = rttiname;
- object->type = CDecl_NewStructType(sizeof(data), 4);
- object->qual = Q_CONST;
- object->sclass = TK_STATIC;
-
- refs = lalloc(sizeof(OLinkList));
- refs->next = NULL;
- refs->obj = nameobj;
- refs->offset = 0;
- refs->somevalue = 0;
-
- if (baselistobj) {
- refs->next = lalloc(sizeof(OLinkList));
- refs->next->next = NULL;
- refs->next->obj = baselistobj;
- refs->next->offset = 4;
- refs->next->somevalue = 0;
- }
-
- CScope_AddGlobalObject(object);
- CInit_DeclareData(object, data, refs, object->type->size);
- }
-
- return object;
-}
-
-static void CRTTI_ConstructVTableHeader(TypeClass *tclass1, TypeClass *tclass2, Object *typeinfoObj, char *data, SInt32 offset, SInt32 voffset) {
- ClassList *base;
- Offset *o;
- OLinkList *olink;
- SInt32 tmp;
- SInt32 newoffset;
- SInt32 newvoffset;
-
- if (tclass2->vtable->owner == tclass2) {
- for (o = crtti_offsets; o; o = o->next) {
- if (o->offset == voffset)
- break;
- }
-
- if (!o) {
- o = lalloc(sizeof(Offset));
- o->next = crtti_offsets;
- o->offset = voffset;
- crtti_offsets = o;
-
- olink = lalloc(sizeof(OLinkList));
- olink->next = crtti_olinks;
- olink->obj = typeinfoObj;
- olink->offset = voffset;
- olink->somevalue = 0;
- crtti_olinks = olink;
-
- *((SInt32 *) (data + voffset + 4)) = CTool_EndianConvertWord32(-offset);
- } else {
- tmp = *((SInt32 *) (data + voffset + 4));
- CError_ASSERT(404, tmp == CTool_EndianConvertWord32(-offset));
- }
- }
-
- for (base = tclass2->bases; base; base = base->next) {
- if (base->base->vtable) {
- if (base->is_virtual) {
- newoffset = CClass_VirtualBaseOffset(tclass1, base->base);
- newvoffset = CClass_VirtualBaseVTableOffset(tclass1, base->base);
- } else {
- newoffset = offset + base->offset;
- newvoffset = voffset + base->voffset;
- }
-
- CRTTI_ConstructVTableHeader(tclass1, base->base, typeinfoObj, data, newoffset, newvoffset);
- }
- }
-}
-
-OLinkList *CRTTI_ConstructVTableHeaders(TypeClass *tclass, void *data, OLinkList *links) {
- crtti_offsets = NULL;
- crtti_olinks = links;
-
- CRTTI_ConstructVTableHeader(
- tclass, tclass,
- CRTTI_ConstructTypeInfoObject(TYPE(tclass), 0),
- data, 0, 0);
-
- return crtti_olinks;
-}
-
-static Type *CRTTI_FindTypeInfoType(void) {
- NameSpace *nspace;
- NameSpaceObjectList *list;
- Type *type;
-
- if ((list = CScope_FindName(cscope_root, GetHashNameNodeExport("std"))) && list->object->otype == OT_NAMESPACE)
- nspace = OBJ_NAMESPACE(list->object)->nspace;
- else
- nspace = cscope_root;
-
- type = CScope_GetLocalTagType(nspace, GetHashNameNodeExport("type_info"));
- if (type && IS_TYPE_CLASS(type) && type->size)
- return type;
-
- CError_Error(CErrorStr140, "::std::type_info");
- return TYPE(&stchar);
-}
-
-ENode *CRTTI_ParseTypeID(void) {
- ENode *expr;
- Type *type;
- Type *typeinfoType;
- UInt32 qual;
-
- if (!copts.RTTI)
- CError_Warning(CErrorStr257);
-
- typeinfoType = CRTTI_FindTypeInfoType();
-
- if (lex() != '(') {
- CError_Error(CErrorStr114);
- return nullnode();
- }
-
- tk = lex();
- if ((type = CParser_ParseTypeID(&qual, NULL))) {
- if (tk != ')')
- CError_ErrorSkip(CErrorStr115);
- else
- tk = lex();
-
- if (IS_TYPE_REFERENCE(type))
- type = TPTR_TARGET(type);
- } else {
- expr = s_expression();
-
- if (tk != ')')
- CError_ErrorSkip(CErrorStr115);
- else
- tk = lex();
-
- type = expr->rtype;
- qual = ENODE_QUALS(expr);
-
- if (IS_TYPE_REFERENCE(type))
- type = TPTR_TARGET(type);
-
- if (IS_TYPE_CLASS(type) && TYPE_CLASS(type)->vtable) {
- expr = funccallexpr(
- Rgtid_func,
- getnodeaddress(expr, 0),
- intconstnode(TYPE(&stsignedlong), TYPE_CLASS(type)->vtable->offset),
- NULL,
- NULL);
- expr->rtype = CDecl_NewPointerType(typeinfoType);
-
- expr = makemonadicnode(expr, EINDIRECT);
- expr->rtype = typeinfoType;
- expr->flags = ENODE_FLAG_CONST;
- return expr;
- }
- }
-
- expr = create_objectrefnode(CRTTI_ConstructTypeInfoObject(type, qual));
- expr = makemonadicnode(expr, EINDIRECT);
- expr->rtype = typeinfoType;
- expr->flags = ENODE_FLAG_CONST;
- return expr;
-}
-
-static void CRTTI_ConstCastQualCheck(UInt32 qual1, UInt32 qual2) {
- if (
- ((qual1 & Q_CONST) && !(qual2 & Q_CONST)) ||
- ((qual1 & Q_VOLATILE) && !(qual2 & Q_VOLATILE))
- )
- CError_Error(CErrorStr258);
-}
-
-static void CRTTI_ConstCastCheck(Type *type1, UInt32 qual1, Type *type2, UInt32 qual2) {
- Boolean flag = 1;
- if (IS_TYPE_REFERENCE(type2)) {
- type2 = TPTR_TARGET(type2);
- flag = 0;
- }
-
- while (1) {
- if (type1->type != type2->type)
- break;
-
- switch (type1->type) {
- case TYPEPOINTER:
- if (!flag)
- CRTTI_ConstCastQualCheck(TPTR_QUAL(type1), TPTR_QUAL(type2));
- type1 = TPTR_TARGET(type1);
- type2 = TPTR_TARGET(type2);
- flag = 0;
- continue;
-
- case TYPEMEMBERPOINTER:
- if (!flag)
- CRTTI_ConstCastQualCheck(TYPE_MEMBER_POINTER(type1)->qual, TYPE_MEMBER_POINTER(type2)->qual);
- type1 = TYPE_MEMBER_POINTER(type1)->ty1;
- type2 = TYPE_MEMBER_POINTER(type2)->ty1;
- flag = 0;
- continue;
- }
-
- break;
- }
-
- if (!flag && !IS_TYPE_FUNC(type1) && !IS_TYPE_FUNC(type2))
- CRTTI_ConstCastQualCheck(CParser_GetCVTypeQualifiers(type1, qual1), CParser_GetCVTypeQualifiers(type2, qual2));
-}
-
-static ENode *CRTTI_ParseCast(DeclInfo *di) {
- ENode *expr;
-
- if (lex() != '<') {
- CError_Error(CErrorStr230);
- return NULL;
- }
-
- tk = lex();
-
- memclrw(di, sizeof(DeclInfo));
- CParser_GetDeclSpecs(di, 0);
- scandeclarator(di);
-
- if (di->name)
- CError_Error(CErrorStr164);
-
- if (tk != '>') {
- CError_Error(CErrorStr231);
- return NULL;
- }
-
- if (lex() != '(') {
- CError_Error(CErrorStr114);
- return NULL;
- }
-
- tk = lex();
- expr = s_expression();
- if (!IS_TYPE_REFERENCE(di->thetype))
- expr = pointer_generation(expr);
-
- if (tk != ')') {
- CError_Error(CErrorStr115);
- return NULL;
- }
-
- tk = lex();
- return expr;
-}
-
-static void CRTTI_IncompleteCheck(Type *type) {
- if (IS_TYPE_POINTER_ONLY(type))
- type = TPTR_TARGET(type);
-
- if (IS_TYPE_CLASS(type) && type->size == 0) {
- CDecl_CompleteType(type);
- if (!(TYPE_CLASS(type)->flags & CLASS_COMPLETED))
- CError_Error(CErrorStr136, type, 0);
- }
-}
-
-static Boolean CRTTI_IsSameType(Type *a, Type *b) {
- while (1) {
- if (a->type != b->type)
- return 0;
-
- switch (a->type) {
- case TYPEVOID:
- return 1;
- case TYPEINT:
- case TYPEFLOAT:
- case TYPEENUM:
- case TYPESTRUCT:
- return a == b;
- case TYPEPOINTER:
- a = TPTR_TARGET(a);
- b = TPTR_TARGET(b);
- continue;
- default:
- return is_typesame(a, b);
- }
- }
-}
-
-static ENode *CRTTI_UniversalCast(ENode *expr, Type *type, UInt32 qual, UInt8 mode) {
- // type/qual are the target type
- Boolean isSimpleCast;
- Boolean needsTypcon;
- Boolean failed;
-
- if (ENODE_IS(expr, EOBJLIST))
- return CExpr_AssignmentPromotion(expr, type, qual & (Q_CONST | Q_VOLATILE), 1);
-
- isSimpleCast = needsTypcon = failed = 0;
-
- switch (type->type) {
- case TYPEINT:
- case TYPEENUM:
- if (mode == 2 && IS_TYPE_POINTER_ONLY(expr->rtype) && type != TYPE(&stbool))
- failed = 1;
- break;
-
- case TYPEPOINTER:
- if (TPTR_QUAL(type) & Q_REFERENCE) {
- if (
- !CRTTI_IsSameType(TPTR_TARGET(type), expr->rtype) &&
- mode == 2 &&
- !(
- IS_TYPE_CLASS(TPTR_TARGET(type)) &&
- IS_TYPE_CLASS(expr->rtype) &&
- (
- CClass_IsBaseClass(TYPE_CLASS(TPTR_TARGET(type)), TYPE_CLASS(expr->rtype), NULL, 0, 1) ||
- CClass_IsBaseClass(TYPE_CLASS(expr->rtype), TYPE_CLASS(TPTR_TARGET(type)), NULL, 0, 1)
- )
- )
- )
- {
- failed = 1;
- }
- } else if (IS_TYPE_POINTER_ONLY(expr->rtype)) {
- if (
- mode == 3 ||
- CRTTI_IsSameType(type, expr->rtype) ||
- IS_TYPE_VOID(TPTR_TARGET(type)) ||
- IS_TYPE_VOID(TPTR_TARGET(expr->rtype))
- )
- {
- isSimpleCast = needsTypcon = 1;
- }
- else if (
- mode == 2 &&
- !(
- IS_TYPE_CLASS(TPTR_TARGET(type)) &&
- IS_TYPE_CLASS(TPTR_TARGET(expr->rtype)) &&
- (
- CClass_IsBaseClass(TYPE_CLASS(TPTR_TARGET(type)), TYPE_CLASS(TPTR_TARGET(expr->rtype)), NULL, 0, 1) ||
- CClass_IsBaseClass(TYPE_CLASS(TPTR_TARGET(expr->rtype)), TYPE_CLASS(TPTR_TARGET(type)), NULL, 0, 1)
- )
- )
- )
- {
- failed = 1;
- }
- } else {
- if (IS_TYPE_ENUM(expr->rtype))
- expr->rtype = TYPE_ENUM(expr->rtype)->enumtype;
-
- if (IS_TYPE_INT(expr->rtype)) {
- if (ENODE_IS(expr, EINTCONST) && CInt64_IsZero(&expr->data.intval)) {
- isSimpleCast = 1;
- break;
- }
-
- if (mode != 2)
- break;
- }
-
- if (IS_TYPE_CLASS(expr->rtype)) {
- if (mode == 2)
- break;
- }
-
- failed = 1;
- }
- break;
- }
-
- if (failed) {
- CError_Error(CErrorStr247, expr->rtype, ENODE_QUALS(expr), type, qual);
- return expr;
- }
-
- if (isSimpleCast) {
- if (needsTypcon && ENODE_IS(expr, EINDIRECT) && (copts.pointercast_lvalue || !copts.ANSIstrict))
- expr = makemonadicnode(expr, ETYPCON);
-
- expr->rtype = type;
- expr->flags = qual & ENODE_FLAG_QUALS;
- return expr;
- }
-
- if (copts.old_argmatch)
- return do_typecast(expr, type, qual);
-
- return CExpr_Convert(expr, type, qual, 1, 1);
-}
-
-ENode *CRTTI_Parse_dynamic_cast(void) {
- Boolean isRef;
- ENode *expr;
- TypeClass *srcclass;
- TypeClass *destclass;
- ENode *typeinfo;
- DeclInfo di;
-
- expr = CRTTI_ParseCast(&di);
- if (!expr)
- return nullnode();
-
- if (!copts.RTTI)
- CError_Warning(CErrorStr257);
-
- CRTTI_ConstCastCheck(expr->rtype, expr->flags, di.thetype, di.qual);
- if (!IS_TYPE_POINTER_ONLY(di.thetype)) {
- CError_Error(CErrorStr164);
- return expr;
- }
-
- isRef = (TPTR_QUAL(di.thetype) & Q_REFERENCE) != 0;
-
- if (IS_TYPE_CLASS(TPTR_TARGET(di.thetype))) {
- destclass = TYPE_CLASS(TPTR_TARGET(di.thetype));
- CDecl_CompleteType(TYPE(destclass));
- if (!(destclass->flags & CLASS_COMPLETED)) {
- CError_Error(CErrorStr136, destclass, 0);
- return expr;
- }
- } else if (!IS_TYPE_VOID(TPTR_TARGET(di.thetype))) {
- CError_Error(CErrorStr164);
- return expr;
- } else {
- destclass = NULL;
- }
-
- if (isRef) {
- if (!IS_TYPE_CLASS(expr->rtype)) {
- CError_Error(CErrorStr164);
- return expr;
- }
-
- srcclass = TYPE_CLASS(expr->rtype);
- if (destclass) {
- if (srcclass == destclass || CClass_IsBaseClass(srcclass, destclass, NULL, 0, 1))
- return do_typecast(expr, di.thetype, di.qual);
- }
-
- expr = getnodeaddress(expr, 1);
- } else {
- if (!IS_TYPE_POINTER_ONLY(expr->rtype) || !IS_TYPE_CLASS(TPTR_TARGET(expr->rtype))) {
- CError_Error(CErrorStr164);
- return expr;
- }
-
- srcclass = TYPE_CLASS(TPTR_TARGET(expr->rtype));
- if (destclass) {
- if (srcclass == destclass || CClass_IsBaseClass(srcclass, destclass, NULL, 0, 1))
- return do_typecast(expr, di.thetype, di.qual);
- }
- }
-
- if (!(srcclass->flags & CLASS_COMPLETED)) {
- CError_Error(CErrorStr136, srcclass, 0);
- return expr;
- }
-
- if (!srcclass->vtable) {
- CError_Error(CErrorStr164);
- return expr;
- }
-
- if (srcclass->sominfo) {
- CError_Error(CErrorStr164);
- return expr;
- }
-
- if (destclass) {
- typeinfo = create_objectrefnode(CRTTI_ConstructTypeInfoObject(TYPE(destclass), 0));
- if (destclass->sominfo) {
- CError_Error(CErrorStr164);
- return expr;
- }
- } else {
- typeinfo = nullnode();
- }
-
- expr = CExpr_FuncCallSix(
- Rdync_func,
- expr,
- intconstnode(TYPE(&stsignedlong), srcclass->vtable->offset),
- typeinfo,
- create_objectrefnode(CRTTI_ConstructTypeInfoObject(TYPE(srcclass), 0)),
- intconstnode(TYPE(&stsignedshort), isRef),
- NULL
- );
-
- if (isRef) {
- expr->rtype = CDecl_NewPointerType(TYPE(destclass));
- expr = makemonadicnode(expr, EINDIRECT);
- expr->rtype = TYPE(destclass);
- } else {
- expr->rtype = di.thetype;
- }
- expr->flags = di.qual & ENODE_FLAG_QUALS;
- return expr;
-}
-
-ENode *CRTTI_Parse_static_cast(void) {
- ENode *expr;
- DeclInfo di;
-
- expr = CRTTI_ParseCast(&di);
- if (!expr)
- return nullnode();
-
- CRTTI_ConstCastCheck(expr->rtype, expr->flags, di.thetype, di.qual);
-
- if (IS_TYPE_REFERENCE(di.thetype)) {
- if (IS_TYPE_CLASS(expr->rtype) && CExpr_CanImplicitlyConvert(expr, di.thetype, di.qual)) {
- expr = CExpr_Convert(expr, di.thetype, di.qual, 0, 1);
- CError_ASSERT(959, IS_TYPE_POINTER_ONLY(expr->rtype));
-
- expr = makemonadicnode(expr, EINDIRECT);
- expr->rtype = TPTR_TARGET(di.thetype);
- expr->flags = di.qual & ENODE_FLAG_QUALS;
- return expr;
- }
- } else {
- if (CExpr_CanImplicitlyConvert(expr, di.thetype, di.qual))
- return CExpr_Convert(expr, di.thetype, di.qual, 1, 1);
- }
-
- if (!IS_TYPE_VOID(di.thetype) && !(IS_TYPE_POINTER_ONLY(expr->rtype) && IS_TYPE_VOID(TPTR_TARGET(expr->rtype)))) {
- CRTTI_IncompleteCheck(di.thetype);
- CRTTI_IncompleteCheck(expr->rtype);
- }
-
- return CRTTI_UniversalCast(expr, di.thetype, di.qual, 2);
-}
-
-ENode *CRTTI_Parse_reinterpret_cast(void) {
- ENode *expr;
- Type *origtype;
- ENode *lvalue;
- DeclInfo di;
-
- expr = CRTTI_ParseCast(&di);
- if (!expr)
- return nullnode();
-
- CRTTI_ConstCastCheck(expr->rtype, expr->flags, di.thetype, di.qual);
-
- if (IS_TYPE_REFERENCE(di.thetype)) {
- lvalue = CExpr_LValue(expr, 0, 1);
- if (!ENODE_IS(lvalue, EINDIRECT))
- return lvalue;
-
- lvalue->data.monadic->rtype = CDecl_NewPointerType(lvalue->rtype);
- expr = lvalue->data.monadic;
- origtype = di.thetype;
- di.thetype = CDecl_NewPointerType(TPTR_TARGET(di.thetype));
- } else {
- origtype = NULL;
- }
-
- switch (di.thetype->type) {
- case TYPEINT:
- switch (expr->rtype->type) {
- case TYPEMEMBERPOINTER:
- case TYPEPOINTER:
- expr = do_typecast(expr, di.thetype, di.qual);
- break;
- default:
- CError_Error(CErrorStr164);
- }
- break;
- case TYPEPOINTER:
- switch (expr->rtype->type) {
- case TYPEINT:
- case TYPEENUM:
- if (origtype)
- di.thetype = origtype;
- expr = do_typecast(expr, di.thetype, di.qual);
- break;
- case TYPEPOINTER:
- expr = makemonadicnode(expr, ETYPCON);
- expr->rtype = di.thetype;
- expr->flags = di.qual & ENODE_FLAG_QUALS;
- break;
- default:
- CError_Error(CErrorStr164);
- }
- break;
- case TYPEMEMBERPOINTER:
- if (IS_TYPE_MEMBERPOINTER(expr->rtype)) {
- if (IS_TYPE_FUNC(TYPE_MEMBER_POINTER(di.thetype)->ty1)) {
- if (IS_TYPE_FUNC(TYPE_MEMBER_POINTER(expr->rtype)->ty1)) {
- expr->rtype = di.thetype;
- expr->flags = di.qual & ENODE_FLAG_QUALS;
- break;
- }
- } else {
- if (!IS_TYPE_FUNC(TYPE_MEMBER_POINTER(expr->rtype)->ty1)) {
- expr->rtype = di.thetype;
- expr->flags = di.qual & ENODE_FLAG_QUALS;
- break;
- }
- }
- }
- expr = do_typecast(expr, di.thetype, di.qual);
- break;
- default:
- CError_Error(CErrorStr164);
- }
-
- if (origtype && IS_TYPE_POINTER_ONLY(expr->rtype)) {
- expr = makemonadicnode(expr, EINDIRECT);
- expr->rtype = TPTR_TARGET(di.thetype);
- }
-
- return expr;
-}
-
-ENode *CRTTI_Parse_const_cast(void) {
- DeclInfo di;
- ENode *expr;
-
- if (!(expr = CRTTI_ParseCast(&di)))
- return nullnode();
-
- if (IS_TYPE_POINTER_ONLY(di.thetype)) {
- if (TPTR_QUAL(di.thetype) & Q_REFERENCE) {
- if (!iscpp_typeequal(TPTR_TARGET(di.thetype), expr->rtype))
- CError_Error(CErrorStr164);
-
- if (ENODE_IS(expr, EINDIRECT)) {
- expr->rtype = TPTR_TARGET(di.thetype);
- expr->flags = di.qual & ENODE_FLAG_QUALS;
- } else {
- CError_Error(CErrorStr142);
- }
- } else {
- if (!iscpp_typeequal(di.thetype, expr->rtype))
- CError_Error(CErrorStr164);
-
- expr = do_typecast(expr, di.thetype, di.qual);
- }
- } else if (IS_TYPE_MEMBERPOINTER(di.thetype)) {
- if (!iscpp_typeequal(di.thetype, expr->rtype))
- CError_Error(CErrorStr164);
-
- expr = do_typecast(expr, di.thetype, di.qual);
- } else {
- if (!is_typesame(di.thetype, expr->rtype))
- CError_Error(CErrorStr164);
- else
- expr = do_typecast(expr, di.thetype, di.qual);
- }
-
- return expr;
-}