mirror of https://git.wuffs.org/MWCC
2700 lines
88 KiB
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);
|
|
}
|