MWCC/compiler_and_linker/FrontEnd/C/CScope.c

2700 lines
88 KiB
C

#include "compiler/CScope.h"
#include "compiler/CClass.h"
#include "compiler/CDecl.h"
#include "compiler/CError.h"
#include "compiler/CMangler.h"
#include "compiler/CParser.h"
#include "compiler/CPrep.h"
#include "compiler/CPrepTokenizer.h"
#include "compiler/CTemplateClass.h"
#include "compiler/CTemplateNew.h"
#include "compiler/CTemplateTools.h"
#include "compiler/CompilerTools.h"
#include "compiler/enode.h"
#include "compiler/objects.h"
#include "compiler/scopes.h"
#include "compiler/templates.h"
#include "compiler/types.h"
typedef enum ELookupType {
Lookup_0,
Lookup_1,
Lookup_2
} ELookupType;
static Boolean cscope_isambig;
static ELookupType cscope_lookuptype;
static SInt32 cscope_foundclassoffset;
static TemplClass *cscope_foundtemplate;
static TypeClass *cscope_foundclass;
static HashNameNode *cscope_name;
static TypeClass *cscope_mostderived;
Boolean cscope_is_member_func;
Object *cscope_currentfunc;
TypeClass *cscope_currentclass;
NameSpace *cscope_current;
NameSpace *cscope_root;
void CScope_Setup(void) {
cscope_current = cscope_root = CScope_NewHashNameSpace(0);
cscope_currentclass = NULL;
cscope_currentfunc = NULL;
cscope_is_member_func = 0;
}
void CScope_Cleanup(void) {
}
void CScope_GetScope(CScopeSave *save) {
save->current = cscope_current;
save->currentclass = cscope_currentclass;
save->currentfunc = cscope_currentfunc;
save->is_member_func = cscope_is_member_func;
}
void CScope_SetNameSpaceScope(NameSpace *nspace, CScopeSave *save) {
save->current = cscope_current;
save->currentclass = cscope_currentclass;
save->currentfunc = cscope_currentfunc;
save->is_member_func = cscope_is_member_func;
cscope_current = nspace;
cscope_currentclass = nspace->theclass;
cscope_currentfunc = NULL;
cscope_is_member_func = 0;
}
void CScope_SetClassScope(TypeClass *cls, CScopeSave *save) {
save->current = cscope_current;
save->currentclass = cscope_currentclass;
save->currentfunc = cscope_currentfunc;
save->is_member_func = cscope_is_member_func;
cscope_current = cls->nspace;
cscope_currentclass = cls;
cscope_currentfunc = NULL;
cscope_is_member_func = 0;
}
void CScope_SetClassDefScope(TypeClass *cls, CScopeSave *save) {
save->current = cscope_current;
save->currentclass = cscope_currentclass;
save->currentfunc = cscope_currentfunc;
save->is_member_func = cscope_is_member_func;
cscope_current = cls->nspace;
cscope_currentclass = cls;
}
void CScope_SetFunctionScope(Object *function, CScopeSave *save) {
save->current = cscope_current;
save->currentclass = cscope_currentclass;
save->currentfunc = cscope_currentfunc;
save->is_member_func = cscope_is_member_func;
cscope_currentfunc = function;
cscope_currentclass = NULL;
cscope_is_member_func = 0;
if (TYPE_FUNC(function->type)->flags & FUNC_FLAGS_METHOD) {
cscope_currentclass = TYPE_METHOD(function->type)->theclass;
cscope_current = cscope_currentclass->nspace;
cscope_is_member_func = TYPE_METHOD(function->type)->x26 == 0;
} else {
cscope_current = function->nspace;
}
}
void CScope_SetMethodScope(Object *function, TypeClass *cls, Boolean is_static, CScopeSave *save) {
save->current = cscope_current;
save->currentclass = cscope_currentclass;
save->currentfunc = cscope_currentfunc;
save->is_member_func = cscope_is_member_func;
cscope_currentfunc = function;
cscope_currentclass = cls;
cscope_current = cls->nspace;
cscope_is_member_func = !is_static;
}
void CScope_RestoreScope(CScopeSave *saved) {
cscope_current = saved->current;
cscope_currentclass = saved->currentclass;
cscope_currentfunc = saved->currentfunc;
cscope_is_member_func = saved->is_member_func;
}
static Boolean CScope_ObjectIsFunction(Object *obj) {
return obj->otype == OT_OBJECT && IS_TYPE_FUNC(obj->type);
}
Boolean CScope_IsEmptySymTable(void) {
NameSpaceObjectList *scan;
NameSpaceName *nsname;
int i;
CError_ASSERT(232, cscope_root->is_hash);
i = 0;
do {
for (nsname = cscope_root->data.hash[i]; nsname; nsname = nsname->next) {
for (scan = &nsname->first; scan; scan = scan->next) {
if (scan->object->otype != OT_OBJECT || !CParser_IsPublicRuntimeObject(OBJECT(scan->object)))
return 0;
}
}
} while (++i < 1024);
return 1;
}
Boolean CScope_IsInLocalNameSpace(NameSpace *nspace) {
while (nspace) {
if (!nspace->is_global && !nspace->is_templ)
return 1;
nspace = nspace->parent;
}
return 0;
}
static void CScope_AppendNameSpaceName(NameSpaceName *nsn) {
if (nsn->next)
CScope_AppendNameSpaceName(nsn->next);
if (nsn->name) {
AppendGListName(&name_mangle_list, nsn->name->name);
AppendGListName(&name_mangle_list, "::");
}
}
static void CScope_AmbigNameError(NameSpace *nspace1, NameSpace *nspace2, HashNameNode *name) {
if (name && nspace1 != nspace2) {
CError_Error(CErrorStr319, CError_GetNameString(nspace1, name), CError_GetNameString(nspace2, name));
} else {
CError_Error(CErrorStr188, nspace2);
}
}
NameSpaceObjectList *CScope_FindName(NameSpace *nspace, HashNameNode *name) {
NameSpaceName *scan;
for (scan = nspace->tparams; scan; scan = scan->next) {
if (scan->name == name)
return &scan->first;
}
if (!nspace->is_hash)
scan = nspace->data.list;
else
scan = nspace->data.hash[name->hashval & 1023];
for (; scan; scan = scan->next) {
if (scan->name == name)
return &scan->first;
}
return NULL;
}
static NameSpaceObjectList *CScope_FindQualName(NameSpace *nspace, HashNameNode *name) {
NameSpaceName *scan;
if (!nspace->is_hash)
scan = nspace->data.list;
else
scan = nspace->data.hash[name->hashval & 1023];
for (; scan; scan = scan->next) {
if (scan->name == name)
return &scan->first;
}
return NULL;
}
NameSpaceName *CScope_FindNameSpaceName(NameSpace *nspace, HashNameNode *name) {
NameSpaceName *scan;
for (scan = nspace->tparams; scan; scan = scan->next) {
if (scan->name == name)
return scan;
}
if (!nspace->is_hash)
scan = nspace->data.list;
else
scan = nspace->data.hash[name->hashval & 1023];
for (; scan; scan = scan->next) {
if (scan->name == name)
return scan;
}
return NULL;
}
NameSpaceObjectList *CScope_InsertName(NameSpace *nspace, HashNameNode *name) {
NameSpaceName **nsnptr;
NameSpaceName *nsname;
if (nspace->is_global)
nsname = galloc(sizeof(NameSpaceName));
else
nsname = lalloc(sizeof(NameSpaceName));
nsname->name = name;
nsname->first.next = NULL;
nsname->first.object = NULL;
if (nspace->is_hash) {
nsnptr = &nspace->data.hash[name->hashval & 0x3FF];
nsname->next = *nsnptr;
*nsnptr = nsname;
} else {
nsname->next = nspace->data.list;
nspace->data.list = nsname;
}
nspace->names++;
return &nsname->first;
}
static NameSpaceObjectList *CScope_AppendName(NameSpace *nspace, HashNameNode *name) {
NameSpaceName *nsname;
NameSpaceName *scan;
CError_ASSERT(387, !nspace->is_hash);
if (nspace->is_global)
nsname = galloc(sizeof(NameSpaceName));
else
nsname = lalloc(sizeof(NameSpaceName));
nsname->next = NULL;
nsname->name = name;
nsname->first.next = NULL;
nsname->first.object = NULL;
if (nspace->data.list) {
scan = nspace->data.list;
while (scan->next)
scan = scan->next;
scan->next = nsname;
} else {
nspace->data.list = nsname;
}
nspace->names++;
return &nsname->first;
}
static NameSpaceList *CScope_AddNameSpaceToList(NameSpaceList *list, NameSpace *nspace) {
NameSpaceList *scan;
NameSpaceList *newlist;
ClassList *clslist;
for (scan = list; scan; scan = scan->next) {
if (scan->nspace == nspace)
return list;
}
newlist = lalloc(sizeof(NameSpaceList));
newlist->next = list;
newlist->nspace = nspace;
list = newlist;
if (nspace->theclass) {
list = CScope_AddNameSpaceToList(list, nspace->parent);
for (clslist = nspace->theclass->bases; clslist; clslist = clslist->next)
list = CScope_AddNameSpaceToList(list, clslist->base->nspace);
}
return list;
}
static NameSpaceList *CScope_BuildTypeAssociatedNameSpaceList(NameSpaceList *list, Type *type) {
FuncArg *arg;
restart:
switch (type->type) {
case TYPEVOID:
case TYPEINT:
case TYPEFLOAT:
case TYPESTRUCT:
case TYPEBITFIELD:
case TYPETEMPLATE:
case TYPETEMPLDEPEXPR:
break;
case TYPEPOINTER:
case TYPEARRAY:
type = TYPE_POINTER(type)->target;
goto restart;
case TYPEENUM:
list = CScope_AddNameSpaceToList(list, TYPE_ENUM(type)->nspace);
break;
case TYPEFUNC:
for (arg = TYPE_FUNC(type)->args; arg; arg = arg->next) {
if (arg->type)
list = CScope_BuildTypeAssociatedNameSpaceList(list, arg->type);
}
type = TYPE_FUNC(type)->functype;
goto restart;
case TYPEMEMBERPOINTER:
list = CScope_BuildTypeAssociatedNameSpaceList(list, TYPE_MEMBER_POINTER(type)->ty1);
type = TYPE_MEMBER_POINTER(type)->ty2;
if (!IS_TYPE_CLASS(type))
break;
case TYPECLASS:
list = CScope_AddNameSpaceToList(list, TYPE_CLASS(type)->nspace);
break;
default:
CError_FATAL(494);
}
return list;
}
static NameSpaceList *CScope_BuildAssociatedNameSpaceList(ENodeList *enodeList) {
// not 100% sure about the type for this but i think it's right??
NameSpaceList *nslist = NULL;
while (enodeList) {
nslist = CScope_BuildTypeAssociatedNameSpaceList(nslist, enodeList->node->rtype);
enodeList = enodeList->next;
}
return nslist;
}
static Boolean CScope_IsSameObject(Object *a, Object *b) {
if (a == b)
return 1;
return (a->nspace == b->nspace) && (a->name == b->name) && is_typesame(a->type, b->type);
}
NameSpaceObjectList *CScope_ArgumentDependentNameLookup(NameSpaceObjectList *list, HashNameNode *name, ENodeList *argNodes, Boolean flag) {
NameSpaceList *scan;
NameSpaceObjectList *iscan;
NameSpaceObjectList *iiscan;
NameSpaceObjectList *newlist;
for (scan = CScope_BuildAssociatedNameSpaceList(argNodes); scan; scan = scan->next) {
for (iscan = CScope_FindQualName(scan->nspace, name); iscan; iscan = iscan->next) {
if (iscan->object->otype != OT_OBJECT)
continue;
if (!IS_TYPE_FUNC(OBJECT(iscan->object)->type))
continue;
if (flag && (TYPE_FUNC(OBJECT(iscan->object)->type)->flags & FUNC_FLAGS_METHOD))
continue;
for (iiscan = list; iiscan; iiscan = iiscan->next) {
if (iiscan->object->otype == OT_OBJECT && CScope_IsSameObject(OBJECT(iiscan->object), OBJECT(iscan->object)))
break;
}
if (!iiscan) {
newlist = lalloc(sizeof(NameSpaceObjectList));
newlist->object = iscan->object;
newlist->next = list;
list = newlist;
}
}
}
return list;
}
NameSpace *CScope_NewHashNameSpace(HashNameNode *name) {
NameSpace *nspace;
void *buffer;
buffer = galloc(0x400 * sizeof(void *));
memclrw(buffer, 0x400 * sizeof(void *));
nspace = galloc(sizeof(NameSpace));
memclrw(nspace, sizeof(NameSpace));
nspace->name = name;
nspace->data.hash = buffer;
nspace->is_hash = 1;
nspace->is_global = 1;
return nspace;
}
NameSpace *CScope_NewListNameSpace(HashNameNode *name, Boolean is_global) {
NameSpace *nspace;
if (is_global) {
nspace = galloc(sizeof(NameSpace));
memclrw(nspace, sizeof(NameSpace));
} else {
nspace = lalloc(sizeof(NameSpace));
memclrw(nspace, sizeof(NameSpace));
}
nspace->name = name;
nspace->is_hash = 0;
nspace->is_global = is_global;
return nspace;
}
NameSpace *CScope_FindNonClassNonFunctionNS(NameSpace *nspace) {
while (nspace) {
if (!nspace->theclass && !nspace->is_templ)
return nspace;
nspace = nspace->parent;
}
return cscope_root;
}
NameSpace *CScope_FindGlobalNS(NameSpace *nspace) {
while (nspace) {
if (nspace->name && !nspace->theclass && nspace->is_global)
return nspace;
nspace = nspace->parent;
}
return cscope_root;
}
Boolean CScope_IsStdNameSpace(NameSpace *nspace) {
return nspace && !nspace->theclass && (nspace->parent == cscope_root) && nspace->name && !strcmp(nspace->name->name, "std");
}
Boolean CScope_IsEmptyNameSpace(NameSpace *nspace) {
CError_ASSERT(664, !nspace->is_hash);
return !nspace->data.list;
}
void CScope_MergeNameSpace(NameSpace *dst, NameSpace *src) {
NameSpaceName *nsname;
CError_ASSERT(678, !dst->is_hash && !src->is_hash);
if ((nsname = dst->data.list)) {
while (nsname->next)
nsname = nsname->next;
nsname->next = src->data.list;
} else {
dst->data.list = src->data.list;
}
}
void CScope_AddObject(NameSpace *nspace, HashNameNode *name, ObjBase *obj) {
NameSpaceObjectList *objlist;
NameSpaceObjectList *newlist;
objlist = CScope_FindQualName(nspace, name);
if (objlist) {
if (nspace->is_global)
newlist = galloc(sizeof(NameSpaceObjectList));
else
newlist = lalloc(sizeof(NameSpaceObjectList));
if (obj->otype == OT_NAMESPACE || objlist->object->otype == OT_NAMESPACE) {
CError_Error(CErrorStr322/*, objlist->object*/);
return;
}
if (obj->otype == OT_TYPETAG) {
do {
if (objlist->object->otype == OT_TYPETAG) {
CError_Error(CErrorStr322/*, objlist->object*/);
return;
}
if (copts.cplusplus && objlist->object->otype == OT_TYPE && !is_typesame(OBJ_TYPE_TAG(obj)->type, OBJ_TYPE(objlist->object)->type)) {
CError_Error(CErrorStr332);
return;
}
if (!objlist->next) {
objlist->next = newlist;
newlist->next = NULL;
newlist->object = obj;
return;
}
objlist = objlist->next;
} while (1);
}
if (objlist->object->otype == OT_TYPETAG) {
if (copts.cplusplus && obj->otype == OT_TYPE && !is_typesame(OBJ_TYPE(obj)->type, OBJ_TYPE_TAG(objlist->object)->type)) {
CError_Error(CErrorStr332);
return;
}
CError_ASSERT(739, !objlist->next);
newlist->object = objlist->object;
newlist->next = NULL;
objlist->object = obj;
objlist->next = newlist;
return;
}
if (!copts.cplusplus || !CScope_ObjectIsFunction(OBJECT(obj))) {
CError_Error(CErrorStr322);
return;
}
do {
if (objlist->object->otype == OT_TYPETAG) {
objlist->next = galloc(sizeof(NameSpaceObjectList));
objlist->next->next = NULL;
objlist->next->object = objlist->object;
objlist->object = obj;
return;
}
if (!CScope_ObjectIsFunction(OBJECT(objlist->object))) {
CError_Error(CErrorStr322);
return;
}
if (!objlist->next) {
objlist->next = galloc(sizeof(NameSpaceObjectList));
objlist->next->next = NULL;
objlist->next->object = obj;
return;
}
objlist = objlist->next;
} while (1);
} else if (nspace->theclass && TYPE_CLASS(nspace->theclass)->flags & CLASS_FLAGS_900) {
CScope_AppendName(nspace, name)->object = obj;
} else {
CScope_InsertName(nspace, name)->object = obj;
}
}
void CScope_AddGlobalObject(Object *obj) {
obj->nspace = cscope_root;
CScope_AddObject(cscope_root, obj->name, OBJ_BASE(obj));
}
NameSpaceLookupList *CScope_BuildNameSpaceLookupList(NameSpace *nspace) {
NameSpaceLookupList *lookup;
NameSpaceList list;
NameSpaceList *current;
NameSpaceList *current2;
NameSpaceList *current3;
NameSpaceList *newlist;
NameSpaceLookupList *currentL;
NameSpace *currentNS;
lookup = lalloc(sizeof(NameSpaceLookupList));
memclrw(lookup, sizeof(NameSpaceLookupList));
lookup->nspace = nspace;
if (nspace->parent)
lookup->next = CScope_BuildNameSpaceLookupList(nspace->parent);
if (nspace->usings) {
list.nspace = nspace;
list.next = NULL;
for (current2 = &list; current2; current2 = current2->next) {
for (current = current2->nspace->usings; current; current = current->next) {
for (current3 = &list; current3; current3 = current3->next) {
if (current3->nspace == current->nspace)
break;
}
if (!current3) {
newlist = lalloc(sizeof(NameSpaceList));
newlist->nspace = current->nspace;
newlist->next = current2->next;
current2->next = newlist;
}
}
}
for (current = list.next; current; current = current->next) {
for (currentL = lookup; currentL; currentL = currentL->next) {
for (currentNS = current->nspace; currentNS; currentNS = currentNS->parent) {
if (currentL->nspace == currentNS)
goto foundIt;
}
}
CError_FATAL(853);
foundIt:
for (current2 = currentL->namespaces; current2; current2 = current2->next) {
if (current2->nspace == current->nspace)
break;
}
if (!current2) {
newlist = lalloc(sizeof(NameSpaceList));
newlist->nspace = current->nspace;
newlist->next = currentL->namespaces;
currentL->namespaces = newlist;
}
}
}
return lookup;
}
static Boolean CScope_IsInLookup(NameSpaceLookupList *list, NameSpace *nspace) {
NameSpaceLookupList *scan;
NameSpaceList *iscan;
for (scan = list; scan; scan = scan->next) {
if (scan->nspace == nspace)
return 1;
for (iscan = scan->namespaces; iscan; iscan = iscan->next) {
if (iscan->nspace == nspace)
return 1;
}
}
return 0;
}
static NameSpaceLookupList *CScope_BuildNameSpaceMemberLookupList(NameSpace *nspace) {
NameSpaceLookupList list;
NameSpaceLookupList *current;
NameSpaceList *scan;
NameSpaceList *oscan;
NameSpaceList *newlist;
list.nspace = nspace;
list.namespaces = NULL;
list.next = NULL;
for (current = &list; current; current = current->next) {
if (current->nspace) {
for (scan = current->nspace->usings; scan; scan = scan->next) {
if (!CScope_IsInLookup(&list, scan->nspace)) {
if (!current->next) {
current->next = lalloc(sizeof(NameSpaceLookupList));
current->next->nspace = NULL;
current->next->namespaces = NULL;
current->next->next = NULL;
}
newlist = lalloc(sizeof(NameSpaceList));
newlist->nspace = scan->nspace;
newlist->next = current->next->namespaces;
current->next->namespaces = newlist;
}
}
}
for (oscan = current->namespaces; oscan; oscan = oscan->next) {
for (scan = oscan->nspace->usings; scan; scan = scan->next) {
if (!CScope_IsInLookup(&list, scan->nspace)) {
if (!current->next) {
current->next = lalloc(sizeof(NameSpaceLookupList));
current->next->nspace = NULL;
current->next->namespaces = NULL;
current->next->next = NULL;
}
newlist = lalloc(sizeof(NameSpaceList));
newlist->nspace = scan->nspace;
newlist->next = current->next->namespaces;
current->next->namespaces = newlist;
}
}
}
}
return list.next;
}
static NameSpaceObjectList *CScope_CopyNameSpaceObjectList(NameSpaceObjectList *list) {
NameSpaceObjectList *first, *current;
first = current = lalloc(sizeof(NameSpaceObjectList));
do {
current->object = list->object;
list = list->next;
if (!list) {
current->next = NULL;
break;
} else {
current->next = lalloc(sizeof(NameSpaceObjectList));
current = current->next;
}
} while (1);
return first;
}
static NameSpace *CScope_ExtractNameSpace(NameSpaceObjectList *list, Boolean *fail) {
Type *type;
restart:
if (!list)
return NULL;
switch (list->object->otype) {
case OT_TYPE:
type = OBJ_TYPE(list->object)->type;
break;
case OT_TYPETAG:
type = OBJ_TYPE_TAG(list->object)->type;
break;
case OT_NAMESPACE:
return OBJ_NAMESPACE(list->object)->nspace;
default:
CError_FATAL(1052);
break;
case OT_ENUMCONST:
case OT_MEMBERVAR:
case OT_OBJECT:
list = list->next;
goto restart;
}
if (!IS_TYPE_CLASS(type)) {
if (IS_TYPE_TEMPLATE(type))
return NULL;
CError_Error(CErrorStr320);
if (fail)
*fail = 1;
return NULL;
} else {
return TYPE_CLASS(type)->nspace;
}
}
static BClassList *CScope_RecFindClassMember(CScopeParseResult *result, TypeClass *tclass, SInt32 offset) {
Boolean fail;
NameSpace *nspace;
NameSpaceObjectList *list;
TypeClass *bestClass;
BClassList *bestBase;
ClassList *base;
BClassList *n;
BClassList *candidate;
SInt32 thisoffset;
BClassList *newlist;
if ((list = CScope_FindName(tclass->nspace, cscope_name))) {
if (cscope_foundclass) {
if (CClass_ClassDominates(cscope_foundclass, tclass))
return NULL;
if (CClass_ClassDominates(tclass, cscope_foundclass))
cscope_foundclass = NULL;
}
switch (cscope_lookuptype) {
case Lookup_2:
fail = 0;
if ((nspace = CScope_ExtractNameSpace(list, &fail))) {
if (cscope_foundclass) {
if (cscope_foundclass != tclass) {
CScope_AmbigNameError(cscope_foundclass->nspace, tclass->nspace, cscope_name);
return NULL;
}
if (cscope_foundclassoffset != offset)
cscope_isambig = 1;
return NULL;
}
cscope_foundclass = tclass;
cscope_foundclassoffset = offset;
result->nspace_0 = nspace;
newlist = lalloc(sizeof(BClassList));
newlist->next = NULL;
newlist->type = TYPE(tclass);
return newlist;
}
if (fail)
return NULL;
break;
case Lookup_0:
if (cscope_foundclass) {
if (
list->object->otype == OT_TYPETAG
&& result->nsol_14->object->otype == OT_TYPETAG
&& IS_TYPE_CLASS(OBJ_TYPE_TAG(list->object)->type)
&& IS_TYPE_CLASS(OBJ_TYPE_TAG(result->nsol_14->object)->type)
&& (TYPE_CLASS(OBJ_TYPE_TAG(list->object)->type)->flags & CLASS_FLAGS_800)
&& (TYPE_CLASS(OBJ_TYPE_TAG(result->nsol_14->object)->type)->flags & CLASS_FLAGS_800)
&& TEMPL_CLASS_INST(OBJ_TYPE_TAG(list->object)->type)->templ == TEMPL_CLASS_INST(OBJ_TYPE_TAG(result->nsol_14->object)->type)->templ
) {
cscope_foundtemplate = TEMPL_CLASS_INST(OBJ_TYPE_TAG(result->nsol_14->object)->type)->templ;
} else {
if (cscope_foundclass != tclass) {
CScope_AmbigNameError(cscope_foundclass->nspace, tclass->nspace, cscope_name);
return NULL;
}
if (cscope_foundclassoffset != offset) {
cscope_isambig = 1;
return NULL;
}
}
}
cscope_foundclass = tclass;
cscope_foundclassoffset = offset;
result->nsol_14 = list;
newlist = lalloc(sizeof(BClassList));
newlist->next = NULL;
newlist->type = TYPE(tclass);
return newlist;
case Lookup_1:
for (; list; list = list->next) {
if (list->object->otype == OT_TYPETAG) {
if (cscope_foundclass) {
if (cscope_foundclass != tclass) {
CScope_AmbigNameError(cscope_foundclass->nspace, tclass->nspace, cscope_name);
return NULL;
}
if (cscope_foundclassoffset != offset)
cscope_isambig = 1;
return NULL;
}
cscope_foundclass = tclass;
cscope_foundclassoffset = offset;
result->x8 = OBJ_TYPE_TAG(list->object)->type;
newlist = lalloc(sizeof(BClassList));
newlist->next = NULL;
newlist->type = TYPE(tclass);
return newlist;
}
}
break;
default:
CError_FATAL(1202);
}
}
for (base = tclass->bases, bestBase = NULL; base; base = base->next) {
thisoffset = base->is_virtual ? CClass_VirtualBaseOffset(cscope_mostderived, base->base) : offset + base->offset;
if ((candidate = CScope_RecFindClassMember(result, base->base, thisoffset))) {
n = lalloc(sizeof(BClassList));
n->next = candidate;
n->type = TYPE(tclass);
if (bestBase && bestClass == cscope_foundclass) {
if (CClass_IsMoreAccessiblePath(n, bestBase))
bestBase = n;
} else {
bestClass = cscope_foundclass;
bestBase = n;
}
}
}
return bestBase;
}
static Boolean CScope_FindClassMember(CScopeParseResult *result, NameSpace *nspace, HashNameNode *name, ELookupType lookupType) {
BClassList *bcl;
BClassList *scan;
cscope_mostderived = nspace->theclass;
cscope_foundclass = NULL;
cscope_foundtemplate = NULL;
cscope_name = name;
cscope_lookuptype = lookupType;
cscope_isambig = 0;
if ((bcl = CScope_RecFindClassMember(result, cscope_mostderived, 0))) {
if (cscope_foundtemplate)
return 1;
if ((scan = result->bcl_18)) {
while (scan->next)
scan = scan->next;
if (TYPE_CLASS(scan->type) != cscope_mostderived)
scan->next = bcl;
else
scan->next = bcl->next;
} else {
result->bcl_18 = bcl;
}
if (cscope_isambig)
result->isambig = 1;
return 1;
} else {
return 0;
}
}
static BClassList *CScope_GetAccessPathRec(TypeClass *src, TypeClass *dest, SInt32 offset) {
BClassList *list;
BClassList *best;
ClassList *base;
if (src == dest) {
if (cscope_foundclass && cscope_foundclassoffset != offset)
CError_Error(CErrorStr188);
list = lalloc(sizeof(BClassList));
list->next = NULL;
list->type = TYPE(src);
cscope_foundclass = src;
cscope_foundclassoffset = offset;
return list;
}
for (base = src->bases, best = NULL; base; base = base->next) {
if ((list = CScope_GetAccessPathRec(base->base, dest, base->is_virtual ? CClass_VirtualBaseOffset(cscope_mostderived, base->base) : (offset + base->offset))))
best = list;
}
if (best) {
list = lalloc(sizeof(BClassList));
list->next = best;
list->type = TYPE(src);
return list;
}
return NULL;
}
static BClassList *CScope_GetAccessPath(TypeClass *src, TypeClass *dest) {
cscope_mostderived = src;
cscope_foundclass = NULL;
return CScope_GetAccessPathRec(src, dest, 0);
}
static NameSpace *CScope_FindLookupNameSpace(CScopeNSIterator *iterator, NameSpaceLookupList *lookup, HashNameNode *name) {
NameSpaceObjectList *list;
NameSpaceList *scan;
NameSpace *retnspace = NULL;
NameSpace *candidate;
Boolean fail = 0;
if (lookup->nspace->theclass) {
if (CScope_FindClassMember(iterator->result, lookup->nspace, name, Lookup_2)) {
retnspace = iterator->result->nspace_0;
iterator->result->nspace_0 = NULL;
return retnspace;
} else {
return NULL;
}
}
if ((list = CScope_FindName(lookup->nspace, name))) {
fail = 0;
retnspace = CScope_ExtractNameSpace(list, &fail);
if (fail)
return NULL;
}
for (scan = lookup->namespaces; scan; scan = scan->next) {
fail = 0;
if ((list = CScope_FindName(scan->nspace, name)) && (candidate = CScope_ExtractNameSpace(list, &fail))) {
if (retnspace) {
if (retnspace != candidate)
CScope_AmbigNameError(retnspace, candidate, NULL);
} else {
retnspace = candidate;
}
}
if (fail)
return NULL;
}
return retnspace;
}
static NameSpaceObjectList *CScope_FindLookupName(NameSpaceLookupList *list, HashNameNode *name, NameSpace **foundnspace) {
NameSpaceName *scanname;
NameSpaceObjectList *tmpOL;
NameSpaceObjectList *r31;
NameSpaceObjectList *r30;
NameSpaceList *r29;
NameSpace *r28;
Boolean r27;
NameSpaceObjectList *r6;
NameSpaceObjectList *scanOL;
NameSpaceObjectList *newlist;
if (list->nspace) {
for (scanname = list->nspace->tparams; scanname; scanname = scanname->next) {
if (scanname->name == name)
return &scanname->first;
}
if ((tmpOL = CScope_FindName(list->nspace, name))) {
r31 = tmpOL;
r28 = list->nspace;
} else {
r31 = NULL;
r28 = NULL;
}
} else {
r31 = NULL;
r28 = NULL;
}
r27 = 0;
for (r29 = list->namespaces; r29; r29 = r29->next) {
if ((tmpOL = CScope_FindName(r29->nspace, name))) {
if (r31) {
for (r30 = tmpOL; r30; r30 = r30->next) {
for (r6 = r31; r6; r6 = r6->next) {
if (r6->object == r30->object)
break;
if (r6->object->otype == r30->object->otype) {
switch (r6->object->otype) {
case OT_TYPE:
if ((OBJ_TYPE(r6->object)->type == OBJ_TYPE(r30->object)->type) && (OBJ_TYPE(r6->object)->qual == OBJ_TYPE(r30->object)->qual))
goto break1;
break;
case OT_TYPETAG:
if (OBJ_TYPE_TAG(r6->object)->type == OBJ_TYPE_TAG(r30->object)->type)
goto break1;
break;
case OT_ENUMCONST:
if (OBJ_ENUM_CONST(r6->object)->type == OBJ_ENUM_CONST(r30->object)->type)
goto break1;
break;
case OT_OBJECT:
if (OBJECT(r6->object)->datatype == DALIAS) {
if (OBJECT(r30->object)->datatype == DALIAS) {
if (OBJECT(r6->object)->u.alias.object == OBJECT(r30->object)->u.alias.object)
goto break1;
} else {
if (OBJECT(r6->object)->u.alias.object == OBJECT(r30->object))
goto break1;
}
} else {
if ((OBJECT(r30->object)->datatype == DALIAS) && OBJECT(r6->object) == OBJECT(r30->object)->u.alias.object)
goto break1;
}
break;
}
}
}
break1:
if (!r6) {
if (!r27) {
r31 = CScope_CopyNameSpaceObjectList(r31);
r27 = 1;
}
if (CScope_ObjectIsFunction(OBJECT(r30->object))) {
for (scanOL = r31; scanOL; scanOL = scanOL->next) {
if (!CScope_ObjectIsFunction(OBJECT(scanOL->object))) {
if (scanOL->object->otype != OT_TYPETAG) {
CScope_AmbigNameError(r28, r29->nspace, name);
break;
}
}
}
} else if (r30->object->otype == OT_TYPETAG) {
for (scanOL = r31; scanOL; scanOL = scanOL->next) {
if (scanOL->object->otype == OT_TYPETAG) {
CScope_AmbigNameError(r28, r29->nspace, name);
break;
}
}
} else {
for (scanOL = r31; scanOL; scanOL = scanOL->next) {
if (scanOL->object->otype != OT_TYPETAG) {
CScope_AmbigNameError(r28, r29->nspace, name);
break;
}
}
}
if (!scanOL) {
newlist = lalloc(sizeof(NameSpaceObjectList));
newlist->object = r30->object;
newlist->next = r31;
r31 = newlist;
}
}
}
} else {
r31 = tmpOL;
r28 = r29->nspace;
}
}
}
if (foundnspace)
*foundnspace = r28;
return r31;
}
static NameSpaceObjectList *CScope_NSIteratorFind(CScopeNSIterator *iterator, HashNameNode *name) {
NameSpaceObjectList *list;
if (iterator->lookup) {
if (iterator->lookup->namespaces)
return CScope_FindLookupName(iterator->lookup, name, NULL);
if (iterator->lookup->nspace->theclass) {
if (CScope_FindClassMember(iterator->result, iterator->lookup->nspace, name, Lookup_0)) {
list = iterator->result->nsol_14;
iterator->result->nsol_14 = NULL;
return list;
} else {
return NULL;
}
}
if ((list = CScope_FindName(iterator->lookup->nspace, name)))
return list;
} else {
if (iterator->nspace->theclass) {
if (CScope_FindClassMember(iterator->result, iterator->nspace, name, Lookup_0)) {
list = iterator->result->nsol_14;
iterator->result->nsol_14 = NULL;
return list;
} else {
return NULL;
}
}
if ((list = CScope_FindName(iterator->nspace, name)))
return list;
}
return NULL;
}
static NameSpaceObjectList *CScope_NSIteratorNonClassFind(CScopeNSIterator *iterator, HashNameNode *name) {
NameSpaceObjectList *list;
if (iterator->lookup) {
if (iterator->lookup->namespaces)
return CScope_FindLookupName(iterator->lookup, name, NULL);
if (iterator->lookup->nspace->theclass)
return NULL;
if ((list = CScope_FindName(iterator->lookup->nspace, name)))
return list;
} else {
if (iterator->nspace->theclass)
return NULL;
if ((list = CScope_FindName(iterator->nspace, name)))
return list;
}
return NULL;
}
static NameSpace *CScope_NSIteratorFindNameSpace(CScopeNSIterator *iterator, HashNameNode *name) {
NameSpace *nspace;
NameSpaceObjectList *list;
if (iterator->lookup) {
if (iterator->lookup->namespaces)
return CScope_FindLookupNameSpace(iterator, iterator->lookup, name);
if (iterator->lookup->nspace->theclass) {
if (CScope_FindClassMember(iterator->result, iterator->lookup->nspace, name, Lookup_2)) {
nspace = iterator->result->nspace_0;
iterator->result->nspace_0 = NULL;
return nspace;
} else {
return NULL;
}
}
if ((list = CScope_FindName(iterator->lookup->nspace, name)))
return CScope_ExtractNameSpace(list, NULL);
} else {
if (iterator->nspace->theclass) {
if (CScope_FindClassMember(iterator->result, iterator->nspace, name, Lookup_2)) {
nspace = iterator->result->nspace_0;
iterator->result->nspace_0 = NULL;
return nspace;
} else {
return NULL;
}
}
if ((list = CScope_FindName(iterator->nspace, name)))
return CScope_ExtractNameSpace(list, NULL);
}
return NULL;
}
static Boolean CScope_SetupParseNameResult(CScopeParseResult *result, NameSpaceObjectList *list, HashNameNode *name) {
if (!list->next || list->next->object->otype == OT_TYPETAG) {
switch (list->object->otype) {
case OT_NAMESPACE:
CError_Error(CErrorStr321);
return 0;
case OT_TYPE:
result->x8 = OBJ_TYPE(list->object)->type;
result->xC = OBJ_TYPE(list->object)->qual;
result->obj_10 = list->object;
result->name_4 = name;
result->x20 = 1;
break;
case OT_TYPETAG:
result->x8 = OBJ_TYPE_TAG(list->object)->type;
result->xC = 0;
result->obj_10 = list->object;
result->name_4 = name;
result->x20 = 1;
break;
default:
result->obj_10 = list->object;
}
} else {
result->nsol_14 = list;
}
return 1;
}
Boolean CScope_FindQualifiedClassMember(CScopeParseResult *result, TypeClass *tclass, HashNameNode *name) {
NameSpaceObjectList *list;
memclrw(result, sizeof(CScopeParseResult));
CDecl_CompleteType(TYPE(tclass));
if (CScope_FindClassMember(result, tclass->nspace, name, Lookup_0)) {
list = result->nsol_14;
CError_ASSERT(1780, list);
result->nsol_14 = NULL;
if (CScope_SetupParseNameResult(result, list, name) && !result->x8)
return 1;
else
CError_Error(CErrorStr340, name->name);
}
return 0;
}
static NameSpace *CScope_FindQualifiedNameSpace(CScopeParseResult *result, NameSpace *nspace, HashNameNode *name) {
NameSpaceObjectList *list;
NameSpace *cand;
NameSpace *found;
NameSpaceList *scan;
NameSpaceLookupList *lookup;
Boolean fail = 0;
if (nspace->theclass) {
if (CScope_FindClassMember(result, nspace, name, Lookup_2)) {
nspace = result->nspace_0;
result->nspace_0 = NULL;
return nspace;
} else {
return NULL;
}
}
if ((list = CScope_FindQualName(nspace, name)) && CScope_ExtractNameSpace(list, &fail))
return nspace;
if (!fail && nspace->usings) {
found = NULL;
for (lookup = CScope_BuildNameSpaceMemberLookupList(nspace); lookup; lookup = lookup->next) {
for (scan = lookup->namespaces; scan; scan = scan->next) {
if ((list = CScope_FindQualName(scan->nspace, name)) && (cand = CScope_ExtractNameSpace(list, &fail))) {
if (found && cand != found)
CScope_AmbigNameError(found, cand, NULL);
found = cand;
}
if (fail)
return NULL;
}
if (found)
return found;
}
}
return NULL;
}
static NameSpaceObjectList *CScope_FindQualifiedName(CScopeParseResult *result, NameSpace *nspace, HashNameNode *name, NameSpace **foundnspace) {
NameSpaceObjectList *list;
NameSpaceLookupList *lookup;
if (nspace->theclass) {
CDecl_CompleteType(TYPE(nspace->theclass));
if (CScope_FindClassMember(result, nspace, name, Lookup_0)) {
list = result->nsol_14;
result->nsol_14 = NULL;
return list;
} else {
return NULL;
}
}
if ((list = CScope_FindQualName(nspace, name))) {
*foundnspace = nspace;
return list;
}
if (nspace->usings) {
for (lookup = CScope_BuildNameSpaceMemberLookupList(nspace); lookup; lookup = lookup->next) {
if ((list = CScope_FindLookupName(lookup, name, foundnspace)))
return list;
}
}
return NULL;
}
static Boolean CScope_FindQualifiedTag(CScopeParseResult *result, NameSpace *nspace, HashNameNode *name) {
NameSpaceObjectList *list;
NameSpaceLookupList *lookup;
Type *best;
NameSpace *bestnspace;
NameSpaceList *scan;
if (nspace->theclass) {
CDecl_CompleteType(TYPE(nspace->theclass));
return CScope_FindClassMember(result, nspace, name, Lookup_1) != 0;
}
if ((list = CScope_FindQualName(nspace, name))) {
for (; list; list = list->next) {
if (list->object->otype == OT_TYPETAG) {
result->x8 = OBJ_TYPE_TAG(list->object)->type;
return 1;
}
}
}
if (nspace->usings) {
best = NULL;
for (lookup = CScope_BuildNameSpaceMemberLookupList(nspace); lookup; lookup = lookup->next) {
for (scan = lookup->namespaces; scan; scan = scan->next) {
for (list = CScope_FindQualName(scan->nspace, name); list; list = list->next) {
if (list->object->otype == OT_TYPETAG) {
if (best && best != OBJ_TYPE_TAG(list->object)->type)
CScope_AmbigNameError(scan->nspace, bestnspace, name);
best = OBJ_TYPE_TAG(list->object)->type;
bestnspace = scan->nspace;
break;
}
}
}
if (best) {
result->x8 = best;
return 1;
}
}
}
return 0;
}
CW_INLINE void CScope_NSIteratorInit(CScopeNSIterator *iterator, NameSpace *nspace, CScopeParseResult *result) {
// assumed name
if (nspace->usings) {
iterator->nspace = NULL;
iterator->lookup = CScope_BuildNameSpaceLookupList(nspace);
} else {
iterator->nspace = nspace;
iterator->lookup = NULL;
}
iterator->result = result;
}
CW_INLINE Boolean CScope_NSIteratorNext(CScopeNSIterator *iterator) {
// assumed name
if (iterator->lookup)
return (iterator->lookup = iterator->lookup->next) != NULL;
if (iterator->result->x1D)
return 0;
if ((iterator->nspace = iterator->nspace->parent)) {
if (iterator->nspace->usings && !iterator->result->x1D) {
iterator->lookup = CScope_BuildNameSpaceLookupList(iterator->nspace);
iterator->nspace = NULL;
}
return 1;
} else {
return 0;
}
}
Type *CScope_GetType(NameSpace *nspace, HashNameNode *name, UInt32 *qual) {
CScopeParseResult result;
CScopeNSIterator iterator;
NameSpaceObjectList *list;
Boolean ok;
memclrw(&result, sizeof(result));
CScope_NSIteratorInit(&iterator, nspace, &result);
do {
for (list = CScope_NSIteratorFind(&iterator, name); list; list = list->next) {
if (list->object->otype == OT_TYPETAG) {
if (qual)
*qual = 0;
return OBJ_TYPE_TAG(list->object)->type;
}
if (list->object->otype == OT_TYPE) {
if (qual)
*qual = OBJ_TYPE(list->object)->qual;
return OBJ_TYPE(list->object)->type;
}
}
} while (CScope_NSIteratorNext(&iterator));
return NULL;
}
Type *CScope_GetTagType(NameSpace *nspace, HashNameNode *name) {
CScopeParseResult result;
CScopeNSIterator iterator;
NameSpaceObjectList *list;
Boolean ok;
memclrw(&result, sizeof(result));
CScope_NSIteratorInit(&iterator, nspace, &result);
do {
for (list = CScope_NSIteratorFind(&iterator, name); list; list = list->next) {
if (list->object->otype == OT_TYPETAG)
return OBJ_TYPE_TAG(list->object)->type;
}
} while (CScope_NSIteratorNext(&iterator));
return NULL;
}
static Boolean CScope_DependentTemplateMember(CScopeParseResult *result, TypeTemplDep *ttempldep, Boolean flag1, Boolean flag2) {
SInt32 streamstate;
short token;
TypeTemplDep *newtype;
TypeTemplDep *newtype2;
CPrep_TokenStreamGetState(&streamstate);
token = lex();
CError_ASSERT(2026, token == TK_COLON_COLON);
while (1) {
token = lex();
if (token == TK_OPERATOR && flag1) {
if (!CParser_ParseOperatorName(NULL, 1, 1))
return 0;
newtype = TYPE_TEMPLATE(CDecl_NewTemplDepType(TEMPLDEP_QUALNAME));
newtype->u.qual.type = ttempldep;
newtype->u.qual.name = tkidentifier;
CPrep_TokenStreamSetState(&streamstate);
lex();
tk = lex();
result->x8 = TYPE(newtype);
return 1;
}
if (token == TK_TEMPLATE) {
if (lex() != TK_IDENTIFIER) {
CError_Error(CErrorStr107);
return 0;
}
CPrep_TokenStreamGetState(&streamstate);
newtype = TYPE_TEMPLATE(CDecl_NewTemplDepType(TEMPLDEP_QUALNAME));
newtype->u.qual.type = ttempldep;
newtype->u.qual.name = tkidentifier;
if ((token = lex()) != '<') {
CError_Error(CErrorStr230);
return 0;
}
tk = token;
newtype2 = TYPE_TEMPLATE(CDecl_NewTemplDepType(TEMPLDEP_QUALTEMPL));
newtype2->u.qualtempl.type = newtype;
newtype2->u.qualtempl.args = CTempl_ParseUncheckTemplArgs(NULL, 1);
CPrep_TokenStreamGetState(&streamstate);
if (lex() == TK_COLON_COLON) {
ttempldep = newtype2;
continue;
} else {
CPrep_TokenStreamSetState(&streamstate);
result->x8 = TYPE(newtype2);
return 1;
}
}
if (token == TK_IDENTIFIER) {
newtype = TYPE_TEMPLATE(CDecl_NewTemplDepType(TEMPLDEP_QUALNAME));
newtype->u.qual.type = ttempldep;
newtype->u.qual.name = tkidentifier;
tk = token;
CPrep_TokenStreamGetState(&streamstate);
token = lex();
tkidentifier = newtype->u.qual.name;
if (token == TK_COLON_COLON) {
ttempldep = newtype;
continue;
}
if ((token == '<') && !flag2) {
tk = token;
newtype2 = newtype;
newtype = TYPE_TEMPLATE(CDecl_NewTemplDepType(TEMPLDEP_QUALTEMPL));
newtype->u.qualtempl.type = newtype2;
newtype->u.qualtempl.args = CTempl_ParseUncheckTemplArgs(NULL, 1);
CPrep_TokenStreamGetState(&streamstate);
if (lex() == TK_COLON_COLON) {
ttempldep = newtype;
continue;
}
}
CPrep_TokenStreamSetState(&streamstate);
result->x8 = TYPE(newtype);
return 1;
}
CPrep_TokenStreamSetState(&streamstate);
result->x8 = TYPE(ttempldep);
return 1;
}
}
static Boolean CScope_CheckDtorName(TypeClass *tclass, Boolean *flag) {
if ((tk = lex()) != TK_IDENTIFIER)
CError_Error(CErrorStr107);
if (tclass) {
*flag = 0;
if (
(tclass->classname == tkidentifier) ||
(CScope_GetType(tclass->nspace, tkidentifier, NULL) == TYPE(tclass)) ||
(CScope_GetType(cscope_current, tkidentifier, NULL) == TYPE(tclass))
)
{
if (!CClass_Destructor(tclass))
*flag = 1;
if ((tclass->flags & CLASS_FLAGS_800) && (lookahead() == '<')) {
tk = lex();
if (!CTemplTool_EqualArgs(TEMPL_CLASS_INST(tclass)->inst_args, CTempl_ParseUncheckTemplArgs(NULL, 0)))
CError_Error(CErrorStr374);
}
return 1;
}
}
CError_Error(CErrorStr141);
return 0;
}
static Boolean CScope_ParseQualifiedName(CScopeParseResult *result, NameSpace *nspace) {
NameSpaceObjectList *list;
HashNameNode *saveidentifier;
TypeClass *tclass;
Boolean flag = 0;
do {
switch (tk) {
case TK_TEMPLATE:
if ((tk = lex()) != TK_IDENTIFIER) {
CError_Error(CErrorStr107);
return 0;
}
case TK_IDENTIFIER:
saveidentifier = tkidentifier;
if (lookahead() == TK_COLON_COLON) {
tk = lex();
nspace = CScope_FindQualifiedNameSpace(result, nspace, saveidentifier);
if (!nspace)
return 0;
result->x1D = 1;
tk = lex();
continue;
}
break;
case TK_OPERATOR:
if (!CParser_ParseOperatorName(NULL, 1, 1))
return 0;
CPrep_UnLex();
saveidentifier = tkidentifier;
break;
case '~':
if (!CScope_CheckDtorName(nspace->theclass, &flag))
return 0;
saveidentifier = destructor_name_node;
flag = 1;
break;
default:
CError_Error(CErrorStr107);
return 0;
}
if (!(list = CScope_FindQualifiedName(result, nspace, saveidentifier, &result->nspace_0)) || !CScope_SetupParseNameResult(result, list, saveidentifier)) {
if (flag) {
result->x1C = 1;
return 1;
}
if (nspace->theclass && !(nspace->theclass->flags & CLASS_FLAGS_2))
CError_Error(CErrorStr136, nspace->theclass, 0);
else
CError_Error(CErrorStr140, saveidentifier->name);
return 0;
}
if (result->x8 && IS_TYPE_CLASS(result->x8) && (lookahead() == '<')) {
tclass = TYPE_CLASS(result->x8);
if (tclass->flags & CLASS_FLAGS_800)
tclass = TYPE_CLASS(TEMPL_CLASS_INST(tclass)->templ);
else if (!(tclass->flags & CLASS_FLAGS_100))
return 1;
tk = lex();
result->x8 = CTempl_ClassGetType(TEMPL_CLASS(tclass));
if (IS_TYPE_CLASS(result->x8) && (lookahead() == TK_COLON_COLON)) {
lex();
tk = lex();
result->x1D = 1;
nspace = TYPE_CLASS(result->x8)->nspace;
result->x8 = NULL;
result->obj_10 = NULL;
continue;
}
}
return 1;
} while (1);
}
Boolean CScope_ParseExprName(CScopeParseResult *result) {
CScopeNSIterator iterator;
HashNameNode *name;
NameSpaceObjectList *list;
Boolean flag;
if (!copts.cplusplus) {
memclrw(result, sizeof(CScopeParseResult));
if (tk != TK_IDENTIFIER) {
CError_Error(CErrorStr107);
return 0;
}
name = tkidentifier;
CScope_NSIteratorInit(&iterator, cscope_current, result);
do {
if ((list = CScope_NSIteratorFind(&iterator, name)) && (list->object->otype != OT_TYPETAG)) {
result->nspace_0 = iterator.lookup ? iterator.lookup->nspace : iterator.nspace;
return CScope_SetupParseNameResult(result, list, name);
}
} while (CScope_NSIteratorNext(&iterator));
result->nspace_0 = cscope_current;
result->name_4 = name;
return 1;
} else {
if ((tk == TK_COLON_COLON || tk == TK_IDENTIFIER) && CScope_ParseQualifiedNameSpace(result, 1, 1)) {
if (result->x8)
return 1;
CError_ASSERT(2313, result->nspace_0);
} else {
memclrw(result, sizeof(CScopeParseResult));
result->nspace_0 = cscope_current;
}
switch (tk) {
case TK_TEMPLATE:
if (!result->x1D)
CError_Error(CErrorStr373);
if ((tk = lex()) != TK_IDENTIFIER) {
CError_Error(CErrorStr107);
return 0;
}
case TK_IDENTIFIER:
name = tkidentifier;
break;
case TK_OPERATOR:
if (!CParser_ParseOperatorName(NULL, 1, 1))
return 0;
name = tkidentifier;
CPrep_UnLex();
break;
case '~':
if (!CScope_CheckDtorName(result->nspace_0->theclass, &flag))
return 0;
if (flag) {
result->x1C = 1;
return 1;
}
name = destructor_name_node;
break;
default:
CError_Error(CErrorStr107);
return 0;
}
if (result->x1D) {
if (!(list = CScope_FindQualifiedName(result, result->nspace_0, name, &result->nspace_0))) {
CError_Error(CErrorStr140, CError_GetNameString(result->nspace_0, name));
return 0;
} else {
return CScope_SetupParseNameResult(result, list, name);
}
}
CScope_NSIteratorInit(&iterator, result->nspace_0, result);
do {
if ((list = CScope_NSIteratorFind(&iterator, name))) {
result->nspace_0 = iterator.lookup ? iterator.lookup->nspace : iterator.nspace;
return CScope_SetupParseNameResult(result, list, name);
}
} while (CScope_NSIteratorNext(&iterator));
if (result->x1D) {
CError_Error(CErrorStr140, name->name);
return 0;
} else {
result->nspace_0 = cscope_current;
result->name_4 = name;
return 1;
}
}
}
Boolean CScope_ParseDeclName(CScopeParseResult *result) {
CScopeNSIterator iterator;
HashNameNode *name;
NameSpaceObjectList *list;
NameSpace *nspace;
Boolean flag;
CScopeSave save;
short op;
if (!copts.cplusplus) {
non_cpp_mode:
if (tk != TK_IDENTIFIER) {
CError_Error(CErrorStr107);
return 0;
}
memclrw(result, sizeof(CScopeParseResult));
name = tkidentifier;
CScope_NSIteratorInit(&iterator, cscope_current, result);
do {
if ((list = CScope_NSIteratorFind(&iterator, name)) && (copts.cplusplus || (list->object->otype != OT_TYPETAG))) {
result->nspace_0 = iterator.lookup ? iterator.lookup->nspace : iterator.nspace;
return CScope_SetupParseNameResult(result, list, name);
}
} while (CScope_NSIteratorNext(&iterator));
result->nspace_0 = cscope_current;
result->name_4 = name;
return 0;
} else {
if ((tk != TK_COLON_COLON) && (tk != TK_IDENTIFIER)) {
CError_Error(CErrorStr107);
return 0;
}
if (!CScope_ParseQualifiedNameSpace(result, 0, 0))
goto non_cpp_mode;
if (result->x8)
return 1;
nspace = result->nspace_0;
CError_ASSERT(2435, nspace);
switch (tk) {
case TK_OPERATOR:
CScope_SetNameSpaceScope(nspace, &save);
if (!CParser_ParseOperatorName(&op, 1, 1)) {
CScope_RestoreScope(&save);
return 0;
}
CScope_RestoreScope(&save);
if (op)
CError_Error(CErrorStr121);
result->x21 = 1;
return 1;
case TK_IDENTIFIER:
name = tkidentifier;
if (nspace->theclass && nspace->theclass->classname == tkidentifier)
name = constructor_name_node;
break;
case '~':
if (!nspace->theclass) {
CError_Error(CErrorStr121);
return 0;
}
tk = lex();
if (tk != TK_IDENTIFIER) {
CError_Error(CErrorStr107);
return 0;
}
if (nspace->theclass->classname != tkidentifier)
CError_Error(CErrorStr121);
name = destructor_name_node;
break;
default:
CError_Error(CErrorStr107);
return 0;
}
if (result->x1D) {
if (!(list = CScope_FindQualifiedName(result, result->nspace_0, name, &result->nspace_0))) {
CError_Error(CErrorStr140, name->name);
return 0;
} else {
return CScope_SetupParseNameResult(result, list, name);
}
}
CScope_NSIteratorInit(&iterator, nspace, result);
do {
if ((list = CScope_NSIteratorFind(&iterator, name))) {
result->nspace_0 = iterator.lookup ? iterator.lookup->nspace : iterator.nspace;
return CScope_SetupParseNameResult(result, list, name);
}
} while (CScope_NSIteratorNext(&iterator));
CError_Error(CErrorStr140, name->name);
return 0;
}
}
Boolean CScope_ParseQualifiedNameSpace(CScopeParseResult *result, Boolean flag1, Boolean flag2) {
// mostly matches, some registers are awkwardly swapped
HashNameNode *name; // r25
NameSpace *nspace; // r24
short t; // r23
Type *type; // r28?
Type *type2; // r21?
NameSpaceObjectList *list; // r21
CScopeNSIterator iterator;
memclrw(result, sizeof(CScopeParseResult));
nspace = NULL;
if (tk == TK_COLON_COLON) {
result->nspace_0 = nspace = cscope_root;
result->x1D = 1;
tk = lex();
}
restart:
if (tk != TK_IDENTIFIER) {
if (tk != TK_TEMPLATE)
return nspace != NULL;
if (!result->x1D)
CError_Error(CErrorStr373);
if ((tk = lex()) != TK_IDENTIFIER) {
CError_Error(CErrorStr107);
return 0;
}
}
name = tkidentifier;
t = lookahead();
tkidentifier = name;
if (t != TK_COLON_COLON && t != '<')
return nspace != NULL;
CScope_NSIteratorInit(&iterator, nspace ? nspace : cscope_current, result);
// r28 = r23 ???
do {
// list = r21
for (list = CScope_NSIteratorFind(&iterator, name); list; list = list->next) {
if (list->object->otype == OT_NAMESPACE) {
CError_ASSERT(2565, !nspace || !nspace->theclass);
result->nspace_0 = nspace = OBJ_NAMESPACE(list->object)->nspace;
if ((tk = lex()) != TK_COLON_COLON) {
CError_Error(CErrorStr321);
return 0;
}
result->x1D = 1;
tk = lex();
goto restart;
}
if (list->object->otype == OT_TYPETAG) {
type = OBJ_TYPE_TAG(list->object)->type;
if (type->type != TYPECLASS) {
if (t == '<') {
result->x8 = type;
return 1;
} else {
CError_Error(CErrorStr121);
return 0;
}
}
parse_thing:
if (t == '<') {
if (TYPE_CLASS(type)->flags & CLASS_FLAGS_800) {
type = TYPE(TEMPL_CLASS_INST(type)->templ);
} else if (!(TYPE_CLASS(type)->flags & CLASS_FLAGS_100)) {
result->x8 = type;
return 1;
}
}
if ((tk = lex()) == '<') {
CError_ASSERT(2609, TYPE_CLASS(type)->flags & CLASS_FLAGS_100);
type2 = CTempl_ClassGetType(TEMPL_CLASS(type));
if (IS_TYPE_TEMPLATE(type2)) {
if (lookahead() != TK_COLON_COLON) {
result->x8 = type2;
return 1;
}
return CScope_DependentTemplateMember(result, TYPE_TEMPLATE(type2), flag1, flag2);
} else if (type2->type != TYPECLASS) {
return 0;
}
result->nspace_0 = nspace = TYPE_CLASS(type2)->nspace;
if (lookahead() != TK_COLON_COLON) {
result->x8 = type2;
return 1;
}
tk = lex();
CDecl_CompleteType(type2);
} else {
CError_ASSERT(2632, tk == TK_COLON_COLON);
if (!(TYPE_CLASS(type)->flags & CLASS_FLAGS_100) || CParser_CheckTemplateClassUsage(TEMPL_CLASS(type), 1))
result->nspace_0 = nspace = TYPE_CLASS(type)->nspace;
CDecl_CompleteType(type);
}
result->x1D = 1;
tk = lex();
goto restart;
}
if (list->object->otype == OT_TYPE) {
type2 = OBJ_TYPE(list->object)->type;
if (!IS_TYPE_CLASS(type2)) {
if (IS_TYPE_TEMPLATE(type2)) {
if (TYPE_TEMPLATE(type2)->dtype == TEMPLDEP_ARGUMENT && TYPE_TEMPLATE(type2)->u.pid.type == TPT_TEMPLATE) {
type2 = CTempl_ParseTemplTemplParam(TYPE_TEMPLATE(type2));
if ((type2->type != TYPETEMPLATE) || ((t = lookahead()) != TK_COLON_COLON)) {
result->x8 = type2;
return 1;
}
}
if (t == TK_COLON_COLON)
return CScope_DependentTemplateMember(result, TYPE_TEMPLATE(type2), flag1, flag2);
}
if (t == '<') {
result->x8 = type2;
return 1;
} else {
CError_Error(CErrorStr121);
return 0;
}
} else {
if ((t == '<') && (TYPE_CLASS(type2)->flags & CLASS_FLAGS_100)) {
type = type2;
goto parse_thing;
}
if ((tk = lex()) == '<') {
result->x8 = type2;
return 1;
}
CError_ASSERT(2686, tk == TK_COLON_COLON);
if (!type2->size)
CDecl_CompleteType(type2);
result->nspace_0 = nspace = TYPE_CLASS(type2)->nspace;
result->x1D = 1;
tk = lex();
goto restart;
}
}
if (t == '<')
return nspace != NULL;
}
} while (CScope_NSIteratorNext(&iterator));
CError_Error(CErrorStr140, name->name);
return 0;
}
Boolean CScope_ParseElaborateName(CScopeParseResult *result) {
CScopeNSIterator iterator;
HashNameNode *name;
NameSpaceObjectList *list;
Boolean flag;
if (!copts.cplusplus) {
memclrw(result, sizeof(CScopeParseResult));
if (tk != TK_IDENTIFIER) {
CError_Error(CErrorStr107);
return 0;
}
name = tkidentifier;
CScope_NSIteratorInit(&iterator, cscope_current, result);
do {
for (list = CScope_NSIteratorFind(&iterator, name); list; list = list->next) {
if (list->object->otype == OT_TYPETAG) {
result->nspace_0 = iterator.lookup ? iterator.lookup->nspace : iterator.nspace;
return CScope_SetupParseNameResult(result, list, name);
}
}
} while (CScope_NSIteratorNext(&iterator));
result->name_4 = name;
return 1;
} else {
if ((tk != TK_COLON_COLON) && (tk != TK_IDENTIFIER)) {
CError_Error(CErrorStr107);
return 0;
}
if (!CScope_ParseQualifiedNameSpace(result, 0, 0)) {
result->nspace_0 = cscope_current;
if (tk != TK_IDENTIFIER) {
CError_Error(CErrorStr107);
return 0;
}
name = tkidentifier;
} else {
if (result->x8)
return 1;
CError_ASSERT(2760, result->nspace_0);
if (tk != TK_IDENTIFIER) {
CError_Error(CErrorStr107);
return 0;
}
name = tkidentifier;
if (result->x1D) {
if (result->nspace_0->theclass)
return CScope_FindClassMember(result, result->nspace_0, name, Lookup_1) != 0;
else
return CScope_FindQualifiedTag(result, result->nspace_0, name);
}
}
CScope_NSIteratorInit(&iterator, result->nspace_0, result);
do {
for (list = CScope_NSIteratorFind(&iterator, name); list; list = list->next) {
if (list->object->otype == OT_TYPETAG || list->object->otype == OT_TYPE) {
result->nspace_0 = iterator.lookup ? iterator.lookup->nspace : iterator.nspace;
return CScope_SetupParseNameResult(result, list, name);
}
}
} while (CScope_NSIteratorNext(&iterator));
result->name_4 = name;
return 1;
}
}
Boolean CScope_FindObject(NameSpace *nspace, CScopeParseResult *result, HashNameNode *name) {
CScopeNSIterator iterator;
NameSpaceObjectList *list;
memclrw(result, sizeof(CScopeParseResult));
CScope_NSIteratorInit(&iterator, nspace, result);
do {
for (list = CScope_NSIteratorFind(&iterator, name); list; list = list->next) {
if (copts.cplusplus || list->object->otype != OT_TYPETAG) {
result->nspace_0 = iterator.lookup ? iterator.lookup->nspace : iterator.nspace;
return CScope_SetupParseNameResult(result, list, name);
}
}
} while (CScope_NSIteratorNext(&iterator));
return 0;
}
Boolean CScope_FindNonClassObject(NameSpace *nspace, CScopeParseResult *result, HashNameNode *name) {
CScopeNSIterator iterator;
NameSpaceObjectList *list;
memclrw(result, sizeof(CScopeParseResult));
CScope_NSIteratorInit(&iterator, nspace, result);
do {
for (list = CScope_NSIteratorNonClassFind(&iterator, name); list; list = list->next) {
if (copts.cplusplus || list->object->otype != OT_TYPETAG) {
result->nspace_0 = iterator.lookup ? iterator.lookup->nspace : iterator.nspace;
return CScope_SetupParseNameResult(result, list, name);
}
}
} while (CScope_NSIteratorNext(&iterator));
return 0;
}
NameSpaceObjectList *CScope_FindObjectList(CScopeParseResult *result, HashNameNode *name) {
CScopeNSIterator iterator;
NameSpaceObjectList *list;
memclrw(result, sizeof(CScopeParseResult));
CScope_NSIteratorInit(&iterator, cscope_current, result);
do {
for (list = CScope_NSIteratorFind(&iterator, name); list; list = list->next) {
if (copts.cplusplus || list->object->otype != OT_TYPETAG) {
result->nspace_0 = iterator.lookup ? iterator.lookup->nspace : iterator.nspace;
return list;
}
}
} while (CScope_NSIteratorNext(&iterator));
return 0;
}
Boolean CScope_PossibleTypeName(HashNameNode *name) {
CScopeParseResult result;
CScopeNSIterator iterator;
NameSpaceObjectList *list;
memclrw(&result, sizeof(CScopeParseResult));
CScope_NSIteratorInit(&iterator, cscope_current, &result);
do {
if ((list = CScope_NSIteratorFind(&iterator, name))) {
switch (list->object->otype) {
case OT_TYPE:
case OT_NAMESPACE:
return 1;
case OT_TYPETAG:
if (copts.cplusplus)
return 1;
break;
default:
return 0;
}
}
} while (CScope_NSIteratorNext(&iterator));
return 0;
}
Boolean CScope_FindClassMemberObject(TypeClass *tclass, CScopeParseResult *result, HashNameNode *name) {
NameSpaceObjectList *list;
memclrw(result, sizeof(CScopeParseResult));
if (CScope_FindClassMember(result, tclass->nspace, name, Lookup_0)) {
list = result->nsol_14;
result->nsol_14 = NULL;
if (list && list->object->otype == OT_OBJECT)
return CScope_SetupParseNameResult(result, list, name);
}
return 0;
}
void CScope_InitObjectIterator(CScopeObjectIterator *iterator, NameSpace *nspace) {
memclrw(iterator, sizeof(CScopeObjectIterator));
iterator->nspace = nspace;
if (!iterator->nspace->is_hash)
iterator->nextname = nspace->data.list;
else
iterator->nextname = nspace->data.hash[0];
}
ObjBase *CScope_NextObjectIteratorObject(CScopeObjectIterator *iterator) {
ObjBase *obj;
do {
if (iterator->currlist) {
do {
obj = iterator->currlist->object;
if (obj->otype == OT_OBJECT) {
iterator->currlist = iterator->currlist->next;
return obj;
}
} while ((iterator->currlist = iterator->currlist->next));
}
if (iterator->nextname) {
iterator->currlist = &iterator->nextname->first;
iterator->nextname = iterator->nextname->next;
} else {
if (!iterator->nspace->is_hash || ++iterator->hashindex >= 1024)
return NULL;
iterator->nextname = iterator->nspace->data.hash[iterator->hashindex];
}
} while (1);
}
NameSpaceObjectList *CScope_NextObjectIteratorObjectList(CScopeObjectIterator *iterator) {
NameSpaceName *nsname;
do {
if ((nsname = iterator->nextname)) {
iterator->nextname = nsname->next;
return &nsname->first;
} else {
if (!iterator->nspace->is_hash || ++iterator->hashindex >= 1024)
return NULL;
iterator->nextname = iterator->nspace->data.hash[iterator->hashindex];
}
} while (1);
}
void CScope_DefineTypeTag(NameSpace *nspace, HashNameNode *name, Type *type) {
ObjTypeTag *ott;
ott = galloc(sizeof(ObjTypeTag));
memclrw(ott, sizeof(ObjTypeTag));
ott->otype = OT_TYPETAG;
ott->access = nspace->theclass ? global_access : ACCESSPUBLIC;
ott->type = type;
CScope_AddObject(nspace, name, OBJ_BASE(ott));
}
Type *CScope_GetLocalTagType(NameSpace *nspace, HashNameNode *name) {
NameSpaceObjectList *list;
for (list = CScope_FindQualName(nspace, name); list; list = list->next) {
if (list->object->otype == OT_TYPETAG)
return OBJ_TYPE_TAG(list->object)->type;
}
return NULL;
}
Boolean CScope_FindTypeName(NameSpace *nspace, HashNameNode *name, CScopeParseResult *result) {
CScopeNSIterator iterator;
NameSpaceObjectList *list;
NameSpaceObjectList *scan;
memclrw(result, sizeof(CScopeParseResult));
CScope_NSIteratorInit(&iterator, nspace, result);
do {
list = CScope_NSIteratorFind(&iterator, name);
for (scan = list; scan; scan = scan->next) {
switch (scan->object->otype) {
case OT_NAMESPACE:
result->nspace_0 = OBJ_NAMESPACE(scan->object)->nspace;
return 1;
case OT_TYPE:
case OT_TYPETAG:
return CScope_SetupParseNameResult(result, scan, name);
default:
return 0;
}
}
} while (CScope_NSIteratorNext(&iterator));
return 0;
}
static NameSpaceObjectList *CScope_GetLocalObjects(NameSpaceObjectList *objs) {
NameSpaceObjectList *list;
NameSpaceObjectList **ptr;
list = objs;
while (list) {
if (list->object->otype == OT_OBJECT && OBJECT(list->object)->datatype == DALIAS) {
list = CScope_CopyNameSpaceObjectList(objs);
ptr = &list;
while (*ptr) {
if ((*ptr)->object->otype == OT_OBJECT && OBJECT((*ptr)->object)->datatype == DALIAS)
*ptr = (*ptr)->next;
else
ptr = &(*ptr)->next;
}
return list;
} else {
list = list->next;
}
}
return objs;
}
NameSpaceObjectList *CScope_GetLocalObject(NameSpace *nspace, HashNameNode *name) {
NameSpaceObjectList *list;
if ((list = CScope_FindQualName(nspace, name))) {
switch (list->object->otype) {
case OT_OBJECT:
return CScope_GetLocalObjects(list);
default:
CError_Error(CErrorStr122, name->name);
return NULL;
case OT_TYPETAG:
break;
}
}
return NULL;
}
static BClassList *CScope_GetBaseAccessPathEnd(BClassList *list) {
BClassList *best = list;
ClassList *scan;
do {
if (!list->next)
return best;
for (scan = TYPE_CLASS(list->type)->bases; scan; scan = scan->next) {
if (TYPE_CLASS(list->next->type) == scan->base)
break;
}
if (!scan)
best = list->next;
list = list->next;
} while (1);
}
BClassList *CScope_GetClassAccessPath(BClassList *list, TypeClass *tclass) {
BClassList *scan;
BClassList *list2;
if (!list)
return NULL;
list = CScope_GetBaseAccessPathEnd(list);
for (scan = list; scan; scan = scan->next) {
if (scan->type == TYPE(tclass))
return scan;
}
if ((list2 = CScope_GetAccessPath(tclass, TYPE_CLASS(list->type)))) {
for (scan = list2; scan; scan = scan->next) {
if (scan->type == list->type) {
scan->next = list->next;
return list2;
}
}
CError_FATAL(3217);
}
return NULL;
}
static Boolean CScope_FixMemberResult(TypeClass *tclass, CScopeParseResult *result) {
if (!(result->bcl_18 = CScope_GetClassAccessPath(result->bcl_18, tclass))) {
if (result->name_4)
CError_Error(CErrorStr150, result->name_4->name);
else
CError_Error(CErrorStr328);
return 0;
} else {
return 1;
}
}
Boolean CScope_ParseMemberName(TypeClass *tclass, CScopeParseResult *result, Boolean flag) {
HashNameNode *name;
NameSpaceObjectList *list;
short t;
Boolean dtorflag;
if (tk == TK_COLON_COLON) {
restart:
if (!CScope_ParseExprName(result))
return 0;
if (result->x8 && IS_TYPE_TEMPLATE(result->x8) && TYPE_TEMPLATE(result->x8)->dtype == TEMPLDEP_QUALNAME) {
if (flag)
return 1;
CError_Error(CErrorStr340, TYPE_TEMPLATE(result->x8)->u.qual.name->name);
result->x8 = NULL;
return 0;
}
if (result->x1C)
return 1;
else
return CScope_FixMemberResult(tclass, result);
}
if (tk == TK_IDENTIFIER) {
name = tkidentifier;
t = lookahead();
tkidentifier = name;
switch (t) {
case TK_COLON_COLON:
memclrw(result, sizeof(CScopeParseResult));
if (!CScope_FindClassMember(result, tclass->nspace, name, Lookup_2))
goto restart;
break;
case '<':
if (flag)
goto restart;
break;
}
} else if (tk == '~') {
memclrw(result, sizeof(CScopeParseResult));
if (CScope_CheckDtorName(tclass, &dtorflag)) {
if (dtorflag) {
result->x1C = 1;
return 1;
}
if (!(list = CScope_FindQualifiedName(result, tclass->nspace, destructor_name_node, &result->nspace_0))) {
CError_Error(CErrorStr140, CError_GetNameString(result->nspace_0, destructor_name_node));
return 0;
} else {
return CScope_SetupParseNameResult(result, list, destructor_name_node);
}
}
return 0;
}
memclrw(result, sizeof(CScopeParseResult));
return CScope_ParseQualifiedName(result, tclass->nspace);
}
static void CScope_AddUsingObject(BClassList *bcl, NameSpace *nspace, ObjBase *obj, HashNameNode *name, AccessType access) {
NameSpaceObjectList *list;
BClassList *pathcopy;
TypeClass *tclass;
ObjBase *copy;
Object *objscan;
if (bcl) {
if (!nspace->theclass)
CError_Error(CErrorStr200);
else
CClass_CheckPathAccess(bcl, NULL, obj->access);
}
if (obj->otype == OT_TYPE) {
if (!nspace->theclass) {
if ((list = CScope_FindQualName(nspace, name)) && (list->object->otype == OT_TYPE) &&
(OBJ_TYPE(obj)->type == OBJ_TYPE(list->object)->type) &&
(OBJ_TYPE(obj)->qual == OBJ_TYPE(list->object)->qual))
return;
}
copy = galloc(sizeof(ObjType));
*OBJ_TYPE(copy) = *OBJ_TYPE(obj);
copy->access = access;
CScope_AddObject(nspace, name, copy);
} else if (obj->otype == OT_TYPETAG) {
if (!nspace->theclass) {
if ((list = CScope_FindQualName(nspace, name)) && (list->object->otype == OT_TYPETAG) &&
(OBJ_TYPE_TAG(obj)->type == OBJ_TYPE_TAG(list->object)->type))
return;
}
copy = galloc(sizeof(ObjTypeTag));
*OBJ_TYPE_TAG(copy) = *OBJ_TYPE_TAG(obj);
copy->access = access;
CScope_AddObject(nspace, name, copy);
} else if (obj->otype == OT_ENUMCONST) {
copy = galloc(sizeof(ObjEnumConst));
*OBJ_ENUM_CONST(copy) = *OBJ_ENUM_CONST(obj);
copy->access = access;
CScope_AddObject(nspace, OBJ_ENUM_CONST(copy)->name, copy);
} else if (obj->otype == OT_MEMBERVAR) {
if (nspace->theclass) {
copy = galloc(sizeof(ObjMemberVarPath));
*OBJ_MEMBER_VAR(copy) = *OBJ_MEMBER_VAR(obj);
copy->access = access;
pathcopy = CScope_GetClassAccessPath(CClass_GetPathCopy(bcl, 1), nspace->theclass);
if (pathcopy && pathcopy->type == TYPE(nspace->theclass)) {
OBJ_MEMBER_VAR_PATH(copy)->has_path = 1;
OBJ_MEMBER_VAR_PATH(copy)->path = pathcopy;
} else {
CError_Error(CErrorStr221);
}
CScope_AddObject(nspace, OBJ_MEMBER_VAR(copy)->name, copy);
} else {
CError_Error(CErrorStr221);
}
} else if (obj->otype == OT_OBJECT) {
if (!nspace->theclass) {
for (list = CScope_FindQualName(nspace, OBJECT(obj)->name); list; list = list->next) {
if (list->object->otype == OT_OBJECT) {
objscan = OBJECT(list->object);
while (objscan->datatype == DALIAS)
objscan = objscan->u.alias.object;
if (OBJECT(obj) == objscan)
return;
}
}
}
copy = galloc(sizeof(Object));
*OBJECT(copy) = *OBJECT(obj);
copy->access = access;
OBJECT(copy)->datatype = DALIAS;
OBJECT(copy)->u.alias.object = OBJECT(obj);
OBJECT(copy)->u.alias.member = NULL;
OBJECT(copy)->u.alias.offset = 0;
if (IS_TYPE_NONSTATIC_METHOD(OBJECT(copy)->type)) {
if (!(tclass = nspace->theclass) || !(OBJECT(copy)->u.alias.member = CScope_GetClassAccessPath(
CClass_GetPathCopy(bcl, 1), tclass)) || (OBJECT(copy)->u.alias.member->type != TYPE(nspace->theclass))) {
CError_Error(CErrorStr221);
OBJECT(copy)->u.alias.member = NULL;
}
}
CScope_AddObject(nspace, OBJECT(copy)->name, copy);
} else {
CError_Error(CErrorStr200);
}
}
void CScope_AddClassUsingDeclaration(TypeClass *tclass, TypeClass *tclass2, HashNameNode *name, AccessType access) {
CScopeParseResult result;
NameSpaceObjectList *scan;
memclrw(&result, sizeof(CScopeParseResult));
if (!CScope_FindClassMember(&result, tclass2->nspace, name, Lookup_0) || !CScope_FixMemberResult(tclass, &result)) {
CError_Error(CErrorStr340, name->name);
return;
}
if (result.nsol_14) {
for (scan = result.nsol_14; scan; scan = scan->next) {
switch (scan->object->otype) {
case OT_ENUMCONST:
case OT_MEMBERVAR:
case OT_OBJECT:
CScope_AddUsingObject(result.bcl_18, tclass->nspace, scan->object, result.name_4, access);
break;
}
}
} else {
if (result.obj_10)
CScope_AddUsingObject(result.bcl_18, tclass->nspace, result.obj_10, result.name_4, access);
else
CError_Error(CErrorStr340, name->name);
}
}
void CScope_ParseUsingDeclaration(NameSpace *nspace, AccessType access, Boolean flag) {
NameSpace *saveNSpace;
Boolean flag_r27;
Boolean flag_r26;
NameSpaceObjectList *scan;
CScopeParseResult result;
if (nspace->theclass) {
flag_r27 = (TYPE_CLASS(nspace->theclass)->flags & CLASS_FLAGS_100) ? 1 : 0;
flag_r26 = 0;
if (tk == TK_TYPENAME) {
if (!flag_r27)
CError_Error(CErrorStr200);
flag_r26 = 1;
tk = lex();
}
if (!CScope_ParseMemberName(nspace->theclass, &result, flag_r27)) {
CError_Error(CErrorStr200);
return;
}
if (result.x8 && IS_TYPE_TEMPLATE(result.x8) && TYPE_TEMPLATE(result.x8)->dtype == TEMPLDEP_QUALNAME) {
CError_ASSERT(3578, flag_r27);
if (flag_r26) {
ObjType *objtype = galloc(sizeof(ObjType));
memclrw(objtype, sizeof(ObjType));
objtype->otype = OT_TYPE;
objtype->access = access;
objtype->type = result.x8;
CScope_AddObject(nspace, TYPE_TEMPLATE(result.x8)->u.qual.name, OBJ_BASE(objtype));
} else {
CTemplClass_RegisterUsingDecl(
TEMPL_CLASS(nspace->theclass),
TYPE_TEMPLATE(result.x8),
access);
}
if ((tk = lex()) != ';')
CError_Error(CErrorStr123);
return;
}
if (!result.x1D) {
CError_Error(CErrorStr200);
return;
}
} else {
saveNSpace = cscope_current;
cscope_current = nspace;
if (!CScope_ParseExprName(&result) || !result.x1D) {
cscope_current = saveNSpace;
CError_Error(CErrorStr200);
return;
} else {
cscope_current = saveNSpace;
}
}
if (result.nsol_14) {
for (scan = result.nsol_14; scan; scan = scan->next) {
if (scan->object->otype == OT_OBJECT)
CScope_AddUsingObject(result.bcl_18, nspace, scan->object, result.name_4, access);
}
} else {
if (result.obj_10)
CScope_AddUsingObject(result.bcl_18, nspace, result.obj_10, result.name_4, access);
else
CError_Error(CErrorStr200);
}
if ((tk = lex()) != ';')
CError_Error(CErrorStr123);
}
static NameSpace *CScope_ParseQualifiedNamespaceSpecifier(NameSpace *nspace) {
CScopeParseResult result;
CScopeNSIterator iterator;
NameSpaceObjectList *list;
memclrw(&result, sizeof(CScopeParseResult));
if (tk == TK_COLON_COLON) {
nspace = cscope_root;
result.x1D = 1;
tk = lex();
}
do {
if (tk != TK_IDENTIFIER) {
CError_Error(CErrorStr107);
break;
}
CScope_NSIteratorInit(&iterator, nspace, &result);
do {
if ((list = CScope_NSIteratorFind(&iterator, tkidentifier)) && list->object->otype == OT_NAMESPACE) {
nspace = OBJ_NAMESPACE(list->object)->nspace;
goto some_goto;
}
} while (CScope_NSIteratorNext(&iterator));
CError_Error(CErrorStr140, tkidentifier->name);
some_goto:
if ((tk = lex()) != TK_COLON_COLON)
break;
result.x1D = 1;
tk = lex();
} while (1);
return nspace;
}
void CScope_ParseNameSpaceAlias(HashNameNode *name) {
NameSpaceObjectList *list;
ObjNameSpace *objns;
list = CScope_FindQualName(cscope_current, name);
if (!list) {
tk = lex();
objns = galloc(sizeof(ObjNameSpace));
memclrw(objns, sizeof(ObjNameSpace));
objns->otype = OT_NAMESPACE;
objns->access = ACCESSPUBLIC;
objns->nspace = CScope_ParseQualifiedNamespaceSpecifier(cscope_current);
CScope_AddObject(cscope_current, name, OBJ_BASE(objns));
} else if (list->object->otype != OT_NAMESPACE) {
CError_Error(CErrorStr320);
tk = lex();
CScope_ParseQualifiedNamespaceSpecifier(cscope_current);
} else {
tk = lex();
if (CScope_ParseQualifiedNamespaceSpecifier(cscope_current) != OBJ_NAMESPACE(list->object)->nspace)
CError_Error(CErrorStr122, name->name);
}
if (tk != ';')
CError_Error(CErrorStr123);
}
void CScope_ParseUsingDirective(NameSpace *nspace) {
NameSpace *target;
NameSpaceList *list;
target = CScope_ParseQualifiedNamespaceSpecifier(nspace);
if (target != nspace) {
for (list = nspace->usings; list; list = list->next) {
if (list->nspace == target)
break;
}
if (!list) {
list = galloc(sizeof(NameSpaceList));
list->next = nspace->usings;
list->nspace = target;
nspace->usings = list;
}
} else {
CError_Error(CErrorStr321);
}
if (tk != ';')
CError_Error(CErrorStr123);
}