diff options
Diffstat (limited to 'compiler_and_linker/unsorted/CClass.c')
-rw-r--r-- | compiler_and_linker/unsorted/CClass.c | 2312 |
1 files changed, 0 insertions, 2312 deletions
diff --git a/compiler_and_linker/unsorted/CClass.c b/compiler_and_linker/unsorted/CClass.c deleted file mode 100644 index fad276e..0000000 --- a/compiler_and_linker/unsorted/CClass.c +++ /dev/null @@ -1,2312 +0,0 @@ -#include "compiler/CClass.h" -#include "compiler/CABI.h" -#include "compiler/CDecl.h" -#include "compiler/CError.h" -#include "compiler/CExpr.h" -#include "compiler/CInit.h" -#include "compiler/CInline.h" -#include "compiler/CMachine.h" -#include "compiler/CMangler.h" -#include "compiler/CObjC.h" -#include "compiler/CParser.h" -#include "compiler/CRTTI.h" -#include "compiler/CSOM.h" -#include "compiler/CompilerTools.h" -#include "compiler/CodeGen.h" -#include "compiler/objects.h" -#include "compiler/scopes.h" - -#ifdef __MWERKS__ -#pragma options align=mac68k -#endif -typedef struct OVClassBase { - struct OVClassBase *next; - struct OVClass *ovclass; - Boolean is_virtual; -} OVClassBase; - -typedef struct OVFunc { - struct OVFunc *next; - Object *obj; - struct OVClass *ovc8; - struct OVFunc *ovfC; - struct OVFunc *ovf10; -} OVFunc; - -typedef struct OVClass { - TypeClass *tclass; - OVFunc *vfuncs; - OVClassBase *bases; - SInt32 offset; - SInt32 voffset; - Boolean alloced_vtable; -} OVClass; - -typedef struct ThunkList { - struct ThunkList *next; - Object *thunkobj; - Object *obj; - SInt32 a; - SInt32 b; - SInt32 c; -} ThunkList; -#ifdef __MWERKS__ -#pragma options align=reset -#endif - -static TypeClass *main_class; -static ThunkList *cclass_thunklist; -static TypeClass *cclass_isbase_mostderived; -static SInt32 cclass_isbase_foundoffset; -static Boolean cclass_isambigbase; -static short cclass_founddepth; -static char *vtable_object_data; -static SInt32 vtable_data_size; -static OLinkList *vtable_object_links; -static TypeClass *cclass_vbase; -static OVClass *cclass_ovbase; -static OVClass *cclass_root; -static Object *found_pure; -static Boolean check_pures; -static Object *cclass_dominator_vobject; -static SInt32 cclass_dominator_voffset; -static Object *cclass_dominator_oobject; -static TypeClass *cclass_dominator_oclass; -static SInt32 cclass_dominator_ooffset; -static Object *cclass_dominator_eobject; - -void CClass_Init(void) { - cclass_thunklist = NULL; -} - -void CClass_GenThunks(void) { - ThunkList *list; - - for (list = cclass_thunklist; list; list = list->next) { - list->thunkobj->flags |= OBJECT_DEFINED; - CodeGen_GenVDispatchThunk(list->thunkobj, list->obj, list->a, list->b, list->c); - } -} - -static Object *CClass_ThunkObject(Object *obj, SInt32 a, SInt32 b, SInt32 c) { - Object *thunkobj; - ThunkList *list; - - CInline_ObjectAddrRef(obj); - for (list = cclass_thunklist; list; list = list->next) { - if (obj == list->obj && a == list->a && b == list->b && c == list->c) - return list->thunkobj; - } - - thunkobj = CParser_NewCompilerDefFunctionObject(); - thunkobj->name = CMangler_ThunkName(obj, a, b, c); - thunkobj->type = TYPE(&rt_func); - thunkobj->sclass = TK_EXTERN; - thunkobj->qual = Q_20000; - thunkobj->u.func.linkname = thunkobj->name; - - list = galloc(sizeof(ThunkList)); - list->thunkobj = thunkobj; - list->obj = obj; - list->a = a; - list->b = b; - list->c = c; - list->next = cclass_thunklist; - cclass_thunklist = list; - - return thunkobj; -} - -static Boolean CClass_IsZeroOffsetClass(TypeClass *a, TypeClass *b) { - while (1) { - if (a == b) - return 1; - - if (!a->bases || a->bases->is_virtual) - return 0; - - a = a->bases->base; - } -} - -static UInt8 CClass_IsCovariantResult(Type *a, UInt32 qualA, Type *b, UInt32 qualB, Boolean errorflag) { - TypeClass *tclassA; - TypeClass *tclassB; - - if ( - IS_TYPE_POINTER_ONLY(a) && - IS_TYPE_POINTER_ONLY(b) && - TPTR_QUAL(a) == TPTR_QUAL(b) && - !CParser_IsMoreCVQualified(qualB, qualA) && - IS_TYPE_CLASS(TPTR_TARGET(a)) && - IS_TYPE_CLASS(TPTR_TARGET(b)) - ) - { - tclassA = TYPE_CLASS(TPTR_TARGET(a)); - tclassB = TYPE_CLASS(TPTR_TARGET(b)); - if (tclassA == tclassB || CClass_IsBaseClass(tclassB, tclassA, NULL, errorflag, errorflag)) { - if (!CClass_IsZeroOffsetClass(tclassB, tclassA)) - return 2; - else - return 1; - } - } - - return 0; -} - -UInt8 CClass_GetOverrideKind(TypeFunc *a, TypeFunc *b, Boolean errorflag) { - if (!a->args || !b->args) - return 0; - - if ( - (a->flags & FUNC_CALL_CONV_MASK) != (b->flags & FUNC_CALL_CONV_MASK) || - !is_arglistsame(a->args->next, b->args->next) || - a->args->qual != b->args->qual - ) - return 0; - - if (!is_typesame(a->functype, b->functype)) { - switch (CClass_IsCovariantResult(a->functype, a->qual, b->functype, b->qual, errorflag)) { - case 0: - if (errorflag) - CError_Error(CErrorStr227); - return 0; - case 1: - return 1; - case 2: - return 2; - default: - CError_FATAL(225); - } - } - - return 1; -} - -Boolean CClass_IsEmpty(TypeClass *tclass) { - ClassList *base; - - if (tclass->ivars) - return 0; - - for (base = tclass->bases; base; base = base->next) { - if (!CClass_IsEmpty(base->base)) - return 0; - } - - return 1; -} - -Boolean CClass_IsNonStaticMemberFunc(TypeFunc *tfunc) { - return IS_TYPEFUNC_NONSTATIC_METHOD(tfunc) || (tfunc->flags & FUNC_FLAGS_80); -} - -Object *CClass_DefaultConstructor(TypeClass *tclass) { - NameSpaceObjectList *nsol; - Object *object; - - for (nsol = CScope_FindName(tclass->nspace, constructor_name_node); nsol; nsol = nsol->next) { - object = OBJECT(nsol->object); - if (object->otype == OT_OBJECT && IS_TYPE_FUNC(object->type)) { - if ((tclass->flags & CLASS_HAS_VBASES) && !tclass->sominfo) { - if (TYPE_FUNC(object->type)->args->next && !TYPE_FUNC(object->type)->args->next->next) - return object; - } else { - if (!TYPE_FUNC(object->type)->args->next) - return object; - } - } - } - - return NULL; -} - -Object *CClass_DummyDefaultConstructor(TypeClass *tclass) { - Object *ctor; - FuncArg *args; - NameSpaceObjectList *nsol; - HashNameNode *name; - TypeMemberFunc *tmethod; - Object *object; - ObjectList list; - - ctor = NULL; - - for (nsol = CScope_FindName(tclass->nspace, constructor_name_node); nsol; nsol = nsol->next) { - object = OBJECT(nsol->object); - if (object->otype == OT_OBJECT && IS_TYPE_FUNC(object->type)) { - CError_ASSERT(305, args = TYPE_FUNC(object->type)->args); - args = args->next; - if ((tclass->flags & CLASS_HAS_VBASES) && !tclass->sominfo) { - CError_ASSERT(309, args); - args = args->next; - } - CError_ASSERT(312, args); - - if (args->dexpr) { - if (ctor) { - list.next = NULL; - list.object = object; - CError_OverloadedFunctionError(ctor, &list); - break; - } - ctor = object; - } - } - } - - if (!ctor) { - CError_Error(CErrorStr203); - return NULL; - } - - name = GetHashNameNodeExport("__defctor"); - if ((nsol = CScope_FindName(tclass->nspace, name))) { - CError_ASSERT(339, nsol->object->otype == OT_OBJECT && IS_TYPE_FUNC(OBJECT(nsol->object)->type)); - return OBJECT(nsol->object); - } - - tmethod = galloc(sizeof(TypeMemberFunc)); - memclrw(tmethod, sizeof(TypeMemberFunc)); - - tmethod->type = TYPEFUNC; - tmethod->functype = TYPE(&void_ptr); - tmethod->flags = FUNC_METHOD; - tmethod->theclass = tclass; - CDecl_SetFuncFlags(TYPE_FUNC(tmethod), 0); - - if ((tclass->flags & CLASS_HAS_VBASES) && !tclass->sominfo) - CDecl_AddArgument(TYPE_FUNC(tmethod), TYPE(&stsignedshort)); - - CDecl_AddThisPointerArgument(TYPE_FUNC(tmethod), tclass); - - object = CParser_NewCompilerDefFunctionObject(); - object->type = TYPE(tmethod); - object->qual = Q_INLINE | Q_MANGLE_NAME; - object->nspace = tclass->nspace; - object->name = name; - - CScope_AddObject(tclass->nspace, name, OBJ_BASE(object)); - CParser_RegisterDummyCtorFunction(object, ctor); - return object; -} - -ENode *CClass_DefaultConstructorCall(TypeClass *tclass, TypeClass *b, ENode *objexpr, SInt32 varg, Boolean flag1, Boolean flag2, Boolean *errorflag) { - NameSpaceObjectList *nsol; - Object *ctor; - Object *object; - FuncArg *args; - ENodeList *argexprs; - ENode *expr; - BClassList *path; - BClassList list1; - ObjectList objlist; - BClassList list2; - short founddepth; - Boolean isambigbase; - - *errorflag = 0; - - if (!(nsol = CScope_FindName(tclass->nspace, constructor_name_node))) - return NULL; - - ctor = NULL; - do { - object = OBJECT(nsol->object); - if (object->otype == OT_OBJECT && IS_TYPE_FUNC(object->type)) { - CError_ASSERT(397, args = TYPE_FUNC(object->type)->args); - - args = args->next; - - if ((tclass->flags & CLASS_HAS_VBASES) && !tclass->sominfo) { - CError_ASSERT(401, args); - args = args->next; - } - - if (!args || args->dexpr) { - if (ctor) { - objlist.next = NULL; - objlist.object = object; - CError_OverloadedFunctionError(ctor, &objlist); - break; - } - ctor = object; - } - } - } while ((nsol = nsol->next)); - - if (!ctor) { - *errorflag = 1; - return NULL; - } - - if (flag1) { - if (b) { - if (flag2) { - if ((path = CClass_GetBasePath(b, tclass, &founddepth, &isambigbase))) - list1 = *path; - else - goto skipCheck; - } else { - list1.next = &list2; - list1.type = TYPE(b); - list2.next = NULL; - list2.type = TYPE(tclass); - } - } else { - list1.next = NULL; - list1.type = TYPE(tclass); - } - CClass_CheckPathAccess(&list1, ctor, ctor->access); - } - -skipCheck: - if ((tclass->flags & CLASS_HAS_VBASES) && !tclass->sominfo) { - argexprs = lalloc(sizeof(ENodeList)); - argexprs->next = NULL; - argexprs->node = intconstnode(TYPE(&stsignedshort), varg); - } else { - argexprs = NULL; - } - - CError_ASSERT(471, IS_TYPE_POINTER_ONLY(objexpr->rtype)); - - objexpr = makemonadicnode(objexpr, EINDIRECT); - objexpr->rtype = TYPE(tclass); - - list1.next = NULL; - list1.type = TYPE(tclass); - - expr = CExpr_GenericFuncCall( - &list1, - objexpr, - 0, - ctor, - NULL, - NULL, - argexprs, - 0, - 0, - 0 - ); - - if (ENODE_IS2(expr, EFUNCCALL, EFUNCCALLP)) - expr->rtype = CDecl_NewPointerType(TYPE(tclass)); - - return expr; -} - -Object *CClass_AssignmentOperator(TypeClass *tclass) { - NameSpaceObjectList *nsol; - Object *object; - - for (nsol = CScope_FindName(tclass->nspace, asop_name_node); nsol; nsol = nsol->next) { - object = OBJECT(nsol->object); - if ( - object->otype == OT_OBJECT && - IS_TYPE_FUNC(object->type) && - TYPE_FUNC(object->type)->args && - TYPE_FUNC(object->type)->args->next && - !TYPE_FUNC(object->type)->args->next->next - ) - { - if ( - IS_TYPE_CLASS(TYPE_FUNC(object->type)->args->next->type) && - TYPE_CLASS(TYPE_FUNC(object->type)->args->next->type) == tclass - ) - return object; - - if ( - IS_TYPE_REFERENCE(TYPE_FUNC(object->type)->args->next->type) && - TPTR_TARGET(TYPE_FUNC(object->type)->args->next->type) == TYPE(tclass) - ) - return object; - } - } - - return NULL; -} - -Object *CClass_CopyConstructor(TypeClass *tclass) { - NameSpaceObjectList *nsol; - Object *object; - FuncArg *args; - - if (tclass->sominfo) - return NULL; - - for (nsol = CScope_FindName(tclass->nspace, constructor_name_node); nsol; nsol = nsol->next) { - object = OBJECT(nsol->object); - if (object->otype == OT_OBJECT && IS_TYPE_FUNC(object->type)) { - CError_ASSERT(532, args = TYPE_FUNC(object->type)->args); - - args = args->next; - - if (tclass->flags & CLASS_HAS_VBASES) { - CError_ASSERT(536, args); - args = args->next; - } - - if ( - args && - args != &elipsis && - (!args->next || args->next->dexpr) && - IS_TYPE_REFERENCE(args->type) && - TPTR_TARGET(args->type) == TYPE(tclass) - ) - return object; - } - } - - return NULL; -} - -NameSpaceObjectList *CClass_MemberObject(TypeClass *tclass, HashNameNode *name) { - NameSpaceObjectList *nsol; - - if ((nsol = CScope_FindName(tclass->nspace, name)) && nsol->object->otype == OT_OBJECT) - return nsol; - - return NULL; -} - -NameSpaceObjectList *CClass_Constructor(TypeClass *tclass) { - NameSpaceObjectList *nsol; - - if ( - (nsol = CScope_FindName(tclass->nspace, constructor_name_node)) && - nsol->object->otype == OT_OBJECT && - IS_TYPE_FUNC(OBJECT(nsol->object)->type) - ) - return nsol; - - return NULL; -} - -Object *CClass_Destructor(TypeClass *tclass) { - NameSpaceObjectList *nsol; - - for (nsol = CScope_FindName(tclass->nspace, destructor_name_node); nsol; nsol = nsol->next) { - if ( - nsol->object->otype == OT_OBJECT && - IS_TYPE_FUNC(OBJECT(nsol->object)->type) - ) - return OBJECT(nsol->object); - } - - return NULL; -} - -Boolean CClass_IsConstructor(Object *obj) { - return obj && IS_TYPE_FUNC(obj->type) && (TYPE_FUNC(obj->type)->flags & FUNC_IS_CTOR); -} - -Boolean CClass_IsDestructor(Object *obj) { - return obj && IS_TYPE_FUNC(obj->type) && (TYPE_FUNC(obj->type)->flags & FUNC_IS_DTOR); -} - -Boolean CClass_IsPODClass(TypeClass *tclass) { - NameSpaceObjectList *nsol; - Object *object; - ObjMemberVar *ivar; - Type *type; - - if (tclass->vtable || tclass->bases || CClass_Destructor(tclass)) - return 0; - - for (nsol = CClass_Constructor(tclass); nsol; nsol = nsol->next) { - if ( - nsol->object->otype == OT_OBJECT && - IS_TYPE_FUNC(OBJECT(nsol->object)->type) && - !(TYPE_FUNC(OBJECT(nsol->object)->type)->flags & FUNC_AUTO_GENERATED) - ) - return 0; - } - - object = CClass_AssignmentOperator(tclass); - if (object && !(TYPE_FUNC(object->type)->flags & FUNC_AUTO_GENERATED)) - return 0; - - for (ivar = tclass->ivars; ivar; ivar = ivar->next) { - if (ivar->access != ACCESSPUBLIC) - return 0; - - type = ivar->type; - while (IS_TYPE_ARRAY(type)) - type = TPTR_TARGET(type); - - switch (type->type) { - case TYPECLASS: - if (!CClass_IsPODClass(TYPE_CLASS(type))) - return 0; - break; - case TYPEMEMBERPOINTER: - return 0; - case TYPEPOINTER: - if (TPTR_QUAL(type) & Q_REFERENCE) - return 0; - break; - } - } - - return 1; -} - -Boolean CClass_IsTrivialCopyClass(TypeClass *tclass) { - Object *object; - ClassList *base; - ObjMemberVar *ivar; - Type *type; - - if (tclass->vtable || tclass->vbases || CClass_Destructor(tclass)) - return 0; - - object = CClass_CopyConstructor(tclass); - if (object && IS_TYPE_FUNC(object->type) && !(TYPE_FUNC(object->type)->flags & FUNC_AUTO_GENERATED)) - return 0; - - for (base = tclass->bases; base; base = base->next) { - if (!CClass_IsTrivialCopyClass(base->base)) - return 0; - } - - for (ivar = tclass->ivars; ivar; ivar = ivar->next) { - type = ivar->type; - while (IS_TYPE_ARRAY(type)) - type = TPTR_TARGET(type); - - if (IS_TYPE_CLASS(type) && !CClass_IsTrivialCopyClass(TYPE_CLASS(type))) - return 0; - } - - return 1; -} - -Boolean CClass_IsTrivialCopyAssignClass(TypeClass *tclass) { - Object *object; - ObjMemberVar *ivar; - Type *type; - - if (tclass->vtable || tclass->bases || CClass_Destructor(tclass)) - return 0; - - object = CClass_AssignmentOperator(tclass); - if (object && !(TYPE_FUNC(object->type)->flags & FUNC_AUTO_GENERATED)) - return 0; - - for (ivar = tclass->ivars; ivar; ivar = ivar->next) { - type = ivar->type; - while (IS_TYPE_ARRAY(type)) - type = TPTR_TARGET(type); - - if (IS_TYPE_REFERENCE(type)) - return 0; - if (CParser_IsConst(type, ivar->qual)) - return 0; - if (IS_TYPE_CLASS(type) && !CClass_IsTrivialCopyAssignClass(TYPE_CLASS(type))) - return 0; - } - - return 1; -} - -Boolean CClass_ReferenceArgument(TypeClass *tclass) { - if ((tclass->flags & (CLASS_COMPLETED | CLASS_IS_TEMPL_INST)) == CLASS_IS_TEMPL_INST) - CDecl_CompleteType(TYPE(tclass)); - - if (copts.simple_class_byval) - return !CClass_IsTrivialCopyClass(tclass); - - return CClass_Destructor(tclass) || CClass_CopyConstructor(tclass); -} - -BClassList *CClass_GetPathCopy(BClassList *path, Boolean is_global) { - BClassList *last; - BClassList *copy; - - if (!path) - return NULL; - - copy = last = is_global ? galloc(sizeof(BClassList)) : lalloc(sizeof(BClassList)); - last->next = path->next; - last->type = path->type; - - while ((path = path->next)) { - last->next = is_global ? galloc(sizeof(BClassList)) : lalloc(sizeof(BClassList)); - last = last->next; - last->next = path->next; - last->type = path->type; - } - - return copy; -} - -BClassList *CClass_AppendPath(BClassList *dest, BClassList *src) { - BClassList *last; - - if (!(last = dest)) - return src; - - while (last->next) - last = last->next; - - while (src && src->type == last->type) - src = src->next; - - last->next = src; - return dest; -} - -static AccessType CClass_GetPathAccess(BClassList *path) { - AccessType result; - ClassList *base; - TypeClass *tclass; - - CError_ASSERT(930, path); - - result = ACCESSPUBLIC; - - while (1) { - tclass = TYPE_CLASS(path->type); - if (!(path = path->next)) - break; - - for (base = tclass->bases; base; base = base->next) { - if (base->base == TYPE_CLASS(path->type)) - break; - } - - CError_ASSERT(939, base); - - switch (base->access) { - case ACCESSPUBLIC: - break; - case ACCESSPROTECTED: - if (result == ACCESSPUBLIC) - result = ACCESSPROTECTED; - break; - case ACCESSPRIVATE: - if (result == ACCESSPUBLIC || result == ACCESSPROTECTED) - result = ACCESSPRIVATE; - else - return ACCESSNONE; - break; - case ACCESSNONE: - return ACCESSNONE; - default: - CError_FATAL(960); - } - } - - return result; -} - -Boolean CClass_IsMoreAccessiblePath(BClassList *path1, BClassList *path2) { - switch (CClass_GetPathAccess(path2)) { - case ACCESSPUBLIC: - return 0; - case ACCESSNONE: - return 1; - default: - CError_FATAL(978); - case ACCESSPROTECTED: - switch (CClass_GetPathAccess(path1)) { - case ACCESSPUBLIC: - return 1; - case ACCESSPRIVATE: - case ACCESSPROTECTED: - case ACCESSNONE: - return 0; - default: - CError_FATAL(987); - } - case ACCESSPRIVATE: - switch (CClass_GetPathAccess(path1)) { - case ACCESSPUBLIC: - case ACCESSPROTECTED: - return 1; - case ACCESSPRIVATE: - case ACCESSNONE: - return 0; - default: - CError_FATAL(997); - } - } - - return 0; -} - -static BClassList *CClass_GetBasePathRec(TypeClass *a, TypeClass *b, SInt32 offset, short depth) { - ClassList *base; - BClassList *checkpath; - BClassList *bestpath; - BClassList *newpath; - SInt32 newOffset; - - for (base = a->bases, bestpath = NULL; base; base = base->next) { - if (base->is_virtual) - newOffset = CClass_VirtualBaseOffset(cclass_isbase_mostderived, base->base); - else - newOffset = offset + base->offset; - - if (base->base == b) { - if (cclass_founddepth && newOffset != cclass_isbase_foundoffset) { - cclass_isambigbase = 1; - return NULL; - } - - cclass_isbase_foundoffset = newOffset; - cclass_founddepth = depth; - - bestpath = lalloc(sizeof(BClassList)); - bestpath->next = NULL; - bestpath->type = TYPE(b); - } else if ((checkpath = CClass_GetBasePathRec(base->base, b, newOffset, depth + 1))) { - newpath = lalloc(sizeof(BClassList)); - newpath->next = checkpath; - newpath->type = TYPE(base->base); - if (!bestpath || CClass_IsMoreAccessiblePath(newpath, bestpath)) - bestpath = newpath; - } - } - - return bestpath; -} - -BClassList *CClass_GetBasePath(TypeClass *a, TypeClass *b, short *founddepth, Boolean *isambigbase) { - BClassList *path; - BClassList *result; - - if ((a->flags & (CLASS_COMPLETED | CLASS_IS_TEMPL_INST)) == CLASS_IS_TEMPL_INST) - CDecl_CompleteType(TYPE(a)); - if ((b->flags & (CLASS_COMPLETED | CLASS_IS_TEMPL_INST)) == CLASS_IS_TEMPL_INST) - CDecl_CompleteType(TYPE(b)); - - cclass_founddepth = 0; - cclass_isbase_mostderived = a; - cclass_isbase_foundoffset = -1; - cclass_isambigbase = 0; - - if ((path = CClass_GetBasePathRec(a, b, 0, 1))) { - *founddepth = cclass_founddepth; - *isambigbase = cclass_isambigbase; - - result = lalloc(sizeof(BClassList)); - result->next = path; - result->type = TYPE(a); - return result; - } else { - *isambigbase = 0; - return NULL; - } -} - -Boolean CClass_IsBaseClass(TypeClass *a, TypeClass *b, short *founddepth, Boolean pathcheckflag, Boolean ambigerrorflag) { - BClassList *path; - short depth; - Boolean isambigbase; - - if ((path = CClass_GetBasePath(a, b, &depth, &isambigbase))) { - if (isambigbase && ambigerrorflag) - CError_Error(CErrorStr188); - - if (pathcheckflag) - CClass_CheckPathAccess(path, NULL, ACCESSPUBLIC); - - if (founddepth) - *founddepth = depth; - - return 1; - } - - return 0; -} - -TypeClass *CClass_GetQualifiedClass(void) { - DeclInfo di; - - memclrw(&di, sizeof(di)); - CParser_GetDeclSpecs(&di, 0); - - if (IS_TYPE_CLASS(di.thetype)) - return TYPE_CLASS(di.thetype); - - return NULL; -} - -ENode *CClass_AccessPathCast(BClassList *path, ENode *expr, Boolean reverse) { - ClassList *base; - SInt32 offset; - - while (path && path->next) { - base = TYPE_CLASS(path->type)->bases; - while (1) { - if (base->base == TYPE_CLASS(path->next->type)) - break; - CError_ASSERT(1157, base = base->next); - } - - if (base->is_virtual) { - if (reverse) { - CError_Error(CErrorStr164); - break; - } - - if (!base->base->sominfo) { - offset = base->offset; - if (offset && !canadd(expr, offset)) { - expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), offset), EADD); - optimizecomm(expr); - } - - expr->rtype = CDecl_NewPointerType(CDecl_NewPointerType(TYPE(base->base))); - expr = makemonadicnode(expr, EINDIRECT); - expr->rtype = expr->data.monadic->rtype; - } - } else { - offset = base->offset; - if (offset) { - if (reverse) - offset = -offset; - if (!canadd(expr, offset)) { - expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), offset), EADD); - optimizecomm(expr); - } - } - } - - path = path->next; - } - - return expr; -} - -ENode *CClass_ClassPointerCast(ENode *expr, TypeClass *a, TypeClass *b, Boolean typconflag, Boolean ambigerrorflag, Boolean pathcheckflag) { - BClassList *path; - Boolean reverse; - short depth; - Boolean isambigbase; - - reverse = 0; - - if (a != b) { - if (!(path = CClass_GetBasePath(a, b, &depth, &isambigbase))) { - CError_ASSERT(1216, typconflag); - if ((path = CClass_GetBasePath(b, a, &depth, &isambigbase))) { - reverse = 1; - goto doCast; - } - } else { - doCast: - if (isambigbase && ambigerrorflag) - CError_Error(CErrorStr188); - if (pathcheckflag) - CClass_CheckPathAccess(path, NULL, ACCESSPUBLIC); - if (!(a->flags & CLASS_SINGLE_OBJECT) && !b->sominfo) - expr = CClass_AccessPathCast(path, expr, reverse); - } - } - - if (typconflag && ENODE_IS(expr, EINDIRECT) && IS_TYPE_POINTER_ONLY(expr->rtype)) - expr = makemonadicnode(expr, ETYPCON); - - return expr; -} - -ENode *CClass_DirectBasePointerCast(ENode *expr, TypeClass *a, TypeClass *b) { - ClassList *base; - VClassList *vbase; - BClassList *path; - BClassList list1; - BClassList list2; - short depth; - Boolean isambigbase; - - for (base = a->bases; base; base = base->next) { - if (base->base == b) { - list1.next = &list2; - list1.type = TYPE(a); - list2.next = NULL; - list2.type = TYPE(b); - return CClass_AccessPathCast(&list1, expr, 0); - } - } - - for (vbase = a->vbases; vbase; vbase = vbase->next) { - if (vbase->base == b) { - CError_ASSERT(1273, path = CClass_GetBasePath(a, b, &depth, &isambigbase)); - return CClass_AccessPathCast(path, expr, 0); - } - } - - CError_FATAL(1277); - return expr; -} - -SInt32 CClass_GetPathOffset(BClassList *path) { - SInt32 offset; - ClassList *base; - - offset = 0; - - while (path->next) { - if (path->type != path->next->type) { - for (base = TYPE_CLASS(path->type)->bases; base; base = base->next) { - if (base->base == TYPE_CLASS(path->next->type)) - break; - } - - if (!base) { - CError_Error(CErrorStr221); - return offset; - } - } - - if (base->is_virtual) - return -1; - offset += base->offset; - - path = path->next; - } - - return offset; -} - -Boolean CClass_ClassDominates(TypeClass *tclass, TypeClass *baseclass) { - ClassList *base; - - for (base = tclass->bases; base; base = base->next) { - if (base->base == baseclass || CClass_ClassDominates(base->base, baseclass)) - return 1; - } - - return 0; -} - -SInt32 CClass_VirtualBaseOffset(TypeClass *tclass, TypeClass *baseclass) { - VClassList *vbase; - - for (vbase = tclass->vbases; vbase; vbase = vbase->next) { - if (vbase->base == baseclass) - return vbase->offset; - } - - CError_FATAL(1342); - return 0; -} - -SInt32 CClass_VirtualBaseVTableOffset(TypeClass *tclass, TypeClass *baseclass) { - VClassList *vbase; - - for (vbase = tclass->vbases; vbase; vbase = vbase->next) { - if (vbase->base == baseclass) - return vbase->voffset; - } - - CError_FATAL(1359); - return 0; -} - -SInt32 CClass_GetMemberOffset(TypeClass *tclass, HashNameNode *name, ObjMemberVar **resultIvar) { - ObjMemberVar *ivar; - ClassList *base; - SInt32 offset; - SInt32 tmp; - Boolean foundflag; - - for (ivar = tclass->ivars; ivar; ivar = ivar->next) { - if (ivar->name == name) { - if (resultIvar) - *resultIvar = ivar; - return ivar->offset; - } - } - - for (base = tclass->bases, foundflag = 0; base; base = base->next) { - switch ((tmp = CClass_GetMemberOffset(base->base, name, resultIvar))) { - case -3: - case -2: - return tmp; - case -1: - break; - default: - if (base->is_virtual) - return -3; - if (foundflag) - return -2; - foundflag = 1; - offset = base->offset + tmp; - } - } - - return foundflag ? offset : -1; -} - -Boolean CClass_OverridesBaseMember(TypeClass *tclass, HashNameNode *name, Object *obj) { - NameSpaceObjectList *nsol; - ClassList *base; - Boolean result; - - result = 0; - for (base = tclass->bases; base; base = base->next) { - if (base->base->vtable) { - for (nsol = CScope_FindName(base->base->nspace, name); nsol; nsol = nsol->next) { - if ( - nsol->object->otype == OT_OBJECT && - OBJECT(nsol->object)->datatype == DVFUNC && - CClass_GetOverrideKind(TYPE_FUNC(OBJECT(nsol->object)->type), TYPE_FUNC(obj->type), 1) - ) - result = 1; - } - - if (CClass_OverridesBaseMember(base->base, name, obj)) - result = 1; - } - } - - return result; -} - -static OVClass *CClass_FindOVClass(OVClass *ovclass, TypeClass *tclass, SInt32 offset) { - OVClassBase *ovbase; - - if (ovclass->tclass == tclass && ovclass->offset == offset) - return ovclass; - - for (ovbase = ovclass->bases; ovbase; ovbase = ovbase->next) { - if ((ovclass = CClass_FindOVClass(ovbase->ovclass, tclass, offset))) - return ovclass; - } - - return NULL; -} - -static OVClass *CClass_BuildOVClassTree(OVClass *root, TypeClass *tclass, SInt32 offset, SInt32 voffset) { - ClassList *base; - Object *object; - OVClass *tree; - OVFunc *ovfunc; - OVClassBase *ovbase; - SInt32 vboffset; - SInt32 vbvoffset; - CScopeObjectIterator iter; - - tree = lalloc(sizeof(OVClass)); - memclrw(tree, sizeof(OVClass)); - - tree->tclass = tclass; - tree->offset = offset; - tree->voffset = voffset; - if (!root) - root = tree; - - CScope_InitObjectIterator(&iter, tclass->nspace); - while (1) { - if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) - break; - - if (object->datatype == DVFUNC) { - ovfunc = lalloc(sizeof(OVFunc)); - memclrw(ovfunc, sizeof(OVFunc)); - - ovfunc->next = tree->vfuncs; - ovfunc->obj = object; - tree->vfuncs = ovfunc; - } - } - - for (base = tclass->bases; base; base = base->next) { - if (base->base->vtable || base->base->sominfo) { - ovbase = lalloc(sizeof(OVClassBase)); - memclrw(ovbase, sizeof(OVClassBase)); - - if (base->is_virtual) { - vboffset = CClass_VirtualBaseOffset(main_class, base->base); - if (!(ovbase->ovclass = CClass_FindOVClass(root, base->base, vboffset))) { - vbvoffset = CClass_VirtualBaseVTableOffset(main_class, base->base); - ovbase->ovclass = CClass_BuildOVClassTree(root, base->base, vboffset, vbvoffset); - } - ovbase->is_virtual = 1; - } else { - ovbase->ovclass = CClass_BuildOVClassTree( - root, - base->base, - offset + base->offset, - voffset + base->voffset); - ovbase->is_virtual = 0; - } - - ovbase->next = tree->bases; - tree->bases = ovbase; - } - } - - return tree; -} - -static Boolean CClass_IsBaseOf(OVClass *a, OVClass *b) { - OVClassBase *ovbase; - - for (ovbase = b->bases; ovbase; ovbase = ovbase->next) { - if ( - (ovbase->ovclass->tclass == a->tclass && ovbase->ovclass->offset == a->offset) || - CClass_IsBaseOf(a, ovbase->ovclass) - ) - { - if (!cclass_ovbase && ovbase->is_virtual) - cclass_ovbase = ovbase->ovclass; - return 1; - } - } - - return 0; -} - -static void CClass_FindOVFunc(OVClass *a, OVClass *b, OVFunc *func) { - OVFunc *scan; - OVClassBase *ovbase; - UInt8 overrideKind; - - if (CClass_IsBaseOf(b, a)) { - for (scan = a->vfuncs; scan; scan = scan->next) { - if ( - (func->obj->name == scan->obj->name) && - (overrideKind = CClass_GetOverrideKind(TYPE_FUNC(func->obj->type), TYPE_FUNC(scan->obj->type), 0)) - ) - { - if (func->ovc8) { - if (func->ovc8->tclass == a->tclass || CClass_ClassDominates(func->ovc8->tclass, a->tclass)) - return; - if (!CClass_ClassDominates(a->tclass, func->ovc8->tclass)) { - func->ovf10 = scan; - return; - } - } - - if (a == cclass_root) { - TYPE_FUNC(scan->obj->type)->flags |= FUNC_FLAGS_20; - if (overrideKind == 2) - TYPE_FUNC(scan->obj->type)->flags |= FUNC_FLAGS_400000; - } - - func->ovc8 = a; - func->ovfC = scan; - func->ovf10 = NULL; - return; - } - } - - for (ovbase = a->bases; ovbase; ovbase = ovbase->next) - CClass_FindOVFunc(ovbase->ovclass, b, func); - } -} - -static TypeList *CClass_GetCoVariantClassList(TypeList *list, TypeClass *tclass, Object *func, Boolean flag) { - Object *object; - TypeList *scan; - Type *type; - ClassList *base; - CScopeObjectIterator iter; - - if (!flag) { - CScope_InitObjectIterator(&iter, tclass->nspace); - while (1) { - if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) - break; - - if ( - object->name == func->name && - object->datatype == DVFUNC && - CClass_GetOverrideKind(TYPE_FUNC(object->type), TYPE_FUNC(func->type), 0) == 2 - ) - { - CError_ASSERT(1686, - IS_TYPE_POINTER_ONLY(TYPE_FUNC(object->type)->functype) && - IS_TYPE_CLASS(TPTR_TARGET(TYPE_FUNC(object->type)->functype))); - - type = TPTR_TARGET(TYPE_FUNC(object->type)->functype); - for (scan = list; scan; scan = scan->next) { - if (scan->type == type) - break; - } - - if (!scan) { - scan = lalloc(sizeof(TypeList)); - scan->type = type; - scan->next = list; - list = scan; - } - } - } - } - - for (base = tclass->bases; base; base = base->next) { - if (base->base->vtable) - list = CClass_GetCoVariantClassList(list, base->base, func, 0); - } - - return list; -} - -static TypeMemberFunc *CClass_GetCovariantType(TypeMemberFunc *tmethod, Type *type) { - TypePointer *tptr; - TypeMemberFunc *result; - - CError_ASSERT(1724, - IS_TYPE_METHOD(tmethod) && - IS_TYPE_POINTER_ONLY(tmethod->functype)); - - tptr = galloc(sizeof(TypePointer)); - *tptr = *TYPE_POINTER(tmethod->functype); - tptr->target = type; - - result = galloc(sizeof(TypeMemberFunc)); - *result = *tmethod; - result->flags &= ~(FUNC_FLAGS_20 | FUNC_FLAGS_400000); - result->functype = TYPE(tptr); - return result; -} - -static Object *CClass_FindCovariantFunction(Object *func, Type *type) { - NameSpaceObjectList *nsol; - - nsol = CScope_FindName( - TYPE_METHOD(func->type)->theclass->nspace, - CMangler_GetCovariantFunctionName(func, TYPE_CLASS(type))); - - CError_ASSERT(1754, nsol && !nsol->next && nsol->object->otype == OT_OBJECT); - - return OBJECT(nsol->object); -} - -static ObjectList *CClass_DeclareCovariantFuncs(ObjectList *list, Object *func, TypeClass *tclass) { - Object *newfunc; - HashNameNode *name; - TypeList *types; - ObjectList *newlist; - - for (types = CClass_GetCoVariantClassList(NULL, tclass, func, 1); types; types = types->next) { - name = CMangler_GetCovariantFunctionName(func, TYPE_CLASS(types->type)); - - newfunc = galloc(sizeof(Object)); - memclrw(newfunc, sizeof(Object)); - - newfunc->otype = OT_OBJECT; - newfunc->datatype = DFUNC; - newfunc->section = func->section; - newfunc->nspace = func->nspace; - newfunc->name = name; - newfunc->type = TYPE(CClass_GetCovariantType(TYPE_METHOD(func->type), types->type)); - newfunc->qual = func->qual & ~Q_INLINE; - newfunc->sclass = func->sclass; - newfunc->u.func.linkname = name; - - newlist = lalloc(sizeof(ObjectList)); - newlist->object = newfunc; - newlist->next = list; - list = newlist; - } - - return list; -} - -void CClass_DefineCovariantFuncs(Object *method, CI_FuncData *ifuncdata) { - NameSpace *nspace; - TypeList *types; - Object *covariantFunc; - Statement *stmt; - Type *tptr; - Statement firstStmt; - - for (types = CClass_GetCoVariantClassList(NULL, TYPE_METHOD(method->type)->theclass, method, 1); types; types = types->next) { - covariantFunc = CClass_FindCovariantFunction(method, types->type); - tptr = CDecl_NewPointerType(types->type); - - nspace = CFunc_FuncGenSetup(&firstStmt, covariantFunc); - CInline_UnpackIFunctionData(covariantFunc, ifuncdata, &firstStmt); - - for (stmt = &firstStmt; stmt; stmt = stmt->next) { - if (stmt->type == ST_RETURN && stmt->expr) - stmt->expr = CExpr_AssignmentPromotion(stmt->expr, tptr, ENODE_QUALS(stmt->expr), 0); - } - - CFunc_Gen(&firstStmt, covariantFunc, 0); - cscope_current = nspace->parent; - } -} - -static void CClass_OverrideOVClassTree(OVClass *ovclass) { - OVClassBase *ovbase; - OVFunc *ovfunc; - - if (cclass_root != ovclass) { - for (ovfunc = ovclass->vfuncs; ovfunc; ovfunc = ovfunc->next) - CClass_FindOVFunc(cclass_root, ovclass, ovfunc); - } - - for (ovbase = ovclass->bases; ovbase; ovbase = ovbase->next) - CClass_OverrideOVClassTree(ovbase->ovclass); -} - -static void CClass_AllocVTableRec(OVClass *ovclass) { - OVFunc *ovfunc; - Object *object; - SInt32 offset27; - SInt32 offset26; - SInt32 offset23; - OVClassBase *ovbase; - OLinkList *link; - - if (ovclass->alloced_vtable) - return; - - for (ovfunc = ovclass->vfuncs; ovfunc; ovfunc = ovfunc->next) { - offset27 = ovclass->voffset + TYPE_METHOD(ovfunc->obj->type)->vtbl_index + CABI_GetVTableOffset(ovclass->tclass); - CError_ASSERT(1867, offset27 < vtable_data_size); - - if (!(vtable_object_data[offset27])) { - if (ovfunc->ovfC) { - object = ovfunc->ovfC->obj; - if ( - (TYPE_FUNC(object->type)->flags & FUNC_FLAGS_400000) && - CClass_GetOverrideKind(TYPE_FUNC(ovfunc->obj->type), TYPE_FUNC(object->type), 0) == 2 - ) - { - CError_ASSERT(1887, - IS_TYPE_POINTER_ONLY(TYPE_FUNC(ovfunc->obj->type)->functype) && - IS_TYPE_CLASS(TPTR_TARGET(TYPE_FUNC(ovfunc->obj->type)->functype))); - object = CClass_FindCovariantFunction( - object, - TPTR_TARGET(TYPE_FUNC(ovfunc->obj->type)->functype)); - } - - if ((offset26 = ovfunc->ovc8->offset - ovclass->offset)) { - if (!(TYPE_FUNC(object->type)->flags & FUNC_PURE)) { - cclass_ovbase = NULL; - CError_ASSERT(1899, CClass_IsBaseOf(ovclass, ovfunc->ovc8)); - - if (cclass_ovbase && (main_class->flags & CLASS_FLAGS_8000)) { - offset23 = ovclass->offset - cclass_ovbase->offset; - offset23 = CABI_GetCtorOffsetOffset(cclass_ovbase->tclass, NULL) - offset23; - CError_ASSERT(1906, offset23 > 0); - object = CClass_ThunkObject(object, offset26, 0, offset23); - } else { - object = CClass_ThunkObject(object, offset26, 0, -1); - } - } - } - } else { - object = ovfunc->obj; - } - - if (!(TYPE_FUNC(object->type)->flags & FUNC_PURE)) { - link = lalloc(sizeof(OLinkList)); - link->next = vtable_object_links; - link->obj = object; - link->offset = offset27; - link->somevalue = 0; - vtable_object_links = link; - vtable_object_data[offset27] = 1; - } - } - } - - ovclass->alloced_vtable = 1; - - for (ovbase = ovclass->bases; ovbase; ovbase = ovbase->next) - CClass_AllocVTableRec(ovbase->ovclass); -} - -static Object *CClass_CheckClass(OVClass *ovclass, Boolean errorflag) { - Object *object; - Object *check; - OVFunc *ovfunc; - OVClassBase *ovbase; - - object = NULL; - - for (ovfunc = ovclass->vfuncs; ovfunc; ovfunc = ovfunc->next) { - if (ovfunc->ovf10 && errorflag) - CError_Error(CErrorStr251, main_class, 0, ovfunc->obj, ovfunc->ovfC->obj, ovfunc->ovf10->obj); - - if (!object) { - check = ovfunc->ovfC ? ovfunc->ovfC->obj : ovfunc->obj; - if (TYPE_FUNC(check->type)->flags & FUNC_PURE) - object = check; - } - } - - for (ovbase = ovclass->bases; ovbase; ovbase = ovbase->next) { - if (object) - CClass_CheckClass(ovbase->ovclass, errorflag); - else - object = CClass_CheckClass(ovbase->ovclass, errorflag); - } - - return object; -} - -static void CClass_AllocVTable(TypeClass *tclass) { - OVClass *ovclass; - - main_class = tclass; - ovclass = CClass_BuildOVClassTree(NULL, tclass, 0, 0); - cclass_root = ovclass; - CClass_OverrideOVClassTree(ovclass); - CClass_CheckClass(ovclass, 1); - CClass_AllocVTableRec(ovclass); -} - -static Object *CClass_CheckVirtuals(TypeClass *tclass) { - OVClass *ovclass; - - main_class = tclass; - ovclass = CClass_BuildOVClassTree(NULL, tclass, 0, 0); - cclass_root = ovclass; - CClass_OverrideOVClassTree(ovclass); - return CClass_CheckClass(ovclass, 0); -} - -static void CClass_CheckVirtualBaseOverrides(OVClass *a, OVClass *b, Boolean flag) { - VClassList *vbase; - OVFunc *ovfunc; - OVClassBase *ovbase; - - if (flag) { - for (ovfunc = b->vfuncs; ovfunc; ovfunc = ovfunc->next) { - if (ovfunc->ovfC) { - cclass_ovbase = NULL; - CError_ASSERT(2040, CClass_IsBaseOf(b, ovfunc->ovc8)); - - if (cclass_ovbase) { - for (vbase = a->tclass->vbases; vbase; vbase = vbase->next) { - if (vbase->base == cclass_ovbase->tclass) - break; - } - - CError_ASSERT(2047, vbase); - vbase->has_override = 1; - } - } - } - } - - for (ovbase = b->bases; ovbase; ovbase = ovbase->next) { - CClass_CheckVirtualBaseOverrides(a, ovbase->ovclass, flag || ovbase->is_virtual); - } -} - -static void CClass_CheckHideVirtual(OVClass *a, OVClass *b) { - OVClassBase *ovbase; - OVFunc *ovfunc; - Object *foundObject; - Boolean isAlias; - Object *object; - CScopeObjectIterator iter; - - if (a != b) { - for (ovfunc = b->vfuncs; ovfunc; ovfunc = ovfunc->next) { - if (ovfunc->ovc8 != a) { - foundObject = NULL; - isAlias = 0; - CScope_InitObjectIterator(&iter, a->tclass->nspace); - - while (1) { - if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) - break; - - if (object->name == ovfunc->obj->name && IS_TYPE_FUNC(object->type)) { - if (object->datatype != DALIAS) { - if (!(TYPE_FUNC(object->type)->flags & FUNC_FLAGS_20)) - foundObject = object; - } else { - if (object->u.alias.object == ovfunc->obj) { - // don't show a warning if this is just an alias to the base function - isAlias = 1; - break; - } - } - } - } - - if (foundObject && !isAlias) - CError_Warning(CErrorStr225, foundObject, ovfunc->obj); - } - } - } - - for (ovbase = b->bases; ovbase; ovbase = ovbase->next) - CClass_CheckHideVirtual(a, ovbase->ovclass); -} - -void CClass_CheckOverrides(TypeClass *tclass) { - OVClass *tree; - Object *object; - ObjectList *objlist; - ClassList *base; - VClassList *vbase; - int i; - CScopeObjectIterator iter; - - i = 0; - for (base = tclass->bases; base; base = base->next) { - base->offset = i; - base->voffset = i; - i++; - } - for (vbase = tclass->vbases; vbase; vbase = vbase->next) { - vbase->offset = i; - vbase->voffset = i; - i++; - } - - main_class = tclass; - tree = CClass_BuildOVClassTree(NULL, tclass, 0, 0); - cclass_root = tree; - - CClass_OverrideOVClassTree(tree); - if (CClass_CheckClass(tree, 0)) - tclass->flags |= CLASS_ABSTRACT; - - if (copts.warn_hidevirtual) - CClass_CheckHideVirtual(tree, tree); - - if (tclass->flags & CLASS_FLAGS_8000) - CClass_CheckVirtualBaseOverrides(tree, tree, 0); - - objlist = NULL; - CScope_InitObjectIterator(&iter, tclass->nspace); - while (1) { - if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) - break; - - if (object->datatype == DVFUNC) { - CError_ASSERT(2175, IS_TYPE_FUNC(object->type)); - if (TYPE_FUNC(object->type)->flags & FUNC_FLAGS_400000) - objlist = CClass_DeclareCovariantFuncs(objlist, object, tclass); - } - } - - while (objlist) { - CScope_AddObject(tclass->nspace, objlist->object->name, OBJ_BASE(objlist->object)); - objlist = objlist->next; - } - - for (base = tclass->bases; base; base = base->next) { - base->offset = 0; - base->voffset = 0; - } - for (vbase = tclass->vbases; vbase; vbase = vbase->next) { - vbase->offset = 0; - vbase->voffset = 0; - } -} - -static void CClass_FindDominator(TypeClass *tclass1, SInt32 offset1, Object *object1, TypeClass *tclass2, SInt32 offset2, TypeClass *tclass3) { - Object *object; - ClassList *base; - CScopeObjectIterator iter; - - CScope_InitObjectIterator(&iter, tclass1->nspace); - while (1) { - if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) - break; - - if ( - object->name == cclass_dominator_vobject->name && - object->datatype == DVFUNC && - CClass_GetOverrideKind(TYPE_FUNC(cclass_dominator_vobject->type), TYPE_FUNC(object->type), 0) - ) - { - if (object == cclass_dominator_vobject && offset1 == cclass_dominator_voffset) { - if (object1) { - if (cclass_dominator_oobject && cclass_dominator_ooffset != offset2) { - if (CClass_ClassDominates(cclass_dominator_oclass, tclass2)) - return; - if (!CClass_ClassDominates(tclass2, cclass_dominator_oclass)) { - cclass_dominator_eobject = object1; - cclass_vbase = tclass3; - return; - } - } - - cclass_dominator_oobject = object1; - cclass_dominator_ooffset = offset2; - cclass_dominator_oclass = tclass2; - cclass_dominator_eobject = NULL; - cclass_vbase = tclass3; - } - return; - } else { - if (!object1) { - object1 = object; - tclass2 = tclass1; - offset2 = offset1; - } - break; - } - } - } - - for (base = tclass1->bases; base; base = base->next) { - if (base->base->vtable) { - if (!base->is_virtual) { - CClass_FindDominator(base->base, offset1 + base->offset, object1, tclass2, offset2, tclass3); - } else { - SInt32 vboffset = CClass_VirtualBaseOffset(main_class, base->base); - CClass_FindDominator(base->base, vboffset, object1, tclass2, offset2, base->base); - } - } - } -} - -static void CClass_ConstructVTable(TypeClass *tclass, SInt32 voffset, SInt32 offset, TypeClass *baseclass) { - Object *object; - Object *thunkobject; - SInt32 newoffset; - SInt32 newvoffset; - ClassList *base; - SInt32 thunkoffset; - OLinkList *olink; - CScopeObjectIterator iter; - - CScope_InitObjectIterator(&iter, tclass->nspace); - while (1) { - if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) - break; - - if (object->datatype == DVFUNC) { - newoffset = voffset + TYPE_METHOD(object->type)->vtbl_index + CABI_GetVTableOffset(tclass); - CError_ASSERT(2288, newoffset < vtable_data_size); - - if (!vtable_object_data[newoffset]) { - cclass_dominator_vobject = object; - cclass_dominator_voffset = offset; - cclass_dominator_oobject = NULL; - cclass_dominator_ooffset = offset; - CClass_FindDominator(main_class, 0, NULL, NULL, 0, NULL); - - if (cclass_dominator_oobject) { - if (cclass_dominator_eobject) - CError_Error(CErrorStr251, main_class, 0, cclass_dominator_vobject, cclass_dominator_oobject, cclass_dominator_eobject); - } else { - cclass_dominator_oobject = object; - cclass_vbase = NULL; - } - - vtable_object_data[newoffset] = 1; - - if (!(TYPE_FUNC(cclass_dominator_oobject->type)->flags & FUNC_PURE)) { - if (!check_pures) { - thunkobject = cclass_dominator_oobject; - if ((thunkoffset = cclass_dominator_ooffset - offset)) { - if (cclass_vbase && (main_class->flags & CLASS_FLAGS_8000)) { - thunkobject = CClass_ThunkObject(cclass_dominator_oobject, thunkoffset, 0, - CABI_GetCtorOffsetOffset(cclass_vbase, tclass)); - } else { - thunkobject = CClass_ThunkObject(cclass_dominator_oobject, thunkoffset, 0, -1); - } - } - - olink = lalloc(sizeof(OLinkList)); - olink->next = vtable_object_links; - olink->obj = thunkobject; - olink->offset = newoffset; - olink->somevalue = 0; - vtable_object_links = olink; - } - } else { - found_pure = cclass_dominator_oobject; - } - } - } - } - - for (base = tclass->bases; base; base = base->next) { - if (base->base->vtable) { - if (base->is_virtual) { - newoffset = CClass_VirtualBaseOffset(main_class, base->base); - newvoffset = CClass_VirtualBaseVTableOffset(main_class, base->base); - CClass_ConstructVTable( - base->base, - newvoffset, - newoffset, - base->base - ); - } else { - CClass_ConstructVTable( - base->base, - voffset + base->voffset, - offset + base->offset, - baseclass - ); - } - } - } -} - -void CClass_ClassDefaultFuncAction(TypeClass *tclass) { -} - -void CClass_ClassAction(TypeClass *tclass) { - if (tclass->sominfo) { - CSOM_GenerateClassStructures(tclass); - } else if (tclass->vtable) { - vtable_data_size = tclass->vtable->size; - vtable_object_data = lalloc(vtable_data_size); - memclrw(vtable_object_data, vtable_data_size); - - main_class = tclass; - vtable_object_links = NULL; - found_pure = NULL; - check_pures = 0; - - CClass_AllocVTable(tclass); - - memclrw(vtable_object_data, vtable_data_size); - if (copts.RTTI && !(tclass->flags & (CLASS_SINGLE_OBJECT | CLASS_COM_OBJECT))) - vtable_object_links = CRTTI_ConstructVTableHeaders(tclass, vtable_object_data, vtable_object_links); - - CError_ASSERT(2492, tclass->vtable->object->type->size == tclass->vtable->size); - CInit_DeclareData(tclass->vtable->object, vtable_object_data, vtable_object_links, tclass->vtable->size); - } -} - -void CClass_MakeStaticActionClass(TypeClass *tclass) { - if (tclass->vtable) { - tclass->vtable->object->sclass = TK_STATIC; - tclass->vtable->object->qual |= Q_20000; - if (!(tclass->vtable->object->flags & OBJECT_FLAGS_2)) { - CParser_NewCallBackAction(tclass->vtable->object, tclass); - } else if (cparamblkptr->precompile != 1) { - CParser_NewClassAction(tclass); - } - } -} - -Object *CClass_CheckPures(TypeClass *tclass) { - return CClass_CheckVirtuals(tclass); -} - -void CClass_MemberDef(Object *obj, TypeClass *tclass) { - switch (tclass->action) { - case CLASS_ACTION_0: - break; - case CLASS_ACTION_1: - if (IS_TYPE_FUNC(obj->type) && (TYPE_FUNC(obj->type)->flags & FUNC_FLAGS_4)) { - if (obj->qual & Q_INLINE) { - if (tclass->sominfo) - CError_Error(CErrorStr280); - tclass->action = CLASS_ACTION_0; - CClass_MakeStaticActionClass(tclass); - } else if (cparamblkptr->precompile != 1) { - CParser_NewClassAction(tclass); - } - } - break; - case CLASS_ACTION_2: - CError_FATAL(2682); - break; - case CLASS_ACTION_3: - break; - default: - CError_FATAL(2701); - } -} - -Object *CClass_ThisSelfObject(void) { - ObjectList *list; - - if (cscope_currentfunc && cscope_currentclass) { - if (cscope_currentclass->objcinfo) { - for (list = arguments; list; list = list->next) { - if (list->object->name == self_name_node) - return list->object; - } - CError_Error(CErrorStr301); - } else { - if (cscope_is_member_func) { - for (list = arguments; list; list = list->next) { - if (list->object->name == this_name_node) - return list->object; - } - } - CError_Error(CErrorStr189); - } - } - - CError_Error(copts.cplusplus ? CErrorStr189 : CErrorStr301); - return NULL; -} - -ENode *CClass_CreateThisSelfExpr(void) { - Object *object; - ENode *expr; - - if (!(object = CClass_ThisSelfObject())) - return NULL; - - expr = create_objectrefnode(object); - expr->rtype = CDecl_NewPointerType(TYPE(cscope_currentclass)); - expr = makemonadicnode(expr, EINDIRECT); - expr->data.monadic->rtype = CDecl_NewPointerType(expr->rtype); - - return expr; -} - -static AccessType CClass_BaseMemberAccess(BClassList *path, AccessType access) { - ClassList *base; - - if (path->next) { - access = CClass_BaseMemberAccess(path->next, access); - switch (access) { - case ACCESSPRIVATE: - case ACCESSNONE: - return ACCESSNONE; - } - - for (base = TYPE_CLASS(path->type)->bases; ; base = base->next) { - if (!base) - return ACCESSNONE; - - if (base->base == TYPE_CLASS(path->next->type)) { - switch (base->access) { - case ACCESSNONE: - access = ACCESSNONE; - break; - case ACCESSPROTECTED: - if (access == ACCESSPUBLIC) - access = ACCESSPROTECTED; - break; - case ACCESSPRIVATE: - if (access == ACCESSPRIVATE) - access = ACCESSNONE; - else - access = ACCESSPRIVATE; - break; - case ACCESSPUBLIC: - break; - } - break; - } - } - } - - return access; -} - -static Boolean CClass_CanAccess(BClassList *path, AccessType access) { - AccessType access2; - BClassList *scan; - BClassList *next; - TypeClass *prevclass; - TypeClass *tclass; - ClassList *base; - ClassFriend *cfriend; - - tclass = TYPE_CLASS(path->type); - access2 = access; - if ((scan = path->next)) { - if (access2 != ACCESSPRIVATE) { - prevclass = tclass; - while (scan) { - for (base = prevclass->bases; base; base = base->next) { - if (base->base == TYPE_CLASS(scan->type)) - break; - } - - if (!base) - return 0; - - switch (base->access) { - case ACCESSNONE: - access2 = ACCESSNONE; - break; - case ACCESSPROTECTED: - if (access2 == ACCESSPUBLIC) - access2 = ACCESSPROTECTED; - break; - case ACCESSPRIVATE: - if (access2 == ACCESSPRIVATE) - access2 = ACCESSNONE; - else - access2 = ACCESSPRIVATE; - break; - case ACCESSPUBLIC: - break; - } - - prevclass = TYPE_CLASS(scan->type); - scan = scan->next; - } - } else { - access2 = ACCESSNONE; - } - } - - if (access2 == ACCESSPUBLIC) - return 1; - - if (access2 != ACCESSNONE) { - if (cscope_currentclass == tclass) - return 1; - if (cobjc_currentclass == tclass) - return 1; - - for (cfriend = tclass->friends; cfriend; cfriend = cfriend->next) { - if (cfriend->isclass) { - if (cfriend->u.theclass == cscope_currentclass) - return 1; - } else { - if (cfriend->u.obj == cscope_currentfunc) - return 1; - } - } - } - - for (scan = path; scan->next; scan = scan->next) { - if (CClass_CanAccess(scan->next, access)) { - if ((next = scan->next->next) || access != ACCESSPUBLIC) { - scan->next->next = NULL; - if (CClass_CanAccess(path, ACCESSPUBLIC)) { - scan->next->next = next; - return 1; - } - scan->next->next = next; - } - } - } - - return 0; -} - -void CClass_CheckPathAccess(BClassList *path, Object *obj, AccessType access) { - if (!CClass_CanAccess(path, access)) { - if (path && obj) - CError_Error(CErrorStr381, path->type, 0, obj); - else - CError_Error(CErrorStr187); - } -} - -static BClassList *CClass_PathCleanup(BClassList *path, TypeClass *tclass) { - BClassList *first; - ClassList *base; - - first = path; - - while (1) { - if (!path->next) { - if (!tclass) - return first; - if (path->type == TYPE(tclass)) - return first; - return NULL; - } - - if (path->type != path->next->type) { - for (base = TYPE_CLASS(path->type)->bases; base; base = base->next) { - if (base->base == TYPE_CLASS(path->next->type)) - break; - } - - if (base) { - path = path->next; - } else { - first = path = path->next; - } - } else { - path->next = path->next->next; - } - } -} - -void CClass_CheckStaticAccess(BClassList *path, TypeClass *tclass, AccessType access) { - ClassFriend *cfriend; - - if (path) { - path = CClass_PathCleanup(path, tclass); - if (path && path->next) { - if (!CClass_CanAccess(path, access)) - CError_Error(CErrorStr187); - return; - } - } - - switch (access) { - case ACCESSPUBLIC: - return; - case ACCESSPRIVATE: - case ACCESSPROTECTED: - if (tclass == cscope_currentclass) - return; - - for (cfriend = tclass->friends; cfriend; cfriend = cfriend->next) { - if (cfriend->isclass) { - if (cfriend->u.theclass == cscope_currentclass) - return; - } else { - if (cfriend->u.obj == cscope_currentfunc) - return; - } - } - case ACCESSNONE: - CError_Warning(CErrorStr187); - return; - default: - CError_FATAL(3013); - } -} - -void CClass_CheckObjectAccess(BClassList *path, Object *obj) { - short depth; - Boolean isambigbase; - - if (obj->nspace && obj->nspace->theclass) { - if (!path && cscope_currentclass) - path = CClass_GetBasePath(cscope_currentclass, obj->nspace->theclass, &depth, &isambigbase); - - CClass_CheckStaticAccess(path, obj->nspace->theclass, obj->access); - } -} - -void CClass_CheckEnumAccess(BClassList *path, ObjEnumConst *objec) { - if (path) { - if ((path = CClass_PathCleanup(path, NULL))) { - if (!CClass_CanAccess(path, objec->access)) - CError_Error(CErrorStr187); - return; - } - } - - if ( - objec->access != ACCESSPUBLIC && - IS_TYPE_ENUM(objec->type) && - TYPE_ENUM(objec->type)->nspace && - TYPE_ENUM(objec->type)->nspace->theclass - ) - CClass_CheckStaticAccess(NULL, TYPE_ENUM(objec->type)->nspace->theclass, objec->access); -} - -static Type *CClass_PointerTypeCopy(Type *type) { - Type *copy; - - switch (type->type) { - case TYPEPOINTER: - case TYPEARRAY: - copy = galloc(sizeof(TypePointer)); - *TYPE_POINTER(copy) = *TYPE_POINTER(type); - TPTR_TARGET(copy) = CClass_PointerTypeCopy(TPTR_TARGET(copy)); - return copy; - case TYPEMEMBERPOINTER: - copy = galloc(sizeof(TypeMemberPointer)); - *TYPE_MEMBER_POINTER(copy) = *TYPE_MEMBER_POINTER(type); - return copy; - default: - return type; - } -} - -Type *CClass_CombineClassAccessQualifiers(Type *type, UInt32 qual1, UInt32 qual2, UInt32 *outflags) { - Type *inner; - - qual2 = qual2 & (Q_CONST | Q_VOLATILE); - if (qual1 & Q_MUTABLE) - qual2 &= ~Q_CONST; - qual1 = qual1 & (Q_CONST | Q_VOLATILE); - - inner = type; - while (IS_TYPE_ARRAY(inner)) - inner = TPTR_TARGET(inner); - - switch (inner->type) { - case TYPEMEMBERPOINTER: - case TYPEPOINTER: - if (qual2) { - type = CClass_PointerTypeCopy(type); - inner = type; - while (IS_TYPE_ARRAY(inner)) - inner = TPTR_TARGET(inner); - - switch (inner->type) { - case TYPEPOINTER: - TPTR_QUAL(inner) |= qual2; - break; - case TYPEMEMBERPOINTER: - TYPE_MEMBER_POINTER(inner)->qual |= qual2; - break; - default: - CError_FATAL(3125); - } - } - break; - default: - qual1 |= qual2; - } - - *outflags = qual1; - return type; -} - -static void CClass_OptimizeBitFieldAccess(Type **ptype, SInt32 *poffset) { - Type *innertype; - TypeBitfield *newtype; - short i; - - innertype = TYPE_BITFIELD(*ptype)->bitfieldtype; - if (TYPE_BITFIELD(*ptype)->bitlength == 8) { - switch (TYPE_BITFIELD(*ptype)->offset) { - case 0: - i = 0; - break; - case 8: - i = 1; - break; - case 16: - i = 2; - break; - case 24: - i = 3; - break; - default: - i = -1; - break; - } - - if (i >= 0) { - if (innertype->size != 1) { - if (is_unsigned(TYPE_BITFIELD(*ptype)->bitfieldtype)) - *ptype = TYPE(&stunsignedchar); - else - *ptype = TYPE(&stsignedchar); - } else { - *ptype = innertype; - } - *poffset += i; - return; - } - } - - if (TYPE_BITFIELD(*ptype)->bitlength == 16) { - switch (TYPE_BITFIELD(*ptype)->offset) { - case 0: - i = 0; - break; - case 16: - i = 2; - break; - default: - i = -1; - break; - } - - if (i >= 0) { - if (innertype->size != stsignedshort.size) { - if (is_unsigned(innertype)) - *ptype = TYPE(&stunsignedshort); - else - *ptype = TYPE(&stsignedshort); - } else { - *ptype = innertype; - } - *poffset += i; - return; - } - } - - if (TYPE_BITFIELD(*ptype)->bitlength == 32 && TYPE_BITFIELD(*ptype)->offset == 0) { - if (innertype->size != stsignedlong.size) { - if (is_unsigned(innertype)) - *ptype = TYPE(&stunsignedlong); - else - *ptype = TYPE(&stsignedlong); - } else { - *ptype = innertype; - } - return; - } - - if ((*ptype)->size != stsignedchar.size) { - i = TYPE_BITFIELD(*ptype)->offset + TYPE_BITFIELD(*ptype)->bitlength - 1; - - if (TYPE_BITFIELD(*ptype)->bitlength < 8 && (TYPE_BITFIELD(*ptype)->offset & 0xFFF8) == (i & 0xFFF8)) { - newtype = galloc(sizeof(TypeBitfield)); - *newtype = *TYPE_BITFIELD(*ptype); - *ptype = TYPE(newtype); - - i = 0; - if (newtype->offset >= 8) - i = 1; - if (newtype->offset >= 16) - i = 2; - if (newtype->offset >= 24) - i = 3; - *poffset += i; - newtype->offset -= 8 * i; - - newtype->bitfieldtype = is_unsigned(innertype) ? TYPE(&stunsignedchar) : TYPE(&stsignedchar); - newtype->size = newtype->bitfieldtype->size; - return; - } - - if ((*ptype)->size != stsignedshort.size) { - if (TYPE_BITFIELD(*ptype)->bitlength < 16 && (TYPE_BITFIELD(*ptype)->offset & 0xFFF0) == (i & 0xFFF0)) { - newtype = galloc(sizeof(TypeBitfield)); - *newtype = *TYPE_BITFIELD(*ptype); - *ptype = TYPE(newtype); - - i = 0; - if (newtype->offset >= 16) - i = stsignedshort.size; - *poffset += i; - newtype->offset -= 8 * i; - - newtype->bitfieldtype = is_unsigned(innertype) ? TYPE(&stunsignedshort) : TYPE(&stsignedshort); - newtype->size = newtype->bitfieldtype->size; - return; - } - } - } -} - -ENode *CClass_AccessMember(ENode *classexpr, Type *type, UInt32 qual, SInt32 offset) { - Type *innertype; - UInt32 flags; - - innertype = NULL; - - if (IS_TYPE_CLASS(classexpr->rtype) && (TYPE_CLASS(classexpr->rtype)->flags & CLASS_HANDLEOBJECT)) { - classexpr = makemonadicnode(classexpr, EINDIRECT); - classexpr->data.monadic->rtype = CDecl_NewPointerType(classexpr->rtype); - } - - if (IS_TYPE_BITFIELD(type)) { - innertype = TYPE_BITFIELD(type)->bitfieldtype; - CClass_OptimizeBitFieldAccess(&type, &offset); - } - - if (offset && !canadd(classexpr->data.monadic, offset)) { - classexpr->data.monadic = makediadicnode( - classexpr->data.monadic, - intconstnode(TYPE(&stunsignedlong), offset), - EADD); - optimizecomm(classexpr->data.monadic); - } - - if (innertype) { - if (IS_TYPE_BITFIELD(type)) { - classexpr->data.monadic = makemonadicnode(classexpr->data.monadic, EBITFIELD); - classexpr->data.monadic->rtype = type; - classexpr->rtype = TYPE_BITFIELD(type)->bitfieldtype; - } else { - classexpr->rtype = type; - } - } else { - classexpr->rtype = type; - } - - classexpr->rtype = CClass_CombineClassAccessQualifiers(classexpr->rtype, qual, ENODE_QUALS(classexpr), &flags); - classexpr->flags = flags; - return classexpr; -} |