diff options
Diffstat (limited to 'compiler_and_linker/FrontEnd/C/CTemplateClass.c')
-rw-r--r-- | compiler_and_linker/FrontEnd/C/CTemplateClass.c | 1632 |
1 files changed, 1632 insertions, 0 deletions
diff --git a/compiler_and_linker/FrontEnd/C/CTemplateClass.c b/compiler_and_linker/FrontEnd/C/CTemplateClass.c new file mode 100644 index 0000000..8b3b889 --- /dev/null +++ b/compiler_and_linker/FrontEnd/C/CTemplateClass.c @@ -0,0 +1,1632 @@ +#include "compiler/CTemplateClass.h" +#include "compiler/CABI.h" +#include "compiler/CBrowse.h" +#include "compiler/CClass.h" +#include "compiler/CDecl.h" +#include "compiler/CError.h" +#include "compiler/CInline.h" +#include "compiler/CInt64.h" +#include "compiler/CMachine.h" +#include "compiler/CMangler.h" +#include "compiler/CParser.h" +#include "compiler/CPrep.h" +#include "compiler/CPrepTokenizer.h" +#include "compiler/CScope.h" +#include "compiler/CTemplateFunc.h" +#include "compiler/CTemplateNew.h" +#include "compiler/CTemplateTools.h" +#include "compiler/CompilerTools.h" +#include "compiler/objects.h" +#include "compiler/scopes.h" +#include "compiler/templates.h" + +TemplClass *CTemplClass_GetMasterTemplate(TemplClass *tmclass) { + if (tmclass->inst_parent) { + tmclass = TEMPL_CLASS(tmclass->theclass.nspace->theclass); + CError_ASSERT(42, tmclass->theclass.flags & CLASS_IS_TEMPL); + } + + return tmclass; +} + +static void CTemplClass_SetupActionErrorRef(TemplateAction *action, TStreamElement **saved) { + CError_ResetErrorSkip(); + CError_LockErrorPos(&action->source_ref, saved); +} + +static void CTemplClass_RestoreActionErrorRef(TStreamElement **saved) { + CError_ResetErrorSkip(); + CError_UnlockErrorPos(saved); +} + +static void CTemplClass_AppendTemplateAction(TemplClass *tmclass, TemplateAction *action) { + TemplateAction *last; + + action->source_ref = *CPrep_CurStreamElement(); + + if ((last = tmclass->actions)) { + while (last->next) + last = last->next; + last->next = action; + } else { + tmclass->actions = action; + } +} + +static DefAction *CTemplClass_NewDefAction(TypeDeduce *deduce, TemplateAction *action) { + DefAction *defAction = lalloc(sizeof(DefAction)); + defAction->next = deduce->defActions; + defAction->action = action; + deduce->defActions = defAction; + return defAction; +} + +static void CTemplClass_InsertTemplateAction(TemplClass *tmclass, TemplateAction *action) { + action->source_ref = *CPrep_CurStreamElement(); + action->next = tmclass->actions; + tmclass->actions = action; +} + +void CTemplClass_RegisterUsingDecl(TemplClass *tmclass, TypeTemplDep *type, AccessType access) { + TemplateAction *action; + + action = galloc(sizeof(TemplateAction)); + memclrw(action, sizeof(TemplateAction)); + + action->type = TAT_USINGDECL; + action->u.usingdecl.type = type; + action->u.usingdecl.access = access; + + CTemplClass_AppendTemplateAction(tmclass, action); +} + +void CTemplClass_RegisterFriend(TemplClass *tmclass, DeclInfo *di) { + TemplateFriend *tfriend; + TemplateAction *action; + + tfriend = galloc(sizeof(TemplateFriend)); + memclrw(tfriend, sizeof(TemplateFriend)); + + if (tk == '{' && IS_TYPE_FUNC(di->thetype)) { + di->qual |= Q_INLINE; + TYPE_FUNC(di->thetype)->flags |= FUNC_DEFINED | FUNC_IS_TEMPL_INSTANCE; + tfriend->fileoffset = cparser_fileoffset; + + CPrep_StreamGetBlock(&tfriend->stream, NULL, 1); + + if (lookahead() == ';') + tk = lex(); + else + tk = ';'; + } + + CDecl_PackDeclInfo(&tfriend->decl, di); + + action = galloc(sizeof(TemplateAction)); + memclrw(action, sizeof(TemplateAction)); + + action->type = TAT_FRIEND; + action->u.tfriend = tfriend; + + CTemplClass_AppendTemplateAction(tmclass, action); +} + +void CTemplClass_RegisterBaseClass(TemplClass *tmclass, Type *type, AccessType access, Boolean is_virtual) { + TemplateAction *action; + ClassList *insert_after; + + if ((insert_after = tmclass->theclass.bases)) { + while (insert_after->next) + insert_after = insert_after->next; + } + + action = galloc(sizeof(TemplateAction)); + memclrw(action, sizeof(TemplateAction)); + + action->type = TAT_BASE; + action->u.base.type = type; + action->u.base.insert_after = insert_after; + action->u.base.access = access; + action->u.base.is_virtual = is_virtual; + + CTemplClass_InsertTemplateAction(tmclass, action); +} + +void CTemplClass_RegisterEnumType(TemplClass *tmclass, TypeEnum *enumtype) { + TemplateAction *action; + + action = galloc(sizeof(TemplateAction)); + memclrw(action, sizeof(TemplateAction)); + + action->type = TAT_ENUMTYPE; + action->u.enumtype = enumtype; + + CTemplClass_AppendTemplateAction(tmclass, action); +} + +void CTemplClass_RegisterEnumerator(TemplClass *tmclass, ObjEnumConst *objenumconst, ENode *initexpr) { + TemplateAction *action; + + action = galloc(sizeof(TemplateAction)); + memclrw(action, sizeof(TemplateAction)); + + action->type = TAT_ENUMERATOR; + action->u.enumerator.objenumconst = objenumconst; + action->u.enumerator.initexpr = initexpr ? CInline_CopyExpression(initexpr, CopyMode1) : NULL; + + CTemplClass_AppendTemplateAction(tmclass, action); +} + +void CTemplClass_RegisterObjectInit(TemplClass *tmclass, Object *object, ENode *initexpr) { + TemplateAction *action; + + action = galloc(sizeof(TemplateAction)); + memclrw(action, sizeof(TemplateAction)); + + action->type = TAT_OBJECTINIT; + action->u.objectinit.object = object; + action->u.objectinit.initexpr = CInline_CopyExpression(initexpr, CopyMode1); + + CTemplClass_AppendTemplateAction(tmclass, action); +} + +void CTemplClass_RegisterObjectDef(TemplClass *tmclass, ObjBase *refobj) { + TemplateAction *action; + + action = galloc(sizeof(TemplateAction)); + memclrw(action, sizeof(TemplateAction)); + + action->type = TAT_OBJECTDEF; + action->u.refobj = refobj; + + CTemplClass_AppendTemplateAction(tmclass, action); +} + +void CTemplClass_CompleteClass(TemplClass *templ, ClassLayout *de) { + templ->lex_order_count = de->lex_order_count; + if (de->has_vtable) + templ->flags |= TEMPLCLASS_HAS_VTABLE; + templ->theclass.flags |= CLASS_COMPLETED; +} + +static TemplClassInst *CTemplClass_NewInstance(TemplClass *templ, TemplArg *inst_args, TemplArg *oargs) { + TemplClassInst *inst; + ObjTypeTag *tag; + NameSpace *nspace; + HashNameNode *name; + + CError_ASSERT(288, !templ->pspec_owner); + + inst = galloc(sizeof(TemplClassInst)); + memclrw(inst, sizeof(TemplClassInst)); + + inst->next = templ->instances; + templ->instances = inst; + + if (templ->templ__params) + name = CMangler_TemplateInstanceName(templ->theclass.classname, oargs ? oargs : inst_args); + else + name = templ->theclass.classname; + + inst->inst_args = inst_args; + inst->oargs = oargs; + inst->parent = templ->inst_parent; + + nspace = CScope_NewListNameSpace(name, 1); + nspace->theclass = TYPE_CLASS(inst); + if (templ->templ_parent && templ->inst_parent) { + nspace->parent = TYPE_CLASS(templ->inst_parent)->nspace; + } else { + NameSpace *scan = templ->theclass.nspace->parent; + while (scan->is_templ) + scan = scan->parent; + nspace->parent = scan; + } + + inst->theclass.type = TYPECLASS; + inst->theclass.flags = CLASS_IS_TEMPL_INST; + inst->theclass.nspace = nspace; + inst->theclass.classname = templ->theclass.classname; + inst->theclass.mode = templ->theclass.mode; + inst->theclass.eflags = templ->theclass.eflags; + inst->templ = templ; + + tag = galloc(sizeof(ObjTypeTag)); + memclrw(tag, sizeof(ObjTypeTag)); + + tag->otype = OT_TYPETAG; + tag->access = ACCESSPUBLIC; + tag->type = TYPE(inst); + CScope_AddObject(nspace, templ->theclass.classname, OBJ_BASE(tag)); + + return inst; +} + +TemplClassInst *CTemplClass_GetInstance(TemplClass *tmclass, TemplArg *inst_args, TemplArg *oargs) { + TemplClassInst *inst; + + for (inst = tmclass->instances; inst; inst = inst->next) { + CError_ASSERT(353, !oargs); + + if (CTemplTool_EqualArgs(inst_args, inst->oargs ? inst->oargs : inst->inst_args)) + return inst; + } + + return CTemplClass_NewInstance(tmclass, inst_args, oargs); +} + +TemplateMember *CTemplClass_DefineMember(TemplClass *tmclass, Object *object, FileOffsetInfo *foi, TokenStream *stream) { + TemplateMember *member; + + for (member = tmclass->members; member; member = member->next) { + if (member->object == object) { + CError_Error(CErrorStr333, object); + return member; + } + } + + member = galloc(sizeof(TemplateMember)); + memclrw(member, sizeof(TemplateMember)); + member->next = tmclass->members; + tmclass->members = member; + + member->params = NULL; + member->object = object; + member->fileoffset = *foi; + member->stream = *stream; + + return member; +} + +static void CTemplClass_ParseBody(TemplClass *templ, short mode, SInt32 *offset) { + DeclInfo di; + + templ->align = copts.structalignment; + + memclrw(&di, sizeof(di)); + di.file = CPrep_BrowserCurrentFile(); + CPrep_BrowserFilePosition(&di.file2, &di.sourceoffset); + di.sourceoffset = *offset; + di.x28 = templ; + + CDecl_ParseClass(&di, mode, 1, 0); + + if (tk == TK_UU_ATTRIBUTE_UU) + CParser_ParseAttribute(di.thetype, NULL); + if (tk != ';') + CError_Error(CErrorStr123); + + CBrowse_NewTemplateClass(templ, di.file2, di.sourceoffset, CPrep_BrowserFileOffset() + 1); +} + +void CTemplClass_ParsePartialSpecialization(DeclFucker *what_is_this, TemplParam *params, short mode, SInt32 *offset) { + Type *type; + NameSpace *nspace; + TemplArg *args; + TemplPartialSpec *pspec; + TemplClass *templ; + TemplArg *arg; + TemplParam *param; + + nspace = what_is_this->nspace; + + if ((tk = lex()) != TK_IDENTIFIER) { + CError_Error(CErrorStr107); + return; + } + + if (!(type = CScope_GetLocalTagType(nspace, tkidentifier))) { + CError_Error(CErrorStr140, tkidentifier->name); + return; + } + + if (!IS_TEMPL_CLASS(type)) { + CError_Error(CErrorStr132, tkidentifier->name); + return; + } + + if ((tk = lex()) != '<') + CError_FATAL(469); + + for (param = params; param; param = param->next) { + switch (param->pid.type) { + case TPT_TYPE: + if (!param->data.typeparam.type) + continue; + CError_Error(CErrorStr344); + break; + + case TPT_NONTYPE: + if (!param->data.paramdecl.defaultarg) + continue; + CError_Error(CErrorStr344); + break; + + case TPT_TEMPLATE: + if (!param->data.templparam.defaultarg) + continue; + CError_Error(CErrorStr344); + break; + + default: + CError_FATAL(501); + } + + break; + } + + args = CTempl_ParseUncheckTemplArgs(TEMPL_CLASS(type)->templ__params, 0); + tk = lex(); + + arg = args; + param = TEMPL_CLASS(type)->templ__params; + while (1) { + if (!arg) { + if (!param) + break; + CError_Error(CErrorStr344); + return; + } + if (!param) { + CError_Error(CErrorStr344); + return; + } + if (param->pid.type != arg->pid.type) { + CError_Error(CErrorStr344); + return; + } + arg = arg->next; + param = param->next; + } + + if (CTemplTool_IsSameTemplate(TEMPL_CLASS(type)->templ__params, args)) + CError_Error(CErrorStr344); + + for (pspec = TEMPL_CLASS(type)->pspecs; pspec; pspec = pspec->next) { + if (CTemplTool_EqualParams(pspec->templ->templ__params, params, 0) && CTemplTool_EqualArgs(pspec->args, args)) + break; + } + + if (!pspec) { + templ = galloc(sizeof(TemplClass)); + memclrw(templ, sizeof(TemplClass)); + + templ->templ__params = params; + CDecl_DefineClass(nspace, TEMPL_CLASS(type)->theclass.classname, TYPE_CLASS(templ), mode, 0, 0); + + templ->theclass.flags = CLASS_IS_TEMPL; + templ->pspec_owner = TEMPL_CLASS(type); + + pspec = galloc(sizeof(TemplPartialSpec)); + memclrw(pspec, sizeof(TemplPartialSpec)); + + pspec->templ = templ; + pspec->args = CTemplTool_MakeGlobalTemplArgCopy(args); + pspec->next = TEMPL_CLASS(type)->pspecs; + TEMPL_CLASS(type)->pspecs = pspec; + } else { + if ((pspec->templ->theclass.flags & CLASS_COMPLETED) && tk != ';') { + CError_Error(CErrorStr132, TEMPL_CLASS(type)->theclass.classname->name); + return; + } + + if (tk == ':' || tk == '{') + CTemplTool_EqualParams(pspec->templ->templ__params, params, 1); + } + + switch (tk) { + case ':': + case '{': + CTemplClass_ParseBody(pspec->templ, mode, offset); + break; + case ';': + break; + default: + CError_Error(CErrorStr121); + } +} + +void CTemplClass_ParseClass(DeclFucker *what_is_this, TemplParam *params, short mode, SInt32 *offset) { + TemplClass *templ; + NameSpace *nspace; + Type *type; + UInt8 classDeclSpec = 0; + + nspace = what_is_this->nspace; + if ((tk = lex()) == TK_UU_DECLSPEC) + CDecl_ParseClassDeclSpec(&classDeclSpec); + + if (tk != TK_IDENTIFIER) { + CError_Error(CErrorStr107); + return; + } + + type = CScope_GetLocalTagType(nspace, tkidentifier); + if (!type) { + templ = galloc(sizeof(TemplClass)); + memclrw(templ, sizeof(TemplClass)); + + templ->next = ctempl_templates; + ctempl_templates = templ; + + templ->templ__params = params; + CDecl_DefineClass(nspace, tkidentifier, TYPE_CLASS(templ), mode, 0, 1); + templ->theclass.flags = CLASS_IS_TEMPL; + templ->theclass.eflags = classDeclSpec; + + tk = lex(); + if (nspace->theclass && (nspace->theclass->flags & CLASS_IS_TEMPL)) { + TemplateAction *action; + + templ->templ_parent = TEMPL_CLASS(nspace->theclass); + + action = galloc(sizeof(TemplateAction)); + memclrw(action, sizeof(TemplateAction)); + + action->type = TAT_NESTEDCLASS; + action->u.tclasstype = templ; + CTemplClass_AppendTemplateAction(templ->templ_parent, action); + } + } else { + if (!IS_TEMPL_CLASS(type)) { + CError_Error(CErrorStr132, tkidentifier->name); + return; + } + + templ = TEMPL_CLASS(type); + if (!CTemplTool_EqualParams(templ->templ__params, params, 0)) { + CError_Error(CErrorStr132, templ->theclass.classname->name); + return; + } + + CTemplTool_MergeDefaultArgs(templ->templ__params, params); + templ->theclass.eflags |= classDeclSpec; + + tk = lex(); + + if ((templ->theclass.flags & CLASS_COMPLETED) && tk != ';') { + CError_Error(CErrorStr132, templ->theclass.classname->name); + return; + } + + if (tk != ';') + CTemplTool_EqualParams(templ->templ__params, params, 1); + } + + switch (tk) { + case ':': + case '{': + CTemplClass_ParseBody(templ, mode, offset); + break; + case ';': + break; + default: + CError_Error(CErrorStr121); + } +} + +static Boolean CTemplClass_TypeParamCompare(TemplArg *arg, Type *type, UInt32 qual) { + return is_typesame(type, arg->data.typeparam.type) && arg->data.typeparam.qual == qual; +} + +static TemplArg *CTemplClass_PartialTemplateArgMatch(TemplPartialSpec *pspec, TemplArg *args, Boolean flag) { + TemplArg *argA; + TemplArg *argB; + int i; + DeduceInfo info; + + if (!CTemplTool_InitDeduceInfo(&info, pspec->templ->templ__params, NULL, 1)) + return NULL; + + argA = pspec->args; + argB = args; + while (1) { + if (!argA) { + if (argB) + return NULL; + + for (i = 0; i < info.maxCount; i++) { + if (!info.args[i].is_deduced) + return NULL; + } + + if (flag) + return CTemplTool_MakeTemplArgList(&info); + else + return args; + } + + if (!argB) + return NULL; + + if (argA->pid.type != argB->pid.type) + return NULL; + + switch (argA->pid.type) { + case TPT_TYPE: + if (CTemplTool_IsTemplateArgumentDependentType(argA->data.typeparam.type)) { + if (!CTempl_DeduceType( + argA->data.typeparam.type, argA->data.typeparam.qual, + argB->data.typeparam.type, argB->data.typeparam.qual, + info.args, 0, 0 + )) + return NULL; + } else { + if ( + !is_typesame(argA->data.typeparam.type, argB->data.typeparam.type) || + argA->data.typeparam.qual != argB->data.typeparam.qual + ) + return NULL; + } + break; + + case TPT_NONTYPE: + if (CTemplTool_IsTemplateArgumentDependentExpression(argA->data.paramdecl.expr)) { + i = CTempl_GetTemplateArgumentExpressionIndex(argA); + CError_ASSERT(789, i >= 0); + + if (info.args[i].is_deduced) { + if (!CTemplTool_EqualExprTypes(argB->data.paramdecl.expr, info.args[i].data.paramdecl.expr)) + return NULL; + } else { + info.args[i].data.paramdecl.expr = argB->data.paramdecl.expr; + info.args[i].pid.type = TPT_NONTYPE; + info.args[i].is_deduced = 1; + } + } else { + if (!CTemplTool_EqualExprTypes(argB->data.paramdecl.expr, argA->data.paramdecl.expr)) + return NULL; + } + break; + + case TPT_TEMPLATE: + if (CTemplTool_IsTemplateArgumentDependentType(argA->data.ttargtype)) { + if (!CTempl_DeduceType( + argA->data.ttargtype, 0, + argB->data.ttargtype, 0, + info.args, 0, 0 + )) + return NULL; + } else { + if (!is_typesame(argA->data.ttargtype, argB->data.ttargtype)) + return NULL; + } + break; + + default: + CError_FATAL(830); + } + + argA = argA->next; + argB = argB->next; + } +} + +static Boolean CTemplClass_PartialClassIsAtLeastAsSpecialized(TemplPartialSpec *pspec1, TemplPartialSpec *pspec2) { + TemplArg *argA; + TemplArg *argB; + int i; + DeduceInfo info; + + if (!CTemplTool_InitDeduceInfo(&info, pspec2->templ->templ__params, NULL, 1)) + return 0; + + argA = pspec1->args; + argB = pspec2->args; + + while (1) { + if (!argA) { + CError_ASSERT(856, !argB); + + for (i = 0; i < info.maxCount; i++) { + if (!info.args[i].is_deduced) + return 0; + } + + return 1; + } + + CError_ASSERT(865, argB); + CError_ASSERT(866, argA->pid.type == argB->pid.type); + + switch (argA->pid.type) { + case TPT_TYPE: + if (!CTempl_DeduceType( + argB->data.typeparam.type, argB->data.typeparam.qual, + argA->data.typeparam.type, argA->data.typeparam.qual, + info.args, 0, 0 + )) + return 0; + break; + + case TPT_NONTYPE: + if (CTemplTool_IsTemplateArgumentDependentExpression(argB->data.paramdecl.expr)) { + i = CTempl_GetTemplateArgumentExpressionIndex(argB); + CError_ASSERT(907, i >= 0); + + if (info.args[i].is_deduced) { + if (argA->data.paramdecl.expr) { + if (!info.args[i].data.paramdecl.expr || !CTemplTool_EqualExprTypes(argA->data.paramdecl.expr, info.args[i].data.paramdecl.expr)) + return 0; + } else { + if (info.args[i].data.paramdecl.expr || argA->pid.index != info.args[i].pid.index) + return 0; + } + } else { + info.args[i].data.paramdecl.expr = argA->data.paramdecl.expr; + info.args[i].pid.index = argA->pid.index; + info.args[i].pid.type = TPT_NONTYPE; + info.args[i].is_deduced = 1; + } + } else { + if ( + !argA->data.paramdecl.expr || + !CTemplTool_EqualExprTypes(argA->data.paramdecl.expr, argB->data.paramdecl.expr) + ) + return 0; + } + break; + + case TPT_TEMPLATE: + if (!CTempl_DeduceType( + argB->data.ttargtype, 0, + argA->data.ttargtype, 0, + info.args, 0, 0 + )) + return 0; + break; + + default: + CError_FATAL(955); + } + + argA = argA->next; + argB = argB->next; + } +} + +static Boolean CTemplClass_PartialClassIsMoreSpecialized(TemplPartialSpec *pspec1, TemplPartialSpec *pspec2) { + return CTemplClass_PartialClassIsAtLeastAsSpecialized(pspec1, pspec2) && + !CTemplClass_PartialClassIsAtLeastAsSpecialized(pspec2, pspec1); +} + +typedef struct PSpecList { + struct PSpecList *next; + TemplPartialSpec *pspec; +} PSpecList; + +static PSpecList *CTemplClass_FindMostSpecializedPartialSpecializations(PSpecList *list) { + PSpecList **array; + PSpecList *scan; + int i; + int j; + int count; + + scan = list; + count = 0; + while (scan) { + scan = scan->next; + count++; + } + + array = lalloc(sizeof(PSpecList *) * count); + for (i = 0, scan = list; scan; scan = scan->next) + array[i++] = scan; + + for (i = 0; i < count; i++) { + if (array[i]) { + for (j = 0; j < count; j++) { + if (array[j] && i != j && CTemplClass_PartialClassIsMoreSpecialized(array[i]->pspec, array[j]->pspec)) + array[j] = NULL; + } + } + } + + for (i = 0, list = NULL; i < count; i++) { + if (array[i]) { + if (!list) + list = array[i]; + else + array[j]->next = array[i]; + array[i]->next = NULL; + j = i; + } + } + + return list; +} + +Boolean CTemplClass_FindPartialTemplate(TemplArg *args, TemplClass **resultTempl, TemplArg **resultArgs) { + TemplPartialSpec *pspec; + PSpecList *list; + TemplClassInst *inst; + + for (inst = (*resultTempl)->instances; inst; inst = inst->next) { + if (inst->is_instantiated || inst->is_specialized) { + if (CTemplTool_EqualArgs(args, inst->oargs ? inst->oargs : inst->inst_args)) + return 0; + } + } + + list = NULL; + for (pspec = (*resultTempl)->pspecs; pspec; pspec = pspec->next) { + if (CTemplClass_PartialTemplateArgMatch(pspec, args, 0)) { + PSpecList *entry = lalloc(sizeof(PSpecList)); + entry->next = list; + entry->pspec = pspec; + list = entry; + } + } + + if (list) { + if (list->next) { + list = CTemplClass_FindMostSpecializedPartialSpecializations(list); + if (list->next) + CError_Error(CErrorStr346); + } + + if (!list->pspec->templ->templ__params) { + *resultTempl = list->pspec->templ; + *resultArgs = NULL; + return 1; + } + + *resultTempl = list->pspec->templ; + *resultArgs = CTemplClass_PartialTemplateArgMatch(list->pspec, args, 1); + return *resultArgs != NULL; + } else { + return 0; + } +} + +TemplClass *CTemplClass_DefineNestedClass(TemplClass *parent, HashNameNode *name, short mode) { + TemplateAction *action; + TemplClass *templ; + + templ = galloc(sizeof(TemplClass)); + memclrw(templ, sizeof(TemplClass)); + + templ->next = ctempl_templates; + ctempl_templates = templ; + + templ->templ_parent = parent; + templ->templ__params = NULL; + CDecl_DefineClass(parent->theclass.nspace, name, TYPE_CLASS(templ), mode, 0, 1); + + templ->theclass.flags = CLASS_IS_TEMPL; + templ->align = copts.structalignment; + + action = galloc(sizeof(TemplateAction)); + memclrw(action, sizeof(TemplateAction)); + + action->type = TAT_NESTEDCLASS; + action->u.tclasstype = templ; + CTemplClass_AppendTemplateAction(parent, action); + + return templ; +} + +static void CTemplClass_CopyNestedClass(TypeDeduce *deduce, TemplClass *templ) { + ObjTypeTag *tag; + + tag = galloc(sizeof(ObjTypeTag)); + memclrw(tag, sizeof(ObjTypeTag)); + + tag->otype = OT_TYPETAG; + tag->access = ACCESSPUBLIC; + + if (!templ->templ__params) { + TemplClassInst *inst = CTemplClass_NewInstance(templ, NULL, NULL); + inst->parent = deduce->inst; + inst->theclass.nspace->parent = deduce->inst->theclass.nspace; + + tag->type = TYPE(inst); + } else { + TemplClass *copy = galloc(sizeof(TemplClass)); + memclrw(copy, sizeof(TemplClass)); + + copy->next = ctempl_templates; + ctempl_templates = copy; + + copy->theclass = templ->theclass; + copy->templ_parent = deduce->tmclass; + copy->inst_parent = deduce->inst; + copy->templ__params = templ->templ__params; + copy->members = NULL; + copy->instances = NULL; + copy->pspecs = NULL; + copy->actions = templ->actions; + copy->lex_order_count = templ->lex_order_count; + copy->align = templ->align; + copy->flags = templ->flags; + + tag->type = TYPE(copy); + } + + CScope_AddObject(deduce->inst->theclass.nspace, templ->theclass.classname, OBJ_BASE(tag)); +} + +static void CTemplClass_CopyBaseClasses(TypeDeduce *deduce, TemplClassInst *inst, TemplClass *templ) { + TemplateAction *action; + ClassList *newBase; + ClassList *templbase; + ClassList *instbase; + ClassList *base; + UInt32 qual = 0; + + for (base = templ->theclass.bases; base; base = base->next) { + ClassList *scan; + newBase = galloc(sizeof(ClassList)); + *newBase = *base; + newBase->next = NULL; + + if ((scan = inst->theclass.bases)) { + while (1) { + if (scan->base == newBase->base) { + CError_Error(CErrorStr131); + break; + } + if (!scan->next) { + scan->next = newBase; + break; + } + scan = scan->next; + } + } else { + inst->theclass.bases = newBase; + } + } + + for (action = deduce->tmclass->actions; action; action = action->next) { + if (action->type == TAT_BASE) { + TStreamElement *save; + + CTemplClass_SetupActionErrorRef(action, &save); + + newBase = galloc(sizeof(ClassList)); + memclrw(newBase, sizeof(ClassList)); + + newBase->base = TYPE_CLASS(CTemplTool_DeduceTypeCopy(deduce, action->u.base.type, &qual)); + newBase->access = action->u.base.access; + newBase->is_virtual = action->u.base.is_virtual; + + if (IS_TYPE_CLASS(newBase->base)) { + if (newBase->base->size == 0) { + CDecl_CompleteType(TYPE(newBase->base)); + IsCompleteType(TYPE(newBase->base)); + } + + if (CDecl_CheckNewBase(TYPE_CLASS(inst), newBase->base, newBase->is_virtual)) { + if (action->u.base.insert_after) { + templbase = templ->theclass.bases; + instbase = inst->theclass.bases; + while (1) { + CError_ASSERT(1222, templbase && instbase); + + if (templbase == action->u.base.insert_after) { + newBase->next = instbase->next; + instbase->next = newBase; + break; + } + + templbase = templbase->next; + instbase = instbase->next; + } + } else { + newBase->next = inst->theclass.bases; + inst->theclass.bases = newBase; + } + } + } else { + CError_Error(CErrorStr131); + } + + CTemplClass_RestoreActionErrorRef(&save); + } + } + + if (inst->theclass.flags & CLASS_HAS_VBASES) + CDecl_MakeVBaseList(TYPE_CLASS(inst)); +} + +static void CTemplClass_CopyEnum(TypeDeduce *deduce, TemplateAction *action) { + TypeEnum *destenum; + TypeEnum *srcenum; + ObjEnumConst **destptr; + ObjEnumConst *src; + TemplateAction *scanaction; + + srcenum = action->u.enumtype; + destenum = galloc(sizeof(TypeEnum)); + memclrw(destenum, sizeof(TypeEnum)); + + destenum->type = TYPEENUM; + destenum->size = srcenum->size; + destenum->nspace = deduce->inst->theclass.nspace; + destenum->enumtype = srcenum->enumtype; + destenum->enumname = srcenum->enumname; + + if (destenum->enumname) + CScope_DefineTypeTag(destenum->nspace, destenum->enumname, TYPE(destenum)); + + src = srcenum->enumlist; + destptr = &destenum->enumlist; + while (src) { + ObjEnumConst *dest; + + dest = galloc(sizeof(ObjEnumConst)); + *dest = *src; + + *destptr = dest; + dest->next = NULL; + dest->type = TYPE(destenum); + CScope_AddObject(deduce->inst->theclass.nspace, dest->name, OBJ_BASE(dest)); + + src = src->next; + destptr = &(*destptr)->next; + } + + for (scanaction = deduce->tmclass->actions; scanaction; scanaction = scanaction->next) { + if (scanaction->type == TAT_ENUMERATOR && scanaction->u.enumerator.objenumconst->type == TYPE(srcenum)) { + CTemplClass_NewDefAction(deduce, action)->enumtype = destenum; + return; + } + } +} + +static void CTemplClass_CompleteEnumType(TypeDeduce *deduce, TemplateAction *action, TypeEnum *destenum) { + TypeEnum *srcenum; + ObjEnumConst *dest; + TemplateAction *scanaction; + ENode *expr; + ObjEnumConst *src; + + srcenum = action->u.enumtype; + + for (scanaction = deduce->tmclass->actions; scanaction; scanaction = scanaction->next) { + if (scanaction->type == TAT_ENUMERATOR) { + src = scanaction->u.enumerator.objenumconst; + if (src->type == TYPE(srcenum)) { + TStreamElement *save; + + CTemplClass_SetupActionErrorRef(scanaction, &save); + + dest = destenum->enumlist; + while (dest) { + if (dest->name == src->name) + break; + dest = dest->next; + } + + CError_ASSERT(1332, dest); + + if (scanaction->u.enumerator.initexpr) { + expr = CTemplTool_DeduceExpr(deduce, scanaction->u.enumerator.initexpr); + if (!ENODE_IS(expr, EINTCONST)) { + CError_Error(CErrorStr124); + CTemplClass_RestoreActionErrorRef(&save); + break; + } + } else { + CError_ASSERT(1347, expr); + expr->data.intval = CInt64_Add(expr->data.intval, cint64_one); + } + + dest->val = expr->data.intval; + dest->type = expr->rtype; + CTemplClass_RestoreActionErrorRef(&save); + } + } + } + + CDecl_ComputeUnderlyingEnumType(destenum); +} + +static void CTemplClass_CopyObjMemberVarPath(TypeDeduce *deduce, ObjMemberVarPath *ivar) { + ObjMemberVarPath *copy; + + copy = galloc(sizeof(ObjMemberVarPath)); + *copy = *ivar; + + if (copy->path && copy->path->type == TYPE(deduce->tmclass)) { + copy->path = CClass_GetPathCopy(copy->path, 1); + copy->path->type = TYPE(deduce->inst); + } + + CScope_AddObject(deduce->inst->theclass.nspace, copy->name, OBJ_BASE(copy)); +} + +static void CTemplClass_CopyIVars(TypeDeduce *deduce, TemplClassInst *inst, TemplClass *templ) { + ObjMemberVar *src; + ObjMemberVar *dest; + ObjMemberVar **destptr; + TemplateAction *scanaction; + + src = templ->theclass.ivars; + destptr = &inst->theclass.ivars; + + while (src) { + CError_ASSERT(1397, !src->has_path); + + dest = galloc(sizeof(ObjMemberVar)); + *dest = *src; + + for (scanaction = deduce->tmclass->actions; scanaction; scanaction = scanaction->next) { + if (scanaction->type == TAT_OBJECTDEF && scanaction->u.refobj == OBJ_BASE(src)) { + CTemplClass_NewDefAction(deduce, scanaction)->refobj = OBJ_BASE(dest); + break; + } + } + + if (!scanaction) { + dest->type = CTemplTool_DeduceTypeCopy(deduce, dest->type, &dest->qual); + if (dest->type->size == 0) { + CDecl_CompleteType(dest->type); + IsCompleteType(dest->type); + } + } + + if (dest->name && dest->name != no_name_node) + CScope_AddObject(inst->theclass.nspace, dest->name, OBJ_BASE(dest)); + + *destptr = dest; + destptr = &dest->next; + src = src->next; + } +} + +static void CTemplClass_CopyObjType(TypeDeduce *deduce, ObjType *src, HashNameNode *name) { + TemplateAction *scanaction; + NameSpaceObjectList *list; + NameSpaceObjectList *newlist; + ObjType *dest; + + for (scanaction = deduce->tmclass->actions; scanaction; scanaction = scanaction->next) { + if (scanaction->type == TAT_OBJECTDEF && scanaction->u.refobj == OBJ_BASE(src)) + break; + } + + dest = galloc(sizeof(ObjType)); + *dest = *src; + + if (scanaction) + CTemplClass_NewDefAction(deduce, scanaction)->refobj = OBJ_BASE(dest); + else + dest->type = CTemplTool_DeduceTypeCopy(deduce, dest->type, &dest->qual); + + if ((list = CScope_FindName(deduce->inst->theclass.nspace, name)) && list->object->otype == OT_TYPETAG) { + CError_ASSERT(1470, list->next == NULL); + + newlist = galloc(sizeof(NameSpaceObjectList)); + newlist->object = list->object; + newlist->next = NULL; + + list->object = OBJ_BASE(dest); + list->next = newlist; + } else { + CScope_AddObject(deduce->inst->theclass.nspace, name, OBJ_BASE(dest)); + } +} + +static void CTemplClass_CopyObjTypeTag(TypeDeduce *deduce, ObjTypeTag *src, HashNameNode *name) { + UInt32 qual = 0; + ObjTypeTag *dest = galloc(sizeof(ObjTypeTag)); + + *dest = *src; + dest->type = CTemplTool_DeduceTypeCopy(deduce, dest->type, &qual); + + CScope_AddObject(deduce->inst->theclass.nspace, name, OBJ_BASE(dest)); +} + +static void CTemplClass_CopyMemberTemplate(TypeDeduce *deduce, Object *src) { + TemplateFunction *desttempl; + Object *dest; + TemplateFunction *srctempl; + TemplateAction *action; + + srctempl = src->u.func.u.templ; + CError_ASSERT(1516, srctempl && srctempl->params); + + for (action = deduce->tmclass->actions; action; action = action->next) { + if (action->type == TAT_OBJECTDEF && action->u.refobj == OBJ_BASE(src)) + break; + } + + desttempl = galloc(sizeof(TemplateFunction)); + *desttempl = *srctempl; + + desttempl->next = ctempl_templatefuncs; + ctempl_templatefuncs = desttempl; + + desttempl->unk4 = srctempl; + + dest = galloc(sizeof(Object)); + *dest = *src; + + dest->u.func.u.templ = desttempl; + dest->nspace = deduce->inst->theclass.nspace; + + CError_ASSERT(1541, !deduce->x15); + deduce->x15 = 1; + deduce->nindex = srctempl->params->pid.nindex; + + if (action) + CTemplClass_NewDefAction(deduce, action)->refobj = OBJ_BASE(dest); + else + dest->type = CTemplTool_DeduceTypeCopy(deduce, dest->type, &dest->qual); + + deduce->x15 = 0; + + CError_ASSERT(1553, IS_TYPE_FUNC(dest->type)); + + TYPE_FUNC(dest->type)->flags |= FUNC_IS_TEMPL; + + if ( + (TYPE_FUNC(dest->type)->flags & FUNC_IS_CTOR) && + deduce->x17 && + !action + ) + { + FuncArg *arg; + CError_ASSERT(1560, TYPE_FUNC(dest->type)->args); + arg = CParser_NewFuncArg(); + arg->type = TYPE(&stsignedshort); + arg->next = TYPE_FUNC(dest->type)->args->next; + TYPE_FUNC(dest->type)->args->next = arg; + } + + CScope_AddObject(deduce->inst->theclass.nspace, dest->name, OBJ_BASE(dest)); +} + +static void CTemplClass_CopyObject(TypeDeduce *deduce, Object *src) { + ObjectTemplated *dest; + TemplateAction *action; + TemplateAction *action2; + Boolean flag; + + flag = 1; + if (src->nspace != deduce->tmclass->theclass.nspace) { + CError_ASSERT(1587, src->datatype == DALIAS); + flag = 0; + } + + if (IS_TEMPL_FUNC(src->type)) { + CTemplClass_CopyMemberTemplate(deduce, src); + return; + } + + for (action = deduce->tmclass->actions; action; action = action->next) { + if (action->type == TAT_OBJECTDEF && action->u.refobj == OBJ_BASE(src)) + break; + } + + dest = galloc(sizeof(ObjectTemplated)); + dest->object = *src; + + if (action) + CTemplClass_NewDefAction(deduce, action)->refobj = OBJ_BASE(dest); + else + dest->object.type = CTemplTool_DeduceTypeCopy(deduce, dest->object.type, &dest->object.qual); + + if (flag) + dest->object.nspace = deduce->inst->theclass.nspace; + + dest->object.qual |= Q_IS_TEMPLATED; + dest->parent = src; + + if (IS_TYPE_FUNC(dest->object.type)) + TYPE_FUNC(dest->object.type)->flags &= ~FUNC_DEFINED; + + switch (dest->object.datatype) { + case DDATA: + dest->object.u.data.linkname = NULL; + for (action2 = deduce->tmclass->actions; action2; action2 = action2->next) { + if (action2->type == TAT_OBJECTINIT && action2->u.objectinit.object == src) { + CTemplClass_NewDefAction(deduce, action2)->refobj = OBJ_BASE(dest); + break; + } + } + break; + + case DABSOLUTE: + break; + + case DFUNC: + case DVFUNC: + dest->object.u.func.linkname = NULL; + CError_ASSERT(1650, IS_TYPE_FUNC(dest->object.type)); + CError_ASSERT(1651, !dest->object.u.func.u.templ && !dest->object.u.func.defargdata); + + if ( + (TYPE_FUNC(dest->object.type)->flags & FUNC_IS_CTOR) && + deduce->x17 && + !action + ) + { + FuncArg *arg; + CError_ASSERT(1657, TYPE_FUNC(dest->object.type)->args); + arg = CParser_NewFuncArg(); + arg->type = TYPE(&stsignedshort); + arg->next = TYPE_FUNC(dest->object.type)->args->next; + TYPE_FUNC(dest->object.type)->args->next = arg; + } + + if (TYPE_FUNC(dest->object.type)->flags & FUNC_CONVERSION) { + CError_ASSERT(1665, IS_TYPE_FUNC(src->type)); + if (CTemplTool_IsTemplateArgumentDependentType(TYPE_FUNC(src->type)->functype)) { + CError_ASSERT(1668, action); + return; + } + } + + break; + + case DINLINEFUNC: + break; + + case DALIAS: + if (dest->object.u.alias.member && dest->object.u.alias.member->type == TYPE(deduce->tmclass)) { + dest->object.u.alias.member = CClass_GetPathCopy(dest->object.u.alias.member, 1); + dest->object.u.alias.member->type = TYPE(deduce->inst); + } + break; + + case DLOCAL: + case DEXPR: + CError_FATAL(1688); + + default: + CError_FATAL(1691); + } + + CScope_AddObject(deduce->inst->theclass.nspace, dest->object.name, OBJ_BASE(dest)); +} + +static void CTemplClass_CompleteObject(TypeDeduce *deduce, TemplateAction *action, ObjBase *refobj) { + if (refobj->otype == OT_MEMBERVAR) { + ObjMemberVar *ivar = OBJ_MEMBER_VAR(refobj); + ivar->type = CTemplTool_DeduceTypeCopy(deduce, ivar->type, &ivar->qual); + + if (ivar->type->size == 0) { + CDecl_CompleteType(ivar->type); + if (copts.experimental) { + if (ivar->next || ivar->type->size != 0 || !IS_TYPE_ARRAY(ivar->type)) + IsCompleteType(ivar->type); + } else { + IsCompleteType(ivar->type); + } + } + } else if (refobj->otype == OT_TYPE) { + ObjType *obj = OBJ_TYPE(refobj); + obj->type = CTemplTool_DeduceTypeCopy(deduce, obj->type, &obj->qual); + } else { + Object *dest; + Object *src; + + CError_ASSERT(1737, refobj->otype == OT_OBJECT); + + dest = OBJECT(refobj); + src = OBJECT(action->u.refobj); + + if (IS_TEMPL_FUNC(src->type)) { + TemplateFunction *templ = src->u.func.u.templ; + CError_ASSERT(1747, templ); + CError_ASSERT(1748, !deduce->x15); + + deduce->x15 = 1; + deduce->nindex = templ->params->pid.nindex; + dest->type = CTemplTool_DeduceTypeCopy(deduce, dest->type, &dest->qual); + deduce->x15 = 0; + + CError_ASSERT(1753, IS_TYPE_FUNC(dest->type)); + TYPE_FUNC(dest->type)->flags |= FUNC_IS_TEMPL; + } else { + dest->type = CTemplTool_DeduceTypeCopy(deduce, dest->type, &dest->qual); + dest->qual |= Q_IS_TEMPLATED; + + if (IS_TYPE_FUNC(dest->type)) + TYPE_FUNC(dest->type)->flags &= ~FUNC_DEFINED; + + switch (dest->datatype) { + case DFUNC: + case DVFUNC: + CError_ASSERT(1769, IS_TYPE_FUNC(dest->type)); + if (TYPE_FUNC(dest->type)->flags & FUNC_CONVERSION) { + CError_ASSERT(1772, IS_TYPE_FUNC(dest->type)); + if (CTemplTool_IsTemplateArgumentDependentType(TYPE_FUNC(src->type)->functype)) { + dest->name = CMangler_ConversionFuncName( + TYPE_FUNC(dest->type)->functype, TYPE_FUNC(dest->type)->qual); + CScope_AddObject(deduce->inst->theclass.nspace, dest->name, OBJ_BASE(dest)); + } + } + + if ((TYPE_FUNC(dest->type)->flags & FUNC_IS_CTOR) && deduce->x17) { + FuncArg *arg; + CError_ASSERT(1786, TYPE_FUNC(dest->type)->args); + arg = CParser_NewFuncArg(); + arg->type = TYPE(&stsignedshort); + arg->next = TYPE_FUNC(dest->type)->args->next; + TYPE_FUNC(dest->type)->args->next = arg; + } + + break; + } + } + } +} + +static void CTemplClass_CompleteObjectInit(TypeDeduce *deduce, TemplateAction *action, Object *object) { + ENode *expr = CTemplTool_DeduceExpr(deduce, action->u.objectinit.initexpr); + + if (ENODE_IS(expr, EINTCONST) && (object->qual & Q_CONST) && IS_TYPE_INT_OR_ENUM(object->type)) { + object->u.data.u.intconst = expr->data.intval; + object->qual |= Q_INLINE_DATA | Q_20000; + } else { + CError_Error(CErrorStr354, object->name->name); + } +} + +static void CTemplClass_CopyNameSpace(TypeDeduce *deduce, TemplClassInst *inst, TemplClass *templ) { + NameSpaceName *nsname; + NameSpaceObjectList *list; + + CError_ASSERT(1830, !templ->theclass.nspace->is_hash); + + for (nsname = templ->theclass.nspace->data.list; nsname; nsname = nsname->next) { + for (list = &nsname->first; list; list = list->next) { + switch (list->object->otype) { + case OT_ENUMCONST: + break; + case OT_MEMBERVAR: + if (OBJ_MEMBER_VAR(list->object)->has_path) + CTemplClass_CopyObjMemberVarPath(deduce, OBJ_MEMBER_VAR_PATH(list->object)); + break; + case OT_TYPE: + CTemplClass_CopyObjType(deduce, OBJ_TYPE(list->object), nsname->name); + break; + case OT_TYPETAG: + break; + case OT_NAMESPACE: + CError_FATAL(1854); + case OT_OBJECT: + CTemplClass_CopyObject(deduce, OBJECT(list->object)); + break; + default: + CError_FATAL(1861); + } + } + } +} + +static void CTemplClass_CopyUsingDecl(TypeDeduce *deduce, TypeTemplDep *type, AccessType access) { + TypeClass *tclass; + UInt32 qual = 0; + + CError_ASSERT(1878, IS_TYPE_TEMPLATE(type) && type->dtype == TEMPLDEP_QUALNAME); + + tclass = TYPE_CLASS(CTemplTool_DeduceTypeCopy(deduce, TYPE(type->u.qual.type), &qual)); + if (!IS_TYPE_CLASS(tclass)) { + CError_Error(CErrorStr340, type->u.qual.name->name); + return; + } + + CDecl_CompleteType(TYPE(tclass)); + CScope_AddClassUsingDeclaration(TYPE_CLASS(deduce->inst), tclass, type->u.qual.name, access); +} + +static void CTemplClass_CopyFriend(TypeDeduce *deduce, TemplateFriend *tfriend) { + TemplArg *arg; + Object *funcobj; + Boolean flag; + CScopeSave saveScope; + DeclInfo di; + + CDecl_UnpackDeclInfo(&di, &tfriend->decl); + + if (CTemplTool_IsTemplateArgumentDependentType(di.thetype)) + di.thetype = CTemplTool_DeduceTypeCopy(deduce, di.thetype, &di.qual); + + if (di.expltargs) { + di.expltargs = CTemplTool_MakeGlobalTemplArgCopy(di.expltargs); + for (arg = di.expltargs; arg; arg = arg->next) { + switch (arg->pid.type) { + case TPT_TYPE: + if (CTemplTool_IsTemplateArgumentDependentType(arg->data.typeparam.type)) + arg->data.typeparam.type = CTemplTool_DeduceTypeCopy(deduce, arg->data.typeparam.type, &arg->data.typeparam.qual); + break; + case TPT_NONTYPE: + if (CTemplTool_IsTemplateArgumentDependentExpression(arg->data.paramdecl.expr)) + arg->data.paramdecl.expr = CTemplTool_DeduceExpr(deduce, arg->data.paramdecl.expr); + break; + case TPT_TEMPLATE: + default: + CError_FATAL(1930); + } + } + } + + if (IS_TYPE_FUNC(di.thetype)) { + CScope_SetNameSpaceScope(CScope_FindGlobalNS(deduce->inst->theclass.nspace), &saveScope); + funcobj = CDecl_GetFunctionObject(&di, NULL, &flag, 0); + CScope_RestoreScope(&saveScope); + + if (funcobj) { + CDecl_AddFriend(TYPE_CLASS(deduce->inst), funcobj, NULL); + if (tfriend->stream.tokens) + CInline_AddInlineFunctionAction(funcobj, TYPE_CLASS(deduce->inst), &tfriend->fileoffset, &tfriend->stream, 0); + } else { + CError_Error(CErrorStr201); + } + } else { + CError_ASSERT(1963, IS_TYPE_CLASS(di.thetype)); + CDecl_AddFriend(TYPE_CLASS(deduce->inst), NULL, TYPE_CLASS(di.thetype)); + } +} + +Boolean CTempl_InstantiateTemplateClass(TypeClass *tclass) { + TemplClassInst *inst; + ParserTryBlock *tryBlock; + TemplateAction *action; + DefAction *defAction; + UInt8 saveAlignMode; + + TypeDeduce deduce; + TemplStack stack; + CScopeSave saveScope; + ClassLayout layout; + TemplClass *templ; + TStreamElement *saveErrorRef; + TemplArg *inst_args; + + CError_ASSERT(1989, tclass->flags & CLASS_IS_TEMPL_INST); + + if (tclass->flags & CLASS_COMPLETED) + return 1; + + inst = TEMPL_CLASS_INST(tclass); + if (inst->is_specialized) + return 0; + + templ = inst->templ; + if (!(templ->flags & TEMPLCLASS_FLAGS_2)) + templ = CTemplClass_GetMasterTemplate(templ); + + if (templ->pspecs && CTemplClass_FindPartialTemplate(inst->inst_args, &templ, &inst_args)) { + CError_ASSERT(2013, !inst->oargs); + inst->templ = templ; + inst->oargs = inst->inst_args; + inst->inst_args = inst_args; + } + + if (!(templ->theclass.flags & CLASS_COMPLETED)) + return 0; + + if (inst->is_instantiated) + return 0; + + inst->is_instantiated = 1; + CScope_SetClassScope(tclass, &saveScope); + CTemplTool_PushInstance(&stack, tclass, NULL); + + tryBlock = trychain; + trychain = NULL; + + memclrw(&deduce, sizeof(deduce)); + deduce.tmclass = templ; + deduce.inst = inst; + deduce.params = templ->templ__params; + deduce.args = inst->inst_args; + + CError_ASSERT(2045, !templ->theclass.sominfo); + CError_ASSERT(2047, !templ->theclass.objcinfo); + CError_ASSERT(2049, !templ->theclass.vtable); + + inst->theclass.flags |= templ->theclass.flags & + (CLASS_ABSTRACT | CLASS_SINGLE_OBJECT | CLASS_HAS_VBASES | CLASS_IS_CONVERTIBLE | CLASS_COM_OBJECT); + + CTemplClass_CopyBaseClasses(&deduce, inst, templ); + + deduce.x17 = (inst->theclass.flags & CLASS_HAS_VBASES) && !(templ->theclass.flags & CLASS_HAS_VBASES); + + for (action = templ->actions; action; action = action->next) { + switch (action->type) { + case TAT_NESTEDCLASS: + CTemplClass_SetupActionErrorRef(action, &saveErrorRef); + CTemplClass_CopyNestedClass(&deduce, action->u.tclasstype); + CTemplClass_RestoreActionErrorRef(&saveErrorRef); + break; + case TAT_ENUMTYPE: + CTemplClass_SetupActionErrorRef(action, &saveErrorRef); + CTemplClass_CopyEnum(&deduce, action); + CTemplClass_RestoreActionErrorRef(&saveErrorRef); + break; + case TAT_FRIEND: + case TAT_ENUMERATOR: + case TAT_BASE: + case TAT_OBJECTINIT: + case TAT_USINGDECL: + case TAT_OBJECTDEF: + break; + default: + CError_FATAL(2094); + } + } + + CTemplClass_CopyIVars(&deduce, inst, templ); + CTemplClass_CopyNameSpace(&deduce, inst, templ); + + CError_ASSERT(2105, !templ->theclass.friends); + + for (action = templ->actions; action; action = action->next) { + switch (action->type) { + case TAT_NESTEDCLASS: + break; + case TAT_ENUMTYPE: + for (defAction = deduce.defActions; defAction; defAction = defAction->next) { + if (defAction->action == action) { + CTemplClass_SetupActionErrorRef(action, &saveErrorRef); + CTemplClass_CompleteEnumType(&deduce, action, defAction->enumtype); + CTemplClass_RestoreActionErrorRef(&saveErrorRef); + break; + } + } + break; + case TAT_FRIEND: + CTemplClass_SetupActionErrorRef(action, &saveErrorRef); + CTemplClass_CopyFriend(&deduce, action->u.tfriend); + CTemplClass_RestoreActionErrorRef(&saveErrorRef); + break; + case TAT_ENUMERATOR: + break; + case TAT_BASE: + break; + case TAT_OBJECTINIT: + for (defAction = deduce.defActions; ; defAction = defAction->next) { + CError_ASSERT(2136, defAction); + if (defAction->action == action) { + CTemplClass_SetupActionErrorRef(action, &saveErrorRef); + CTemplClass_CompleteObjectInit(&deduce, action, OBJECT(defAction->refobj)); + CTemplClass_RestoreActionErrorRef(&saveErrorRef); + break; + } + } + break; + case TAT_USINGDECL: + CTemplClass_SetupActionErrorRef(action, &saveErrorRef); + CTemplClass_CopyUsingDecl(&deduce, action->u.usingdecl.type, action->u.usingdecl.access); + CTemplClass_RestoreActionErrorRef(&saveErrorRef); + break; + case TAT_OBJECTDEF: + for (defAction = deduce.defActions; ; defAction = defAction->next) { + CError_ASSERT(2156, defAction); + if (defAction->action == action) { + CTemplClass_SetupActionErrorRef(action, &saveErrorRef); + CTemplClass_CompleteObject(&deduce, action, defAction->refobj); + CTemplClass_RestoreActionErrorRef(&saveErrorRef); + break; + } + } + break; + } + } + + memclrw(&layout, sizeof(layout)); + layout.lex_order_count = templ->lex_order_count; + layout.has_vtable = templ->flags & TEMPLCLASS_HAS_VTABLE; + + saveAlignMode = copts.structalignment; + copts.structalignment = templ->align; + CDecl_CompleteClass(&layout, TYPE_CLASS(inst)); + copts.structalignment = saveAlignMode; + + if (templ->theclass.align > inst->theclass.align) { + inst->theclass.align = templ->theclass.align; + inst->theclass.size += CABI_StructSizeAlignValue(TYPE(inst), inst->theclass.size); + } + + CTemplTool_PopInstance(&stack); + CScope_RestoreScope(&saveScope); + trychain = tryBlock; + + return 1; +} |