MWCC/compiler_and_linker/unsorted/CTemplateNew.c

1882 lines
56 KiB
C
Raw Normal View History

2022-12-29 12:32:55 +00:00
#include "compiler/CTemplateNew.h"
#include "compiler/CBrowse.h"
#include "compiler/CDecl.h"
#include "compiler/CError.h"
#include "compiler/CExpr.h"
#include "compiler/CFunc.h"
#include "compiler/CInit.h"
#include "compiler/CInline.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/CTemplateClass.h"
#include "compiler/CTemplateTools.h"
#include "compiler/CompilerTools.h"
#include "compiler/ObjGenMachO.h"
#include "compiler/objects.h"
#include "compiler/scopes.h"
#include "compiler/templates.h"
TemplClass *ctempl_templates;
TemplateFunction *ctempl_templatefuncs;
TemplStack *ctempl_curinstance;
static jmp_buf ctempl_parseparse;
static Boolean ctempl_scanfuncparams;
// forward decls
static TemplParam *CTempl_ParseParamList(NameSpace *nspace, UInt8 nindex);
static Boolean CTempl_GenClassInstance(TemplClassInst *inst, Boolean flag);
void CTempl_Setup(void) {
ctempl_curinstance = NULL;
ctempl_templates = NULL;
ctempl_templatefuncs = NULL;
ctempl_instdepth = 0;
ctempl_scanfuncparams = 0;
}
void CTempl_Cleanup(void) {
}
static short CTempl_MemberParseLex(void) {
switch ((tk = lex())) {
case ';':
case '=':
case '{':
case '}':
longjmp(ctempl_parseparse, 1);
}
return tk;
}
static void CTempl_MemberParseTemplArgList(void) {
struct {
char ch;
char flag;
} stack[256];
int pos;
stack[0].ch = '>';
stack[0].flag = 1;
pos = 0;
while (1) {
switch (CTempl_MemberParseLex()) {
case '<':
if (stack[pos].flag) {
if (pos >= 255)
longjmp(ctempl_parseparse, 1);
stack[++pos].ch = '>';
stack[pos].flag = 1;
}
continue;
case '(':
if (pos >= 255)
longjmp(ctempl_parseparse, 1);
stack[++pos].ch = ')';
stack[pos].flag = 0;
continue;
case '[':
if (pos >= 255)
longjmp(ctempl_parseparse, 1);
stack[++pos].ch = ']';
stack[pos].flag = 0;
continue;
case '>':
if (!(stack[pos].flag))
continue;
case ')':
case ']':
break;
default:
continue;
}
if (tk != stack[pos].ch)
longjmp(ctempl_parseparse, 1);
if (--pos < 0)
break;
}
}
static Type *CTempl_MemberParseTempl(HashNameNode *name) {
Type *type;
type = CScope_GetTagType(cscope_current, name);
if (!type || !IS_TEMPL_CLASS(type))
longjmp(ctempl_parseparse, 1);
CTempl_MemberParseTemplArgList();
if (lookahead() != TK_COLON_COLON)
return NULL;
CTempl_MemberParseLex();
while (1) {
switch (CTempl_MemberParseLex()) {
case TK_IDENTIFIER:
switch (lookahead()) {
case '(':
case ')':
case ';':
case '=':
case '[':
return type;
case TK_COLON_COLON:
CTempl_MemberParseLex();
continue;
default:
return NULL;
}
break;
case '~':
case TK_OPERATOR:
return type;
default:
return NULL;
}
}
}
static Boolean CTempl_ParseTemplateMember(void) {
HashNameNode *name;
SInt32 state;
CPrep_UnLex();
CPrep_TokenStreamGetState(&state);
if (setjmp(ctempl_parseparse) == 0) {
while (1) {
switch (CTempl_MemberParseLex()) {
case TK_IDENTIFIER:
name = tkidentifier;
switch (lookahead()) {
case '<':
CTempl_MemberParseLex();
if (CTempl_MemberParseTempl(name)) {
CError_FATAL(228);
return 1;
}
break;
case TK_COLON_COLON:
CTempl_MemberParseLex();
while (1) {
if (CTempl_MemberParseLex() != TK_IDENTIFIER)
break;
if (lookahead() != TK_COLON_COLON)
break;
CTempl_MemberParseLex();
}
break;
}
break;
case 0:
return 0;
default:
continue;
}
break;
}
while (1) {
switch (CTempl_MemberParseLex()) {
case TK_IDENTIFIER:
name = tkidentifier;
if (CTempl_MemberParseLex() == '<') {
if (CTempl_MemberParseTempl(name)) {
CError_FATAL(265);
return 1;
}
}
break;
case 0:
return 0;
default:
continue;
}
break;
}
}
CPrep_TokenStreamSetState(&state);
tk = lex();
return 0;
}
static Type *CTempl_ParseTemplArgType(UInt32 *resultQual) {
DeclInfo di;
memclrw(&di, sizeof(di));
CParser_GetDeclSpecs(&di, 0);
if (di.storageclass)
CError_Error(CErrorStr177);
if (di.x48)
CError_Error(CErrorStr121);
CError_QualifierCheck(di.qual & ~(Q_CONST | Q_VOLATILE | Q_PASCAL | Q_REFERENCE | Q_ALIGNED_MASK));
scandeclarator(&di);
if (di.name)
CError_Error(CErrorStr121);
CTemplTool_CheckTemplArgType(di.thetype);
*resultQual = di.qual;
return di.thetype;
}
static ENode *CTempl_ParseTemplArgExpr(Type *type, UInt32 qual) {
ENode *expr;
ENode *copy;
disallowgreaterthan = 1;
if (copts.old_argmatch)
expr = conv_assignment_expression();
else
expr = assignment_expression();
disallowgreaterthan = 0;
if (type && !CTemplTool_IsTemplateArgumentDependentType(type) && !IS_TYPE_TEMPLDEPEXPR(expr->rtype)) {
expr = argumentpromotion(expr, type, qual, 1);
if (IS_TYPE_POINTER_ONLY(type)) {
if (ENODE_IS(expr, ETYPCON) && ENODE_IS(expr->data.monadic, EINTCONST))
expr = expr->data.monadic;
if (ENODE_IS(expr, EINTCONST))
expr->rtype = type;
}
}
if (!IS_TYPE_TEMPLDEPEXPR(expr->rtype)) {
if (!copts.old_argmatch)
expr = pointer_generation(expr);
switch (expr->type) {
case EINTCONST:
break;
case EOBJREF:
if (CParser_HasInternalLinkage2(expr->data.objref))
CError_Error(CErrorStr357);
break;
case EOBJLIST:
CError_Error(CErrorStr199);
expr = nullnode();
break;
default:
CError_Error(CErrorStr371);
expr = nullnode();
}
copy = galloc(sizeof(ENode));
*copy = *expr;
return copy;
} else {
return CInline_CopyExpression(expr, CopyMode1);
}
}
static Type *CTempl_ParseTemplArgTempl(TemplParam *params) {
CScopeParseResult pr;
if (
(tk != TK_IDENTIFIER && tk != TK_COLON_COLON) ||
!CScope_ParseDeclName(&pr) ||
!pr.x8
)
{
CError_Error(CErrorStr121);
tk = lex();
return NULL;
}
if (IS_TEMPL_CLASS(pr.x8)) {
if (params && !CTemplTool_EqualParams(params->data.templparam.plist, TEMPL_CLASS(pr.x8)->templ__params, 0)) {
CError_Error(CErrorStr235);
tk = lex();
return NULL;
}
} else {
if (!CTemplTool_IsTemplateArgumentDependentType(pr.x8))
CError_Error(CErrorStr146);
}
tk = lex();
return pr.x8;
}
static UInt8 CTempl_GetTemplateNestIndex(NameSpace *nspace) {
UInt8 count = 0;
while (nspace) {
if (nspace->theclass && (nspace->theclass->flags & CLASS_FLAGS_900))
count++;
nspace = nspace->parent;
}
return count;
}
static TemplParam *CTempl_ParseParam(NameSpace *nspace, TemplParam *paramList, int index, UInt8 nindex) {
TemplParam *param;
DeclInfo di;
short startToken;
SInt32 savedState;
param = galloc(sizeof(TemplParam));
memclrw(param, sizeof(TemplParam));
param->pid.index = index;
param->pid.nindex = nindex;
CPrep_TokenStreamGetState(&savedState);
switch ((startToken = tk)) {
case TK_CLASS:
case TK_TYPENAME:
if ((tk = lex()) == TK_IDENTIFIER) {
param->name = tkidentifier;
tk = lex();
}
switch (tk) {
case ',':
case '>':
break;
case '=':
tk = lex();
param->data.typeparam.type = CTempl_ParseTemplArgType(&param->data.typeparam.qual);
break;
default:
param->name = NULL;
CPrep_TokenStreamSetState(&savedState);
tk = startToken;
goto defaultProc;
}
param->pid.type = TPT_TYPE;
break;
case TK_TEMPLATE:
if ((tk = lex()) != '<') {
CError_Error(CErrorStr230);
return NULL;
}
tk = lex();
param->data.templparam.plist = CTempl_ParseParamList(nspace, 0);
if (tk == '>')
tk = lex();
else
CError_Error(CErrorStr231);
if (tk == TK_CLASS)
tk = lex();
else
CError_Error(CErrorStr121);
if (tk == TK_IDENTIFIER) {
param->name = tkidentifier;
tk = lex();
}
if (tk == '=') {
tk = lex();
param->data.templparam.defaultarg = CTempl_ParseTemplArgTempl(param);
}
param->pid.type = TPT_TEMPLATE;
break;
default:
defaultProc:
memclrw(&di, sizeof(di));
CParser_GetDeclSpecs(&di, 0);
if (di.storageclass)
CError_Error(CErrorStr177);
CError_QualifierCheck(di.qual & ~(Q_CONST | Q_VOLATILE | Q_PASCAL | Q_REFERENCE | Q_ALIGNED_MASK));
scandeclarator(&di);
switch (di.thetype->type) {
case TYPEARRAY:
di.thetype = CDecl_NewPointerType(TPTR_TARGET(di.thetype));
break;
case TYPEFUNC:
di.thetype = CDecl_NewPointerType(di.thetype);
break;
case TYPEMEMBERPOINTER:
CError_Error(CErrorStr190);
di.thetype = TYPE(&stsignedint);
break;
case TYPEINT:
case TYPEENUM:
case TYPETEMPLATE:
case TYPEPOINTER:
break;
default:
CError_Error(CErrorStr229);
di.thetype = TYPE(&stsignedint);
}
di.thetype = CParser_RemoveTopMostQualifiers(di.thetype, &di.qual);
param->name = di.name;
param->data.paramdecl.type = di.thetype;
param->data.paramdecl.qual = di.qual;
if (tk == '=') {
tk = lex();
param->data.paramdecl.defaultarg = CTempl_ParseTemplArgExpr(di.thetype, di.qual);
}
param->pid.type = TPT_NONTYPE;
break;
}
if (param->name)
CTemplTool_InsertTemplateParameter(nspace, param);
return param;
}
static TemplParam *CTempl_ParseParamList(NameSpace *nspace, UInt8 nindex) {
TemplParam *params;
TemplParam **ptr;
TemplParam *param;
TemplParam *scan;
int index;
params = NULL;
index = 0;
ptr = &params;
while (1) {
param = CTempl_ParseParam(nspace, params, index, nindex);
if (!param)
break;
if (param->name) {
for (scan = params; scan; scan = scan->next) {
if (scan->name == param->name)
CError_Error(CErrorStr122, param->name->name);
}
}
*ptr = param;
ptr = &param->next;
if (tk != ',')
break;
tk = lex();
index++;
}
if (!params)
CError_Error(CErrorStr229);
return params;
}
TemplArg *CTempl_ParseUncheckTemplArgs(TemplParam *params, Boolean is_global) {
TemplArg *args;
TemplArg *last;
int index;
if (tk != '<') {
CError_Error(CErrorStr230);
return NULL;
}
if ((tk = lex()) == '>')
return NULL;
args = NULL;
index = 0;
while (1) {
if (is_global) {
if (args) {
last->next = galloc(sizeof(TemplArg));
last = last->next;
} else {
last = galloc(sizeof(TemplArg));
args = last;
}
} else {
if (args) {
last->next = lalloc(sizeof(TemplArg));
last = last->next;
} else {
last = galloc(sizeof(TemplArg));
args = last;
}
}
last->next = NULL;
if (!params) {
Type *type;
UInt32 qual;
Boolean flag;
last->pid.index = index;
last->pid.nindex = 0;
if ((type = CParser_ParseTypeID(&qual, &flag))) {
if (flag) {
last->data.ttargtype = type;
last->pid.type = TPT_TEMPLATE;
} else {
last->data.typeparam.type = type;
last->data.typeparam.qual = qual;
last->pid.type = TPT_TYPE;
}
} else {
last->data.paramdecl.expr = CTempl_ParseTemplArgExpr(NULL, 0);
last->pid.type = TPT_NONTYPE;
}
} else {
last->pid = params->pid;
switch (last->pid.type) {
case TPT_TYPE:
last->data.typeparam.type = CTempl_ParseTemplArgType(&last->data.typeparam.qual);
break;
case TPT_NONTYPE:
last->data.paramdecl.expr = CTempl_ParseTemplArgExpr(NULL, 0);
break;
case TPT_TEMPLATE:
if (!(last->data.ttargtype = CTempl_ParseTemplArgTempl(params)))
return NULL;
break;
default:
CError_FATAL(674);
}
params = params->next;
}
if (tk == '>')
return args;
if (tk != ',') {
CError_Error(CErrorStr116);
return NULL;
}
tk = lex();
index++;
}
}
static TemplArg *CTempl_ParseTemplArgs(TemplClass **resultTempl, TemplArg **resultArgs) {
TemplParam *param;
TemplParam *params;
TemplArg *args;
TemplArg **ptr;
TemplArg *arg;
params = (*resultTempl)->templ__params;
*resultArgs = NULL;
if (tk != '<') {
CError_Error(CErrorStr230);
return NULL;
}
tk = lex();
param = params;
args = NULL;
ptr = &args;
while (param) {
arg = galloc(sizeof(TemplArg));
memclrw(arg, sizeof(TemplArg));
*ptr = arg;
ptr = &arg->next;
arg->pid = param->pid;
if (tk != '>') {
switch (arg->pid.type) {
case TPT_TYPE:
arg->data.typeparam.type = CTempl_ParseTemplArgType(&arg->data.typeparam.qual);
break;
case TPT_NONTYPE:
if (CTemplTool_IsTemplateArgumentDependentType(param->data.paramdecl.type)) {
Type *type;
UInt32 qual;
type = CTemplTool_DeduceArgDepType(args, param->data.paramdecl.type, param->data.paramdecl.qual, &qual);
arg->data.paramdecl.expr = CTempl_ParseTemplArgExpr(type, qual);
} else {
arg->data.paramdecl.expr = CTempl_ParseTemplArgExpr(param->data.paramdecl.type, param->data.paramdecl.qual);
}
break;
case TPT_TEMPLATE:
if (!(arg->data.ttargtype = CTempl_ParseTemplArgTempl(param)))
return NULL;
break;
default:
CError_FATAL(742);
}
if (tk != '>') {
if (tk != ',') {
CError_Error(CErrorStr232);
return NULL;
}
if ((tk = lex()) == '>') {
CError_Error(CErrorStr232);
return NULL;
}
}
} else {
switch (arg->pid.type) {
case TPT_TYPE:
if (!param->data.typeparam.type) {
CError_Error(CErrorStr232);
return NULL;
}
arg->data.typeparam.type = param->data.typeparam.type;
arg->data.typeparam.qual = param->data.typeparam.qual;
if (CTemplTool_IsTemplateArgumentDependentType(param->data.typeparam.type)) {
TypeDeduce deduce;
memclrw(&deduce, sizeof(deduce));
deduce.tmclass = *resultTempl;
deduce.inst = NULL;
deduce.params = params;
deduce.args = args;
arg->data.typeparam.qual = param->data.typeparam.qual;
arg->data.typeparam.type = CTemplTool_DeduceTypeCopy(&deduce, arg->data.typeparam.type, &arg->data.typeparam.qual);
}
break;
case TPT_NONTYPE:
if (!param->data.paramdecl.defaultarg) {
CError_Error(CErrorStr232);
return NULL;
}
if (IS_TYPE_TEMPLDEPEXPR(param->data.paramdecl.defaultarg->rtype)) {
TypeDeduce deduce;
memclrw(&deduce, sizeof(deduce));
deduce.tmclass = *resultTempl;
deduce.inst = NULL;
deduce.params = params;
deduce.args = args;
arg->data.paramdecl.expr = CInline_CopyExpression(
CTemplTool_DeduceExpr(&deduce, param->data.paramdecl.defaultarg), CopyMode1);
} else {
arg->data.paramdecl.expr = param->data.paramdecl.defaultarg;
}
break;
case TPT_TEMPLATE:
if (!param->data.templparam.defaultarg) {
CError_Error(CErrorStr232);
return NULL;
}
if (IS_TEMPL_CLASS(param->data.templparam.defaultarg)) {
arg->data.ttargtype = param->data.templparam.defaultarg;
break;
}
if (CTemplTool_IsTemplateArgumentDependentType(param->data.templparam.defaultarg)) {
CError_Error(CErrorStr190);
return NULL;
}
CError_FATAL(817);
default:
CError_FATAL(820);
}
}
param = param->next;
}
if (tk != '>') {
CError_Error(CErrorStr231);
return NULL;
}
if ((*resultTempl)->pspecs)
return args;
return args;
}
Type *CTempl_ParseTemplTemplParam(TypeTemplDep *type) {
TemplArg *args;
Type *newType;
tk = lex();
if (!(args = CTempl_ParseUncheckTemplArgs(NULL, 1))) {
CError_Error(CErrorStr121);
return TYPE(&stsignedint);
}
newType = CDecl_NewTemplDepType(TEMPLDEP_QUALTEMPL);
TYPE_TEMPLATE(newType)->u.qualtempl.type = type;
TYPE_TEMPLATE(newType)->u.qualtempl.args = args;
return newType;
}
Type *CTempl_ClassGetType(TemplClass *templ) {
TemplClass *owner;
TemplArg *ownerArgs;
TemplArg *args;
Type *type;
owner = templ;
if (templ->pspec_owner)
owner = templ->pspec_owner;
if (!(args = CTempl_ParseTemplArgs(&owner, &ownerArgs)))
return &stvoid;
if ((type = CTemplTool_IsDependentTemplate(owner, args)))
return type;
return TYPE(CTemplClass_GetInstance(owner, args, ownerArgs));
}
static void CTempl_SetupClassParamNameSpace(DeclFucker *what_is_this, TypeClass *tclass) {
cscope_current = tclass->nspace;
}
Boolean CTempl_IsQualifiedMember(DeclInfo *di, Type *type, NameSpace **resultnspace) {
if (
TYPE_TEMPLATE(type)->dtype == TEMPLDEP_QUALNAME &&
(type = CTemplTool_GetSelfRefTemplate(TYPE(TYPE_TEMPLATE(type)->u.qual.type)))
)
{
*resultnspace = TYPE_CLASS(type)->nspace;
CError_ASSERT(948, di->fucker34 && (*resultnspace)->theclass);
CTempl_SetupClassParamNameSpace(di->fucker34, (*resultnspace)->theclass);
di->fucker34 = NULL;
return 1;
}
return 0;
}
static void *CTempl_ParseMemberFunction(int unk1, int unk2, int unk3, Object *func) {
// no idea what should've been here, it's not called
CError_ASSERT(974, TYPE_FUNC(func->type)->flags & FUNC_FLAGS_METHOD);
return NULL;
}
static void CTempl_ParseMember(TemplParam *params, TemplClass *templ, DeclInfo *di, SInt32 *startOffset) {
Object *object;
NameSpaceObjectList *nsol;
TStream stream;
CPrepFileInfo *file;
SInt32 offset;
Boolean saveForceLoc;
TemplateMember *member;
if (templ->theclass.flags & CLASS_FLAGS_100)
di->thetype = CTemplTool_ResolveMemberSelfRefs(templ, di->thetype, &di->qual);
if (IS_TYPE_FUNC(di->thetype)) {
Boolean flag;
if (!(object = CDecl_GetFunctionObject(di, NULL, &flag, 0))) {
CError_Error(CErrorStr140, di->name->name);
return;
}
if (tk != '{' && tk != TK_TRY && tk != ':') {
if (tk != ';')
CError_Error(CErrorStr123);
else
tk = lex();
return;
}
if (
(TYPE_FUNC(object->type)->flags & FUNC_FLAGS_2) &&
(!(TYPE_FUNC(object->type)->flags & FUNC_FLAGS_100000) || object->u.func.u.templ->instances)
)
CError_Error(CErrorStr333, object);
TYPE_FUNC(object->type)->flags |= FUNC_FLAGS_800000 | FUNC_FLAGS_2;
CPrep_StreamGetBlock(&stream, NULL, 1);
saveForceLoc = gForceSourceLoc;
gForceSourceLoc = 1;
CPrep_BrowserFilePosition(&file, &offset);
gForceSourceLoc = saveForceLoc;
if (file && file->recordbrowseinfo && *startOffset >= 0 && offset > *startOffset)
CBrowse_NewFunction(object, file, file, *startOffset, offset + 1);
} else {
if (!(nsol = CScope_GetLocalObject(templ->theclass.nspace, di->name))) {
CError_Error(CErrorStr140, di->name->name);
return;
}
object = OBJECT(nsol->object);
if (object->otype != OT_OBJECT) {
CError_Error(CErrorStr122, di->name->name);
return;
}
if (
!is_typesame(di->thetype, object->type) ||
(object->qual & (Q_CONST | Q_VOLATILE | Q_PASCAL)) != (di->qual & (Q_CONST | Q_VOLATILE | Q_PASCAL))
)
{
CError_Error(CErrorStr249, CError_GetObjectName(object), object->type, object->qual, di->thetype, di->qual);
return;
}
CError_ASSERT(1070, object->datatype == DDATA);
CPrep_StreamGetSemicolon(&stream, NULL);
}
if (stream.tokens) {
if (IS_TEMPL_FUNC(object->type) != 0) {
if (!CTemplTool_EqualParams(object->u.func.u.templ->params, params, 0))
CError_Error(CErrorStr235);
object->u.func.u.templ->stream = stream;
} else {
if (!(templ->theclass.flags & CLASS_FLAGS_100)) {
CError_Error(CErrorStr190);
return;
}
member = CTemplClass_DefineMember(templ, object, &cparser_fileoffset, &stream);
if (templ->templ__params) {
if (!CTemplTool_EqualParams(templ->templ__params, params, 0)) {
CError_Error(CErrorStr235);
return;
}
member->params = params;
}
}
}
}
static TemplateFunction *CTempl_DeclareTemplateFunction(DeclInfo *di, TemplParam *params, TypeClass *tclass, AccessType access, Boolean flag) {
TemplateFunction *templ;
Object *object;
if (tclass) {
CError_ASSERT(1122, cscope_current->theclass);
di->thetype = TYPE(CDecl_MakeTypeMemberFunc(TYPE_FUNC(di->thetype), cscope_current->theclass, flag));
} else {
access = ACCESSPUBLIC;
}
templ = galloc(sizeof(TemplateFunction));
memclrw(templ, sizeof(TemplateFunction));
templ->next = ctempl_templatefuncs;
ctempl_templatefuncs = templ;
templ->params = params;
templ->name = di->name;
templ->deftoken = symdecltoken;
object = CParser_NewFunctionObject(NULL);
object->access = access;
object->name = di->name;
object->u.func.linkname = CParser_GetUniqueName();
object->type = di->thetype;
object->qual = di->qual | Q_80000;
object->sclass = di->storageclass;
TYPE_FUNC(object->type)->flags |= FUNC_FLAGS_100000;
object->u.func.u.templ = templ;
if (di->qual & Q_INLINE)
object->sclass = TK_STATIC;
templ->tfunc = object;
CScope_AddObject(cscope_current, di->name, OBJ_BASE(object));
return templ;
}
static void CTempl_ParseTemplateFunction(TemplateFunction *templ, TypeClass *tclass, SInt32 *startOffset) {
Object *object;
CPrepFileInfo *file;
SInt32 offset;
Boolean saveForceLoc;
object = templ->tfunc;
if (tk == '{' || tk == ':' || tk == TK_TRY) {
if (tclass) {
object->qual |= Q_INLINE;
object->sclass = TK_STATIC;
}
if (TYPE_FUNC(object->type)->flags & FUNC_FLAGS_2)
CError_Error(CErrorStr333, object);
TYPE_FUNC(object->type)->flags |= FUNC_FLAGS_2 | FUNC_FLAGS_800000;
CPrep_StreamGetBlock(&templ->stream, NULL, 0);
if (lookahead() == ';')
tk = lex();
else
tk = ';';
saveForceLoc = gForceSourceLoc;
gForceSourceLoc = 1;
CPrep_BrowserFilePosition(&file, &offset);
gForceSourceLoc = saveForceLoc;
if (file && *startOffset >= 0 && offset > *startOffset) {
templ->srcfile = file;
templ->startoffset = *startOffset;
templ->endoffset = offset + 1;
if (cparamblkptr->browseOptions.recordTemplates && file->recordbrowseinfo)
CBrowse_NewTemplateFunc(templ);
}
} else {
if (tk != ';')
CError_Error(CErrorStr121);
}
}
static HashNameNode *CTempl_FindConversionFuncName(TypeClass *tclass, Type *type, UInt32 qual) {
Object *object;
CScopeObjectIterator iter;
CScope_InitObjectIterator(&iter, tclass->nspace);
do {
if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter))))
return NULL;
} while (
!IS_TYPE_FUNC(object->type) ||
!(TYPE_FUNC(object->type)->flags & FUNC_FLAGS_40) ||
(TYPE_FUNC(object->type)->qual & (Q_CONST | Q_VOLATILE)) != (qual & (Q_CONST | Q_VOLATILE)) ||
!is_typesame(TYPE_FUNC(object->type)->functype, type)
);
return object->name;
}
static void CTempl_ParseConversionFunctionTemplate(DeclInfo *di, DeclFucker *what_is_this, TemplParam *params, TypeClass *tclass, SInt32 *startOffset, AccessType access) {
tk = lex();
if (!tclass) {
CError_Error(CErrorStr121);
return;
}
tclass->flags |= CLASS_FLAGS_40;
CError_QualifierCheck(di->qual & ~Q_INLINE);
conversion_type_name(di);
CDecl_NewConvFuncType(di);
if (cscope_current->is_templ) {
CError_ASSERT(1260, cscope_current == what_is_this->nspace);
cscope_current = what_is_this->nspace->parent;
}
CTempl_ParseTemplateFunction(CTempl_DeclareTemplateFunction(di, params, tclass, access, 0), tclass, startOffset);
}
static void CTempl_ParseFunctionOrMemberTemplate(DeclFucker *what_is_this, TemplParam *params, TypeClass *tclass, SInt32 *startOffset, AccessType access, Boolean mysteryFlag) {
NameSpaceObjectList *nsol;
Object *object;
TemplParam *param;
TemplateFunction *templfunc;
Boolean disallowCVFlag;
TypeClass *tclass2;
Type *type;
UInt32 qual;
DeclInfo di;
for (param = params; param; param = param->next) {
switch (param->pid.type) {
case TPT_TYPE:
if (param->data.typeparam.type) {
CError_Error(CErrorStr378);
param->data.typeparam.type = NULL;
}
break;
case TPT_NONTYPE:
if (param->data.paramdecl.defaultarg) {
CError_Error(CErrorStr378);
param->data.paramdecl.defaultarg = NULL;
}
break;
case TPT_TEMPLATE:
if (param->data.templparam.defaultarg) {
CError_Error(CErrorStr378);
param->data.templparam.defaultarg = NULL;
}
break;
default:
CError_FATAL(1317);
}
}
disallowCVFlag = 0;
ctempl_scanfuncparams = 1;
memclrw(&di, sizeof(di));
di.x51 = mysteryFlag;
if (tk == TK_OPERATOR) {
CTempl_ParseConversionFunctionTemplate(&di, what_is_this, params, tclass, startOffset, access);
return;
}
CParser_GetDeclSpecs(&di, 1);
if (tk == ';' && IS_TEMPL_CLASS(di.thetype))
return;
if (di.x10 || di.x14) {
TypeFunc *tfunc;
if (di.x14) {
di.x10 = OBJECT(di.x14->object);
CError_ASSERT(1342, di.x10->otype == OT_OBJECT);
}
CError_ASSERT(1344, IS_TYPE_FUNC(di.x10->type));
tfunc = TYPE_FUNC(di.x10->type);
if (tfunc->flags & FUNC_FLAGS_40) {
di.thetype = tfunc->functype;
di.qual |= tfunc->qual;
di.nspace = di.x10->nspace;
di.name = di.x10->name;
} else if (tfunc->flags & FUNC_FLAGS_1000) {
di.thetype = TYPE(&void_ptr);
di.nspace = di.x10->nspace;
di.name = di.x10->name;
} else {
CError_Error(CErrorStr121);
return;
}
if ((tk = lex()) == '(') {
tk = lex();
CDecl_ParseDirectFuncDecl(&di);
if (IS_TYPE_FUNC(di.thetype))
goto skipPastStuff;
} else {
CError_Error(CErrorStr114);
}
}
if (di.storageclass) {
if (tclass) {
if (di.storageclass == TK_STATIC)
disallowCVFlag = 1;
else
CError_Error(CErrorStr177);
di.storageclass = 0;
} else {
if (di.storageclass != TK_STATIC && di.storageclass != TK_EXTERN) {
CError_Error(CErrorStr177);
di.storageclass = 0;
}
}
}
CError_QualifierCheck(di.qual & ~(Q_CONST | Q_VOLATILE | Q_ASM | Q_PASCAL | Q_INLINE | Q_EXPLICIT | Q_20000 | Q_OVERLOAD | Q_ALIGNED_MASK));
if (tk == TK_OPERATOR && di.x4A) {
CTempl_ParseConversionFunctionTemplate(&di, what_is_this, params, tclass, startOffset, access);
return;
}
if (!di.x53) {
if (tclass && IS_TYPE_CLASS(di.thetype) && TYPE_CLASS(di.thetype) == tclass && tk == '(') {
CError_ASSERT(1418, cscope_current == tclass->nspace);
CError_QualifierCheck(di.qual & ~(Q_INLINE | Q_EXPLICIT));
di.thetype = TYPE(&void_ptr);
di.x4B = 1;
tk = lex();
CDecl_ParseDirectFuncDecl(&di);
if (IS_TYPE_FUNC(di.thetype)) {
if (TYPE_FUNC(di.thetype)->args && !TYPE_FUNC(di.thetype)->args->next && TYPE_FUNC(di.thetype)->args->type == TYPE(tclass)) {
CError_Error(CErrorStr239);
TYPE_FUNC(di.thetype)->args = NULL;
}
if (tclass->flags & CLASS_FLAGS_20)
CDecl_AddArgument(TYPE_FUNC(di.thetype), TYPE(&stsignedshort));
TYPE_FUNC(di.thetype)->flags |= FUNC_FLAGS_1000;
di.name = constructor_name_node;
what_is_this->nspace->tparams = NULL;
CTempl_ParseTemplateFunction(
CTempl_DeclareTemplateFunction(&di, params, tclass, access, disallowCVFlag),
tclass, startOffset);
return;
} else {
CError_Error(CErrorStr241);
}
}
if (IS_TYPE_TEMPLATE(di.thetype)) {
if (
tk == '(' &&
TYPE_TEMPLATE(di.thetype)->dtype == TEMPLDEP_QUALNAME &&
(tclass2 = TYPE_CLASS(CTemplTool_GetSelfRefTemplate(TYPE(TYPE_TEMPLATE(di.thetype)->u.qual.type)))) &&
TYPE_TEMPLATE(di.thetype)->u.qual.name == tclass2->classname
)
{
if (tclass)
CError_Error(CErrorStr229);
di.thetype = TYPE(&void_ptr);
di.x4B = 1;
CTempl_SetupClassParamNameSpace(what_is_this, tclass2);
tk = lex();
CDecl_ParseDirectFuncDecl(&di);
if (IS_TYPE_FUNC(di.thetype)) {
di.name = constructor_name_node;
if (tclass2->flags & CLASS_FLAGS_20)
CDecl_AddArgument(TYPE_FUNC(di.thetype), TYPE(&stsignedshort));
TYPE_FUNC(di.thetype)->flags |= FUNC_FLAGS_1000;
CTempl_ParseMember(params, TEMPL_CLASS(tclass2), &di, startOffset);
} else {
CError_Error(CErrorStr241);
}
return;
}
if (
tk == TK_COLON_COLON &&
TYPE_TEMPLATE(di.thetype)->dtype == TEMPLDEP_TEMPLATE &&
(tclass2 = TYPE_CLASS(CTemplTool_GetSelfRefTemplate(di.thetype)))
)
{
if (tclass)
CError_Error(CErrorStr229);
if ((tk = lex()) == '~') {
if (
(tk = lex()) != TK_IDENTIFIER ||
tkidentifier != tclass2->classname ||
(tk = lex()) != '('
)
{
if (tk == '<') {
DeclInfo di2;
CPrep_UnLex();
tk = TK_IDENTIFIER;
tkidentifier = tclass2->classname;
memclrw(&di2, sizeof(di2));
CParser_GetDeclSpecs(&di2, 0);
if (tk != '(')
CError_Error(CErrorStr241);
if (di2.thetype != TYPE(tclass2) && (!IS_TYPE_TEMPLATE(di2.thetype) || CTemplTool_IsTemplate(
TYPE_TEMPLATE(di2.thetype)) != TEMPL_CLASS(tclass2)))
{
CError_Error(CErrorStr241);
}
} else {
CError_Error(CErrorStr241);
}
}
di.thetype = TYPE(&void_ptr);
CTempl_SetupClassParamNameSpace(what_is_this, tclass2);
tk = lex();
CDecl_ParseDirectFuncDecl(&di);
if (IS_TYPE_FUNC(di.thetype)) {
if (tclass2->sominfo)
di.qual |= Q_VIRTUAL;
else
CDecl_AddArgument(TYPE_FUNC(di.thetype), TYPE(&stsignedshort));
di.name = destructor_name_node;
TYPE_FUNC(di.thetype)->flags |= FUNC_FLAGS_2000;
CTempl_ParseMember(params, TEMPL_CLASS(tclass2), &di, startOffset);
} else {
CError_Error(CErrorStr241);
}
} else if (tk == TK_OPERATOR) {
CTempl_SetupClassParamNameSpace(what_is_this, tclass2);
if (CMangler_OperatorName((tk = lex()))) {
CError_Error(CErrorStr349);
return;
}
CError_QualifierCheck(di.qual & ~(Q_INLINE | Q_VIRTUAL));
conversion_type_name(&di);
type = di.thetype;
qual = di.qual;
CDecl_NewConvFuncType(&di);
if (CTemplTool_IsTemplateArgumentDependentType(type)) {
di.name = CTempl_FindConversionFuncName(tclass2, type, qual);
if (!di.name) {
CError_Error(CErrorStr150, "conversion function");
return;
}
}
CTempl_ParseMember(params, TEMPL_CLASS(tclass2), &di, startOffset);
} else {
CError_Error(CErrorStr121);
}
return;
}
if (TYPE_TEMPLATE(di.thetype)->dtype == TEMPLDEP_QUALNAME && !di.x49)
CError_Warning(CErrorStr355);
}
}
di.x30 = params;
di.fucker34 = what_is_this;
scandeclarator(&di);
ctempl_scanfuncparams = 0;
skipPastStuff:
if (cscope_current->is_templ) {
CError_ASSERT(1589, cscope_current == what_is_this->nspace);
what_is_this->nspace->tparams = NULL;
}
if (!di.name) {
CError_Error(CErrorStr229);
return;
}
if (di.nspace) {
if (di.nspace->theclass) {
if (tclass)
CError_Error(CErrorStr229);
CTempl_ParseMember(params, TEMPL_CLASS(di.nspace->theclass), &di, startOffset);
return;
}
if (!IS_TYPE_FUNC(di.thetype)) {
CError_Error(CErrorStr229);
return;
}
CScope_FindName(di.nspace, di.name);
} else {
if (!IS_TYPE_FUNC(di.thetype)) {
CError_Error(CErrorStr229);
return;
}
CScope_FindName(cscope_current, di.name);
}
nsol = CScope_FindName(di.nspace ? di.nspace : cscope_current, di.name);
while (nsol) {
object = OBJECT(nsol->object);
if (object->otype == OT_OBJECT && IS_TEMPL_FUNC(object->type)) {
templfunc = CTemplTool_GetFuncTempl(object);
if (CTemplTool_EqualParams(templfunc->params, params, 0) && is_typesame(object->type, di.thetype)) {
if (tk != ';' && templfunc->stream.tokens)
CError_Error(CErrorStr234);
if (tk == '{' || tk == ':' || tk == TK_TRY)
CError_ASSERT(1654, CTemplTool_EqualParams(templfunc->params, params, 1));
if (di.qual & Q_INLINE)
object->qual |= Q_INLINE;
TYPE_FUNC(object->type)->args = TYPE_FUNC(di.thetype)->args;
break;
}
}
nsol = nsol->next;
}
if (!nsol) {
if (di.nspace)
CError_Error(CErrorStr229);
templfunc = CTempl_DeclareTemplateFunction(&di, params, tclass, access, disallowCVFlag);
}
CTempl_ParseTemplateFunction(templfunc, tclass, startOffset);
}
static void CTempl_ExplicitInstantiation(void) {
Boolean flag;
short saveToken;
Object *object;
DeclInfo di;
memclrw(&di, sizeof(di));
di.x51 = 1;
flag = 1;
if (tk == TK_IDENTIFIER && !strcmp(tkidentifier->name, "__dont_instantiate")) {
flag = 0;
tk = lex();
}
switch (tk) {
case TK_STRUCT:
case TK_UNION:
case TK_CLASS:
memclrw(&di, sizeof(di));
CParser_GetDeclSpecs(&di, 0);
if (tk == ';') {
if (IS_TEMPL_CLASS_INST(di.thetype)) {
CTempl_InstantiateTemplateClass(TYPE_CLASS(di.thetype));
if ((TYPE_CLASS(di.thetype)->flags & CLASS_FLAGS_2) && !(TYPE_CLASS(di.thetype)->eflags & CLASS_EFLAGS_IMPORT)) {
if (flag)
CTempl_GenClassInstance(TEMPL_CLASS_INST(di.thetype), 1);
else
TEMPL_CLASS_INST(di.thetype)->is_extern = 1;
} else {
CError_Error(CErrorStr136, TYPE_CLASS(di.thetype), 0);
}
} else {
CError_Error(CErrorStr238);
}
return;
}
break;
default:
memclrw(&di, sizeof(di));
CParser_GetDeclSpecs(&di, 0);
}
di.x51 = 1;
scandeclarator(&di);
saveToken = tk;
di.x38 = NULL;
if (
di.name &&
IS_TYPE_FUNC(di.thetype) &&
(object = CDecl_GetFunctionObject(&di, di.nspace, NULL, 1)) &&
IS_TYPE_FUNC(object->type) &&
object->u.func.inst &&
di.x38
)
{
if (!flag)
object->u.func.inst->is_extern = 1;
else
CTempl_GenFuncInstance(di.x38, object->u.func.inst, 1);
} else {
CError_Error(CErrorStr238);
}
if (saveToken != ';')
CError_Error(CErrorStr123);
}
static void CTempl_ExplicitSpecialization(void) {
Boolean flag;
TemplParam *params;
int counter;
DeclFucker what_is_this;
DeclInfo di;
flag = 0;
counter = 1;
while (tk == TK_TEMPLATE) {
if ((tk = lex()) != '<') {
CError_Error(CErrorStr230);
break;
}
if ((tk = lex()) != '>') {
if (!flag) {
what_is_this.nspace = cscope_current;
what_is_this.mystery4 = NULL;
cscope_current->tparams = NULL;
flag = 1;
}
params = CTempl_ParseParamList(what_is_this.nspace, counter);
if (tk != '>')
CError_Error(CErrorStr231);
} else {
if (flag)
CError_Error(CErrorStr335);
}
counter++;
tk = lex();
}
if (flag) {
SInt32 startOffset = -1;
CTempl_ParseFunctionOrMemberTemplate(&what_is_this, params, NULL, &startOffset, ACCESSPUBLIC, 1);
return;
}
memclrw(&di, sizeof(di));
di.x3C = counter;
di.x51 = 1;
CParser_GetDeclSpecs(&di, 1);
if (tk == ';') {
if (IS_TEMPL_CLASS_INST(di.thetype))
TEMPL_CLASS_INST(di.thetype)->is_specialized = 1;
else
CError_Error(CErrorStr335);
} else {
scandeclaratorlist(&di);
if ((tk != ';' && tk != '}') || di.x3C)
CError_Error(CErrorStr335);
}
if (flag)
what_is_this.nspace->tparams = NULL;
}
void CTempl_Parse(TemplClass *templ, AccessType access) {
TemplParam *params;
UInt8 i;
short mode;
Boolean flag;
UInt8 classDeclSpec;
SInt32 startOffset;
SInt32 savedState;
CScopeSave savedScope;
DeclFucker what_is_this;
startOffset = CPrep_BrowserFileOffset();
CScope_GetScope(&savedScope);
if ((tk = lex()) != '<') {
if (templ)
CError_Error(CErrorStr238);
CTempl_ExplicitInstantiation();
CScope_RestoreScope(&savedScope);
return;
}
if ((tk = lex()) == '>') {
if (templ)
CError_Error(CErrorStr335);
tk = lex();
CTempl_ExplicitSpecialization();
CScope_RestoreScope(&savedScope);
return;
}
what_is_this.nspace = cscope_current;
what_is_this.mystery4 = NULL;
cscope_current->tparams = NULL;
i = CTempl_GetTemplateNestIndex(what_is_this.nspace);
while (1) {
params = CTempl_ParseParamList(what_is_this.nspace, i);
if (tk != '>')
CError_Error(CErrorStr231);
if ((tk = lex()) != TK_TEMPLATE)
break;
if (templ)
CError_Error(CErrorStr121);
if ((tk = lex()) != '<')
CError_Error(CErrorStr230);
else
tk = lex();
i++;
}
switch (tk) {
case TK_CLASS:
mode = CLASS_MODE_2;
break;
case TK_UNION:
mode = CLASS_MODE_1;
break;
case TK_STRUCT:
mode = CLASS_MODE_0;
break;
default:
mode = -1;
}
if (mode >= 0) {
classDeclSpec = 0;
flag = 0;
CPrep_TokenStreamGetState(&savedState);
if ((tk = lex()) == TK_UU_DECLSPEC)
CDecl_ParseClassDeclSpec(&classDeclSpec);
if (tk == TK_IDENTIFIER) {
if ((tk = lex()) == '<') {
if (setjmp(ctempl_parseparse) == 0) {
CTempl_MemberParseTemplArgList();
flag = 1;
tk = lex();
}
}
switch (tk) {
case ':':
case ';':
case '{':
CPrep_TokenStreamSetCurState(&savedState);
if (flag)
CTemplClass_ParsePartialSpecialization(&what_is_this, params, mode, &startOffset);
else
CTemplClass_ParseClass(&what_is_this, params, mode, &startOffset);
goto done;
}
}
CPrep_TokenStreamSetCurState(&savedState);
}
CTempl_ParseFunctionOrMemberTemplate(&what_is_this, params, TYPE_CLASS(templ), &startOffset, access, 0);
done:
what_is_this.nspace->tparams = NULL;
CScope_RestoreScope(&savedScope);
}
void CTempl_ParseInstanceScopeFunction(Object *funcobj, TemplClassInst *inst, TypeClass *tclass) {
TemplParam *params;
NameSpace *nspace;
TemplateMember *member;
Object *parent;
DeclInfo di;
CScopeSave savedScope;
TemplStack stack;
params = inst->templ->templ__params;
if (funcobj->qual & Q_400000) {
for (member = CTemplClass_GetMasterTemplate(inst->templ)->members, parent = OBJECT_TEMPL(funcobj)->parent; member; member = member->next) {
if (member->object == parent) {
if (member->params)
params = member->params;
break;
}
}
}
CTemplTool_PushInstance(&stack, NULL, funcobj);
nspace = CTemplTool_InsertTemplateArgumentNameSpace(params, inst, &savedScope);
if (tclass)
cscope_current = tclass->nspace;
memclrw(&di, sizeof(di));
CFunc_ParseFuncDef(funcobj, &di, NULL, 0, 0, tclass ? cscope_current : NULL);
CTemplTool_RemoveTemplateArgumentNameSpace(nspace, inst, &savedScope);
CTemplTool_PopInstance(&stack);
}
Boolean CTempl_GenFuncInstance(TemplateFunction *templ, TemplFuncInstance *inst, Boolean flag) {
Boolean saveDebugInfo;
NameSpace *nspace;
SInt32 streamState;
TemplStack stack;
DeclInfo di;
if (!flag && copts.no_implicit_templates && inst->object->sclass != TK_STATIC)
return 0;
if (inst->is_extern && !flag)
return 0;
while (1) {
if (templ->stream.tokens)
break;
if (!templ->unk4)
break;
templ = templ->unk4;
}
if (!templ->stream.tokens) {
if (flag) {
CError_SetErrorToken(&templ->deftoken);
CError_Error(CErrorStr233, inst->object);
}
return 0;
}
inst->is_instantiated = 1;
CPrep_StreamInsert(&templ->stream, &streamState);
saveDebugInfo = copts.isGeneratingDebugInfo;
if (copts.nosyminline || !templ->deftoken.tokenfile)
copts.isGeneratingDebugInfo = 0;
CError_ASSERT(2112, (tk = lex()) == '{' || tk == ':' || tk == TK_TRY);
symdecltoken = *CPrep_CurStreamElement();
if (copts.isGeneratingDebugInfo) {
CPrep_NewFileOffsetInfo(&cparser_fileoffset, &templ->deftoken);
symdecloffset = cparser_fileoffset.tokenline;
}
if (inst->object->sclass != TK_STATIC)
inst->object->qual |= Q_OVERLOAD;
memclrw(&di, sizeof(di));
di.file2 = templ->srcfile;
di.file = CPrep_BrowserCurrentFile();
di.x60 = templ->startoffset;
CTemplTool_PushInstance(&stack, NULL, inst->object);
CTemplTool_MergeArgNames(TYPE_FUNC(templ->tfunc->type), TYPE_FUNC(inst->object->type));
nspace = CTemplTool_SetupTemplateArgumentNameSpace(templ->params, inst->args, 0);
nspace->parent = inst->object->nspace;
inst->object->nspace = nspace;
CTemplTool_SetupOuterTemplateArgumentNameSpace(nspace);
CFunc_ParseFuncDef(inst->object, &di, NULL, 0, 0, nspace);
CTemplTool_RemoveOuterTemplateArgumentNameSpace(nspace);
inst->object->nspace = nspace->parent;
CTemplTool_PopInstance(&stack);
CPrep_StreamRemove(&templ->stream, &streamState);
copts.isGeneratingDebugInfo = saveDebugInfo;
if (di.file->recordbrowseinfo)
CBrowse_NewFunction(inst->object, di.file, di.file2, di.x60, templ->endoffset);
return 1;
}
void CTempl_InstantiateMember(TemplClass *templ, TemplClassInst *inst, TemplateMember *tmemb, Object *object, Boolean flag) {
Boolean saveDebugInfo;
NameSpace *nspace;
Boolean saveSourceLoc;
DeclInfo di;
CScopeSave savedScope;
TemplStack stack;
SInt32 savedState;
if (!flag && copts.no_implicit_templates)
return;
CTemplTool_PushInstance(&stack, NULL, object);
nspace = CTemplTool_InsertTemplateArgumentNameSpace(
tmemb->params ? tmemb->params : templ->templ__params, inst, &savedScope);
CPrep_StreamInsert(&tmemb->stream, &savedState);
saveSourceLoc = gForceSourceLoc;
gForceSourceLoc = 1;
symdecltoken.tokenoffset = tmemb->startoffset;
tk = lex();
symdecltoken = *CPrep_CurStreamElement();
saveDebugInfo = copts.isGeneratingDebugInfo;
if (copts.isGeneratingDebugInfo) {
CPrep_NewFileOffsetInfo(&cparser_fileoffset, &symdecltoken);
symdecloffset = cparser_fileoffset.tokenline;
}
if (object->sclass != TK_STATIC)
object->qual |= Q_OVERLOAD;
memclrw(&di, sizeof(di));
di.file2 = tmemb->srcfile;
di.file = CPrep_BrowserCurrentFile();
di.x60 = tmemb->startoffset;
switch (object->datatype) {
case DFUNC:
case DVFUNC:
CTemplTool_MergeArgNames(TYPE_FUNC(tmemb->object->type), TYPE_FUNC(object->type));
CFunc_ParseFuncDef(object, &di, TYPE_CLASS(inst), 0, 0, NULL);
break;
case DDATA:
CDecl_CompleteType(object->type);
CInit_InitializeData(object);
break;
default:
CError_FATAL(2227);
}
CTemplTool_PopInstance(&stack);
CTemplTool_RemoveTemplateArgumentNameSpace(nspace, inst, &savedScope);
CPrep_StreamRemove(&tmemb->stream, &savedState);
copts.isGeneratingDebugInfo = saveDebugInfo;
gForceSourceLoc = saveSourceLoc;
}
static Boolean CTempl_GenMemberInstance(TemplClassInst *inst, ObjectTemplated *objtempl, Boolean flag) {
TemplateMember *member;
Object *parent = objtempl->parent;
for (member = CTemplClass_GetMasterTemplate(inst->templ)->members; member; member = member->next) {
if (member->object == parent) {
CTempl_InstantiateMember(inst->templ, inst, member, OBJECT(objtempl), flag);
return 1;
}
}
if (flag)
CError_Warning(CErrorStr233, objtempl);
return 0;
}
static Boolean CTempl_GenClassInstance(TemplClassInst *inst, Boolean flag) {
Object *object;
Boolean result;
CScopeObjectIterator iter;
result = 0;
if (!flag && copts.no_implicit_templates)
return 0;
if (!flag && inst->is_extern)
return 0;
CScope_InitObjectIterator(&iter, inst->theclass.nspace);
while ((object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) {
if (IS_TYPE_FUNC(object->type) && object->datatype != DALIAS) {
if (
(flag || (object->flags & OBJECT_FLAGS_2)) &&
!(TYPE_FUNC(object->type)->flags & (FUNC_FLAGS_2 | FUNC_FLAGS_100)) &&
CTempl_GenMemberInstance(inst, OBJECT_TEMPL(object), flag) &&
(TYPE_FUNC(object->type)->flags & FUNC_FLAGS_2)
)
result = 1;
} else {
if (
!inst->x49 &&
object->datatype == DDATA &&
!(object->qual & Q_10000) &&
!(object->flags & OBJECT_FLAGS_4) &&
CTempl_GenMemberInstance(inst, OBJECT_TEMPL(object), flag)
)
result = 1;
}
}
inst->x49 = 1;
return result;
}
Boolean CTempl_Instantiate(void) {
Boolean result = 0;
TemplClass *templ;
TemplClassInst *inst;
TemplPartialSpec *pspec;
TemplFuncInstance *instf;
TemplateFunction *templf;
for (templ = ctempl_templates; templ; templ = templ->next) {
for (inst = templ->instances; inst; inst = inst->next) {
if (
(inst->theclass.flags & CLASS_FLAGS_800) &&
!inst->is_specialized &&
CTempl_GenClassInstance(inst, 0)
)
result = 1;
}
for (pspec = templ->pspecs; pspec; pspec = pspec->next) {
for (inst = pspec->templ->instances; inst; inst = inst->next) {
if (
(inst->theclass.flags & CLASS_FLAGS_800) &&
!inst->is_specialized &&
CTempl_GenClassInstance(inst, 0)
)
result = 1;
}
}
}
for (templf = ctempl_templatefuncs; templf; templf = templf->next) {
for (instf = templf->instances; instf; instf = instf->next) {
if (
!instf->is_instantiated &&
!instf->is_specialized &&
(instf->object->flags & OBJECT_FLAGS_2) &&
!(TYPE_FUNC(instf->object->type)->flags & FUNC_FLAGS_2)
)
{
instf->is_instantiated = 1;
if (CTempl_GenFuncInstance(templf, instf, 0))
result = 1;
}
}
}
return result;
}
Boolean CTempl_InlineFunctionCheck(Object *funcobj) {
TemplClassInst *inst;
TemplateMember *member;
Object *parent;
CError_ASSERT(2422, IS_TYPE_FUNC(funcobj->type) && (funcobj->qual & Q_400000));
if (!(TYPE_FUNC(funcobj->type)->flags & FUNC_FLAGS_2)) {
inst = TEMPL_CLASS_INST(TYPE_METHOD(funcobj->type)->theclass);
if (!inst->is_specialized) {
parent = OBJECT_TEMPL(funcobj)->parent;
if (parent->qual & Q_INLINE) {
for (member = CTemplClass_GetMasterTemplate(inst->templ)->members; member; member = member->next) {
funcobj->qual |= Q_INLINE;
if (member->object == parent) {
CTemplTool_MergeArgNames(TYPE_FUNC(member->object->type), TYPE_FUNC(funcobj->type));
CInline_AddInlineFunctionAction(funcobj, TYPE_CLASS(inst), &member->fileoffset, &member->stream, 0);
return 1;
}
}
}
}
}
return 0;
}