MWCC/compiler_and_linker/unsorted/CTemplateClass.c

1633 lines
52 KiB
C

#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;
}