MWCC/compiler_and_linker/unsorted/CDecl.c

4846 lines
159 KiB
C

#include "compiler/CDecl.h"
#include "compiler/CABI.h"
#include "compiler/CBrowse.h"
#include "compiler/CClass.h"
#include "compiler/CError.h"
#include "compiler/CException.h"
#include "compiler/CExpr.h"
#include "compiler/CFunc.h"
#include "compiler/CInit.h"
#include "compiler/CInline.h"
#include "compiler/CInt64.h"
#include "compiler/CMachine.h"
#include "compiler/CMangler.h"
#include "compiler/CObjC.h"
#include "compiler/CParser.h"
#include "compiler/CPrep.h"
#include "compiler/CPrepTokenizer.h"
#include "compiler/CSOM.h"
#include "compiler/CTemplateClass.h"
#include "compiler/CTemplateFunc.h"
#include "compiler/CTemplateNew.h"
#include "compiler/CTemplateTools.h"
#include "compiler/CompilerTools.h"
#include "compiler/objects.h"
#include "compiler/scopes.h"
#include "compiler/templates.h"
#include "compiler/tokens.h"
AccessType global_access;
FileOffsetInfo member_fileoffset;
// forward declarations
static void scandirectdecl1(DeclInfo *declinfo);
Type *CDecl_NewStructType(SInt32 size, SInt16 align) {
TypeStruct *tstruct = galloc(sizeof(TypeStruct));
memclrw(tstruct, sizeof(TypeStruct));
tstruct->type = TYPESTRUCT;
tstruct->size = size;
tstruct->align = align;
tstruct->stype = STRUCT_TYPE_STRUCT;
return (Type *) tstruct;
}
Type *CDecl_NewArrayType(Type *type, SInt32 size) {
TypePointer *tarray = galloc(sizeof(TypePointer));
memclrw(tarray, sizeof(TypePointer));
tarray->type = TYPEARRAY;
tarray->size = size;
tarray->target = type;
tarray->qual = 0;
return (Type *) tarray;
}
Type *CDecl_NewPointerType(Type *type) {
TypePointer *tptr = galloc(sizeof(TypePointer));
memclrw(tptr, sizeof(TypePointer));
tptr->type = TYPEPOINTER;
tptr->size = 4;
tptr->target = type;
return (Type *) tptr;
}
Type *CDecl_NewRefPointerType(Type *type) {
TypePointer *tptr = galloc(sizeof(TypePointer));
memclrw(tptr, sizeof(TypePointer));
tptr->type = TYPEPOINTER;
tptr->size = 4;
tptr->target = type;
tptr->qual = Q_REFERENCE;
return (Type *) tptr;
}
Type *CDecl_NewTemplDepType(TypeTemplDepType tdt) {
TypeTemplDep *t = galloc(sizeof(TypeTemplDep));
memclrw(t, sizeof(TypeTemplDep));
t->type = TYPETEMPLATE;
t->size = 1;
t->dtype = tdt;
return (Type *) t;
}
void CDecl_SetResultReg(TypeFunc *tfunc) {
}
static void CDecl_SetFuncResultReg(TypeFunc *tfunc) {
}
void CDecl_SetFuncFlags(TypeFunc *tfunc, UInt32 flags) {
CDecl_SetResultReg(tfunc);
}
static void CDecl_ParseCPPFuncDecl(TypeFunc *tfunc) {
for (;;) {
if (tk == TK_CONST) {
if (tfunc->flags & FUNC_FLAGS_CONST)
CError_Warning(CErrorStr313, "const");
tfunc->flags |= FUNC_FLAGS_CONST;
tk = lex();
} else if (tk == TK_VOLATILE) {
if (tfunc->flags & FUNC_FLAGS_VOLATILE)
CError_Warning(CErrorStr313, "volatile");
tfunc->flags |= FUNC_FLAGS_VOLATILE;
tk = lex();
} else {
break;
}
}
if (tk == TK_THROW)
CExcept_ScanExceptionSpecification(tfunc);
}
void CDecl_NewConvFuncType(DeclInfo *declinfo) {
TypeFunc *tfunc;
if (tk != '(')
CError_Error(CErrorStr114);
else
tk = lex();
if (tk == TK_VOID)
tk = lex();
if (tk != ')')
CError_Error(CErrorStr115);
else
tk = lex();
tfunc = galloc(sizeof(TypeFunc));
memclrw(tfunc, sizeof(TypeFunc));
declinfo->name = CMangler_ConversionFuncName(declinfo->thetype, declinfo->qual);
tfunc->type = TYPEFUNC;
tfunc->functype = declinfo->thetype;
tfunc->qual = declinfo->qual & (Q_CONST | Q_VOLATILE);
tfunc->flags = FUNC_FLAGS_40;
declinfo->x49 = 0;
CDecl_SetFuncFlags(tfunc, 1);
CDecl_ParseCPPFuncDecl(tfunc);
declinfo->thetype = (Type *) tfunc;
declinfo->qual &= ~(Q_CONST | Q_VOLATILE);
declinfo->storageclass = 0;
}
void CDecl_CompleteType(Type *type) {
switch (type->type) {
case TYPEPOINTER:
if ((TYPE_POINTER(type)->qual & Q_REFERENCE) && IS_TYPE_CLASS(TYPE_POINTER(type)->target)) {
type = TYPE_POINTER(type)->target;
break;
}
return;
case TYPEARRAY:
do {
type = TYPE_POINTER(type)->target;
} while (IS_TYPE_ARRAY(type));
if (IS_TYPE_CLASS(type))
break;
return;
case TYPECLASS:
break;
default:
return;
}
if ((TYPE_CLASS(type)->flags & (CLASS_FLAGS_2 | CLASS_FLAGS_800)) == CLASS_FLAGS_800)
CTempl_InstantiateTemplateClass(TYPE_CLASS(type));
}
Boolean IsCompleteType(Type *type) {
switch (type->type) {
case TYPEVOID:
CError_Error(CErrorStr126);
return 0;
case TYPEFUNC:
CError_Error(CErrorStr146);
return 0;
case TYPESTRUCT:
if (!type->size) {
CError_Error(CErrorStr136, type, 0);
return 0;
}
return 1;
case TYPECLASS:
if (
!(TYPE_CLASS(type)->flags & CLASS_FLAGS_2) &&
(
!(TYPE_CLASS(type)->flags & CLASS_FLAGS_800) ||
!CTempl_InstantiateTemplateClass(TYPE_CLASS(type))
)
)
{
CError_Error(CErrorStr136, type, 0);
return 0;
}
return 1;
default:
if (!type->size) {
CError_Error(CErrorStr145);
return 0;
}
return 1;
}
}
Boolean CanAllocObject(Type *type) {
switch (type->type) {
case TYPEVOID:
CError_Error(CErrorStr126);
return 0;
case TYPEFUNC:
CError_Error(CErrorStr146);
return 0;
case TYPECLASS:
if (TYPE_CLASS(type)->flags & CLASS_FLAGS_ABSTRACT) {
CError_AbstractClassError(TYPE_CLASS(type));
return 0;
}
default:
return 1;
}
}
Boolean CanCreateObject(Type *type) {
if (!CanAllocObject(type))
return 0;
if (IS_TYPE_CLASS(type)) {
if (TYPE_CLASS(type)->flags & CLASS_FLAGS_1) {
CError_Error(CErrorStr191);
return 0;
}
if (TYPE_CLASS(type)->objcinfo) {
CError_Error(CErrorStr307);
return 0;
}
}
return 1;
}
static Boolean CanCreateHandleMemberObject(Type *type) {
while (IS_TYPE_ARRAY(type))
type = TYPE_POINTER(type)->target;
if (!CanCreateObject(type))
return 0;
if (IS_TYPE_CLASS(type)) {
if (CClass_Destructor(TYPE_CLASS(type)) || CClass_Constructor(TYPE_CLASS(type))) {
CError_Error(CErrorStr191);
return 0;
}
}
return 1;
}
void makethetypepointer(DeclInfo *declinfo, UInt32 qual) {
declinfo->thetype = CDecl_NewPointerType(declinfo->thetype);
TYPE_POINTER(declinfo->thetype)->qual = qual;
}
void CDecl_AddThisPointerArgument(TypeFunc *tfunc, TypeClass *tclass) {
Type *ptype;
FuncArg *arg;
ptype = CDecl_NewPointerType(!tclass->sominfo ? (Type *) tclass : &stvoid);
TYPE_POINTER(ptype)->qual = Q_CONST;
arg = CParser_NewFuncArg();
arg->name = this_name_node;
arg->type = ptype;
if (tfunc->flags & FUNC_FLAGS_CONST)
arg->qual |= Q_CONST;
if (tfunc->flags & FUNC_FLAGS_VOLATILE)
arg->qual |= Q_VOLATILE;
arg->next = tfunc->args;
tfunc->args = arg;
}
void CDecl_MakePTMFuncType(TypeFunc *tfunc) {
Type *cvoidp;
FuncArg *arg1;
FuncArg *arg2;
cvoidp = CDecl_NewPointerType(&stvoid);
TYPE_POINTER(cvoidp)->qual = Q_CONST;
arg1 = CParser_NewFuncArg();
arg1->name = this_name_node;
arg1->type = cvoidp;
if (tfunc->flags & FUNC_FLAGS_CONST)
arg1->qual |= Q_CONST;
if (tfunc->flags & FUNC_FLAGS_VOLATILE)
arg1->qual |= Q_VOLATILE;
arg2 = CParser_NewFuncArg();
arg2->name = this_name_node;
arg2->type = cvoidp;
arg2->qual = Q_CONST;
arg1->next = tfunc->args;
arg2->next = arg1;
tfunc->args = arg2;
tfunc->flags |= FUNC_FLAGS_80;
}
void CDecl_AddArgument(TypeFunc *tfunc, Type *argtype) {
FuncArg *arg = CParser_NewFuncArg();
arg->type = argtype;
arg->next = tfunc->args;
tfunc->args = arg;
if (arg->next && arg->next->type == &stvoid)
arg->next = NULL;
}
Boolean CDecl_CheckArrayIntegr(Type *type) {
if (!IsCompleteType(type))
return 0;
if (IS_TYPE_CLASS(type) && TYPE_CLASS(type)->sominfo) {
CError_Error(CErrorStr289);
return 0;
}
if (IS_TYPE_REFERENCE(type)) {
CError_Error(CErrorStr196);
return 0;
}
return CanCreateObject(type);
}
static Boolean checkfuncintegr(Type *type) {
if (IS_TYPE_VOID(type))
return 1;
if (IS_TYPE_CLASS(type) && TYPE_CLASS(type)->sominfo) {
CError_Error(CErrorStr283);
return 0;
}
return CanCreateObject(type);
}
void CDecl_ParseDirectFuncDecl(DeclInfo *declinfo) {
FuncArg *list;
TypeFunc *tfunc;
if (tk == ')') {
if (copts.cplusplus)
list = NULL;
else
list = &oldstyle;
tk = lex();
} else {
list = parameter_type_list(declinfo);
if (tk != ')')
CError_ErrorSkip(CErrorStr115);
else
tk = lex();
}
tfunc = galloc(sizeof(TypeFunc));
memclrw(tfunc, sizeof(TypeFunc));
tfunc->type = TYPEFUNC;
tfunc->args = list;
if (declinfo->qual & Q_PASCAL) {
declinfo->qual &= ~Q_PASCAL;
tfunc->flags = FUNC_FLAGS_PASCAL;
}
if (copts.cplusplus) {
CDecl_ParseCPPFuncDecl(tfunc);
if (declinfo->storageclass == TK_TYPEDEF && tfunc->exspecs)
CError_Error(CErrorStr264);
}
scandirectdecl1(declinfo);
if (!checkfuncintegr(declinfo->thetype))
declinfo->thetype = &stvoid;
tfunc->functype = declinfo->thetype;
tfunc->qual = declinfo->qual & (Q_CONST | Q_VOLATILE);
declinfo->thetype = (Type *) tfunc;
declinfo->qual &= ~(Q_CONST | Q_VOLATILE);
declinfo->x49 = 0;
}
static void scandirectdecl1(DeclInfo *declinfo) {
Boolean flag;
CInt64 len;
ENode *expr;
TypeTemplDep *ttempl;
flag = 0;
if (tk == '[') {
if ((tk = lex()) == ']') {
len = cint64_zero;
tk = lex();
flag = 1;
} else {
if (!declinfo->x46 || declinfo->x47) {
expr = CExpr_IntegralConstOrDepExpr();
if (!ENODE_IS(expr, EINTCONST)) {
if (tk != ']')
CError_ErrorSkip(CErrorStr125);
else
tk = lex();
declinfo->x47 = 1;
scandirectdecl1(declinfo);
if (!CDecl_CheckArrayIntegr(declinfo->thetype))
declinfo->thetype = (Type *) &stsignedchar;
ttempl = (TypeTemplDep *) CDecl_NewTemplDepType(TEMPLDEP_ARRAY);
ttempl->u.array.type = declinfo->thetype;
ttempl->u.array.index = CInline_CopyExpression(expr, CopyMode1);
declinfo->thetype = (Type *) ttempl;
return;
}
len = expr->data.intval;
if (CInt64_IsNegative(&len)) {
CError_Error(CErrorStr124);
len = cint64_one;
} else if (CInt64_IsZero(&len)) {
if (!copts.ANSIstrict && declinfo->x50) {
flag = 1;
} else {
CError_Error(CErrorStr124);
len = cint64_one;
}
}
} else {
len = cint64_one;
expr = expression();
if (IS_TYPE_INT(expr->rtype)) {
if (!ENODE_IS(expr, EINTCONST))
declinfo->x24 = expr;
else
len = expr->data.intval;
} else {
CError_Error(CErrorStr124);
}
}
if (tk != ']')
CError_ErrorSkip(CErrorStr125);
else
tk = lex();
}
declinfo->x47 = 1;
scandirectdecl1(declinfo);
if (!flag && !CDecl_CheckArrayIntegr(declinfo->thetype))
declinfo->thetype = (Type *) &stsignedchar;
if (!declinfo->thetype->size && CTemplTool_IsTemplateArgumentDependentType(declinfo->thetype)) {
ttempl = (TypeTemplDep *) CDecl_NewTemplDepType(TEMPLDEP_ARRAY);
ttempl->u.array.type = declinfo->thetype;
ttempl->u.array.index = CInline_CopyExpression(intconstnode((Type *) &stsignedint, CInt64_GetULong(&len)), CopyMode1);
declinfo->thetype = (Type *) ttempl;
} else {
declinfo->thetype = CDecl_NewArrayType(declinfo->thetype, declinfo->thetype->size * CInt64_GetULong(&len));
}
} else if (tk == '(') {
if (!copts.cplusplus || !declinfo->name || IS_TYPE_VOID(declinfo->thetype) || CParser_TryParamList(!IS_TYPE_CLASS(declinfo->thetype))) {
tk = lex();
CDecl_ParseDirectFuncDecl(declinfo);
}
}
}
static void substitute_type(Type *type1, Type *type2) {
SInt32 oldsize;
while (1) {
switch (type1->type) {
case TYPEPOINTER:
if (TYPE_POINTER(type1)->target == &stillegal) {
TYPE_POINTER(type1)->target = type2;
type1->size = 4;
return;
}
type1 = TYPE_POINTER(type1)->target;
break;
case TYPEMEMBERPOINTER:
if (TYPE_MEMBER_POINTER(type1)->ty1 == &stillegal) {
TYPE_MEMBER_POINTER(type1)->ty1 = type2;
if (IS_TYPE_FUNC(type2)) {
CDecl_MakePTMFuncType(TYPE_FUNC(type2));
type1->size = 12;
} else {
type1->size = 4;
}
return;
}
type1 = TYPE_MEMBER_POINTER(type1)->ty1;
break;
case TYPEARRAY:
if (TYPE_POINTER(type1)->target == &stillegal) {
if (!CDecl_CheckArrayIntegr(type2))
type2 = (Type *) &stsignedchar;
type1->size *= type2->size;
TYPE_POINTER(type1)->target = type2;
return;
}
oldsize = TYPE_POINTER(type1)->target->size;
substitute_type(TYPE_POINTER(type1)->target, type2);
if (oldsize != TYPE_POINTER(type1)->target->size && oldsize != 0)
type1->size = TYPE_POINTER(type1)->target->size * (type1->size / oldsize);
return;
case TYPEFUNC:
if (TYPE_FUNC(type1)->functype == &stillegal) {
if (!checkfuncintegr(type2))
type2 = &stvoid;
TYPE_FUNC(type1)->functype = type2;
CDecl_SetFuncResultReg((TypeFunc *) type1);
return;
}
type1 = TYPE_FUNC(type1)->functype;
break;
case TYPETEMPLATE:
if (TYPE_TEMPLATE(type1)->dtype == TEMPLDEP_ARRAY) {
if (TYPE_TEMPLATE(type1)->u.array.type == &stillegal) {
if (!CDecl_CheckArrayIntegr(type2))
type2 = (Type *) &stsignedchar;
TYPE_TEMPLATE(type1)->u.array.type = type2;
return;
}
type1 = TYPE_TEMPLATE(type1)->u.array.type;
} else {
CError_Error(CErrorStr146);
return;
}
break;
default:
CError_Error(CErrorStr121);
return;
}
}
}
static void scandecl(DeclInfo *declinfo) {
Type *oldtype;
Type *newtype;
oldtype = declinfo->thetype;
declinfo->thetype = &stillegal;
scandeclarator(declinfo);
if (tk != ')')
CError_ErrorSkip(CErrorStr115);
else
tk = lex();
newtype = declinfo->thetype;
if (newtype == &stillegal) {
declinfo->thetype = oldtype;
scandirectdecl1(declinfo);
} else {
declinfo->thetype = oldtype;
scandirectdecl1(declinfo);
substitute_type(newtype, declinfo->thetype);
declinfo->thetype = newtype;
}
}
static Boolean CDecl_ParseOperatorDecl(DeclInfo *declinfo) {
if (declinfo->x3E) {
CError_Error(CErrorStr121);
return 0;
}
declinfo->x3E = 0;
if (!CParser_ParseOperatorName(&declinfo->x3E, declinfo->x4A && cscope_current->theclass, 0))
return 0;
if (!declinfo->x3E) {
conversion_type_name(declinfo);
tkidentifier = CMangler_ConversionFuncName(declinfo->thetype, declinfo->qual);
declinfo->x54 = 1;
}
return 1;
}
static Boolean CDecl_IsEnumClassTypeOrRef(Type *type) {
if (IS_TYPE_CLASS(type) || IS_TYPE_ENUM(type))
return 1;
if (!IS_TYPE_REFERENCE(type))
return 0;
type = TYPE_POINTER(type)->target;
return IS_TYPE_CLASS(type) || IS_TYPE_ENUM(type);
}
typedef enum OpMysteryValue {
OpMysteryValue0 = 0,
OpMysteryValue1 = 1,
OpMysteryValue2 = 2,
OpMysteryValue3 = 3,
OpMysteryValue4 = 4
} OpMysteryValue;
static Boolean CDecl_CheckOperatorType(DeclInfo *declinfo, Boolean flag) {
FuncArg *args;
FuncArg *secondarg;
Type *functype;
short r27;
Boolean r6;
if (!IS_TYPE_FUNC(declinfo->thetype)) {
CError_Error(CErrorStr193);
return 0;
}
functype = TYPE_FUNC(declinfo->thetype)->functype;
args = TYPE_FUNC(declinfo->thetype)->args;
if (args) {
if (args != &elipsis && args != &oldstyle) {
r27 = OpMysteryValue1;
if (args->dexpr) {
switch (declinfo->x3E) {
case TK_NEW:
case TK_DELETE:
case TK_NEW_ARRAY:
case TK_DELETE_ARRAY:
break;
default:
CError_Error(CErrorStr205);
}
}
secondarg = args->next;
if (secondarg) {
//r27 = ((secondarg != &elipsis && !secondarg->next) != 0) ? OpMysteryValue2 : OpMysteryValue3;
if ((secondarg != &elipsis && !secondarg->next) != 0)
r27 = OpMysteryValue2;
else
r27 = OpMysteryValue3;
if (secondarg->dexpr) {
switch (declinfo->x3E) {
case '(':
case TK_NEW:
case TK_DELETE:
case TK_NEW_ARRAY:
case TK_DELETE_ARRAY:
break;
default:
CError_Error(CErrorStr205);
}
}
}
} else {
r27 = OpMysteryValue3;
}
} else {
CError_Error(CErrorStr193);
return 0;
}
r6 = flag && IS_TYPEFUNC_METHOD(TYPE_FUNC(declinfo->thetype)) && !TYPE_METHOD(declinfo->thetype)->x26;
switch (declinfo->x3E) {
case TK_NEW:
case TK_NEW_ARRAY:
if (r6 || !is_typesame(functype, (Type *) &void_ptr) || r27 < OpMysteryValue1 || args->type != CABI_GetSizeTType()) {
CError_Error(CErrorStr193);
return 0;
}
return 1;
case TK_DELETE:
case TK_DELETE_ARRAY:
if (r6 || !IS_TYPE_VOID(functype) || r27 < OpMysteryValue1 || !is_typesame(args->type, (Type *) &void_ptr)) {
CError_Error(CErrorStr193);
return 0;
}
return 1;
case '=':
if (!r6) {
CError_Error(CErrorStr193);
return 0;
}
break;
case '(':
if (!r6) {
CError_Error(CErrorStr193);
return 0;
}
return 1;
case '[':
if (!r6) {
CError_Error(CErrorStr193);
return 0;
}
break;
case TK_ARROW:
if (r27 != OpMysteryValue1 || r6 == 0) {
CError_Error(CErrorStr193);
return 0;
}
return 1;
case TK_INCREMENT:
case TK_DECREMENT:
if (r27 == OpMysteryValue2 && secondarg->type != (Type *) &stsignedint) {
CError_Error(CErrorStr193);
return 0;
}
break;
}
if (flag && !r6) {
CError_Error(CErrorStr193);
return 0;
}
switch (declinfo->x3E) {
case '&':
case '*':
case '+':
case '-':
case TK_INCREMENT:
case TK_DECREMENT:
if (r27 != OpMysteryValue1)
goto whatever;
case '!':
case '~':
if (r27 == OpMysteryValue1) {
if (flag || CDecl_IsEnumClassTypeOrRef(args->type))
return 1;
}
break;
case '%':
case ',':
case '/':
case '<':
case '=':
case '>':
case '[':
case '^':
case '|':
case TK_MULT_ASSIGN:
case TK_DIV_ASSIGN:
case TK_MOD_ASSIGN:
case TK_ADD_ASSIGN:
case TK_SUB_ASSIGN:
case TK_SHL_ASSIGN:
case TK_SHR_ASSIGN:
case TK_AND_ASSIGN:
case TK_XOR_ASSIGN:
case TK_OR_ASSIGN:
case TK_LOGICAL_OR:
case TK_LOGICAL_AND:
case TK_LOGICAL_EQ:
case TK_LOGICAL_NE:
case TK_LESS_EQUAL:
case TK_GREATER_EQUAL:
case TK_SHL:
case TK_SHR:
case TK_ARROW:
case TK_DOT_STAR:
case TK_ARROW_STAR:
whatever:
if (r27 == OpMysteryValue2) {
if (flag || CDecl_IsEnumClassTypeOrRef(args->type) || CDecl_IsEnumClassTypeOrRef(secondarg->type))
return 1;
}
break;
}
CError_Error(CErrorStr193);
return 0;
}
static void scandirectdeclarator(DeclInfo *declinfo, NameSpace *nspace) {
HashNameNode *saveident;
CScopeSave scopesave;
Boolean flag;
if (nspace)
CScope_SetNameSpaceScope(nspace, &scopesave);
if (tk == '(') {
if ((tk = lex()) == ')') {
if (declinfo->x55) {
CDecl_ParseDirectFuncDecl(declinfo);
if (nspace)
CScope_RestoreScope(&scopesave);
return;
} else {
CError_Error(CErrorStr121);
if (nspace)
CScope_RestoreScope(&scopesave);
return;
}
}
if (!(tk >= TK_AUTO && tk <= TK_BYREF)) {
if (!(tk == TK_IDENTIFIER && CScope_PossibleTypeName(tkidentifier))) {
scandecl(declinfo);
if (nspace)
CScope_RestoreScope(&scopesave);
return;
} else {
saveident = tkidentifier;
switch (lookahead()) {
case ')':
case ',':
break;
default:
tkidentifier = saveident;
scandecl(declinfo);
if (nspace)
CScope_RestoreScope(&scopesave);
return;
}
}
}
if (declinfo->name)
CError_Error(CErrorStr121);
CDecl_ParseDirectFuncDecl(declinfo);
if (nspace)
CScope_RestoreScope(&scopesave);
return;
}
if (nspace) {
if (tk == TK_OPERATOR) {
if (!CDecl_ParseOperatorDecl(declinfo)) {
CScope_RestoreScope(&scopesave);
return;
}
if (declinfo->x54) {
declinfo->nspace = nspace;
declinfo->name = tkidentifier;
if (nspace)
CScope_RestoreScope(&scopesave);
if (tk == '(') {
tk = lex();
CDecl_ParseDirectFuncDecl(declinfo);
if (IS_TYPE_FUNC(declinfo->thetype))
TYPE_FUNC(declinfo->thetype)->flags |= FUNC_FLAGS_40;
else
CError_Error(CErrorStr121);
} else {
CError_Error(CErrorStr114);
}
return;
}
flag = 1;
} else if (tk != TK_IDENTIFIER) {
CError_Error(CErrorStr107);
CScope_RestoreScope(&scopesave);
return;
} else {
flag = 0;
}
if (declinfo->name) {
CError_Error(CErrorStr121);
CScope_RestoreScope(&scopesave);
return;
}
declinfo->nspace = nspace;
declinfo->name = tkidentifier;
if (!flag)
tk = lex();
} else if (tk == TK_IDENTIFIER) {
if (declinfo->name)
CError_Error(CErrorStr121);
declinfo->name = tkidentifier;
tk = lex();
} else if (tk == TK_OPERATOR) {
if (!CDecl_ParseOperatorDecl(declinfo))
return;
declinfo->name = tkidentifier;
}
if (tk == '<' && declinfo->x51) {
declinfo->expltargs = CTempl_ParseUncheckTemplArgs(NULL, 0);
declinfo->has_expltargs = 1;
declinfo->x51 = 0;
tk = lex();
}
scandirectdecl1(declinfo);
if (nspace)
CScope_RestoreScope(&scopesave);
}
void makememberpointertype(DeclInfo *declinfo, TypeClass *tclass, UInt32 qual) {
TypeMemberPointer *tmemp;
TypeFunc *tfunc;
if (tclass->flags & CLASS_FLAGS_1) {
CError_Error(CErrorStr191);
declinfo->thetype = (Type *) &stsignedint;
return;
}
if (tclass->sominfo) {
CError_Error(CErrorStr290);
declinfo->thetype = (Type *) &stsignedint;
return;
}
tmemp = galloc(sizeof(TypeMemberPointer));
memclrw(tmemp, sizeof(TypeMemberPointer));
tmemp->type = TYPEMEMBERPOINTER;
tmemp->ty2 = (Type *) tclass;
tmemp->qual = qual;
if (IS_TYPE_FUNC(declinfo->thetype)) {
tfunc = galloc(sizeof(TypeFunc));
*tfunc = *TYPE_FUNC(declinfo->thetype);
tmemp->ty1 = (Type *) tfunc;
tmemp->size = 12;
CDecl_MakePTMFuncType(tfunc);
} else {
tmemp->size = 4;
tmemp->ty1 = declinfo->thetype;
}
declinfo->thetype = (Type *) tmemp;
}
void CDecl_ScanPointer(DeclInfo *declinfo, NameSpace *nspace, Boolean flag) {
CScopeParseResult pr;
UInt32 qual;
while (1) {
qual = (tk == '&') ? Q_REFERENCE : 0;
for (tk = lex(); ; tk = lex()) {
switch (tk) {
case TK_CONST:
if (qual & Q_CONST)
CError_Error(CErrorStr121);
qual |= Q_CONST;
continue;
case TK_VOLATILE:
if (qual & Q_VOLATILE)
CError_Error(CErrorStr121);
qual |= Q_VOLATILE;
continue;
case TK_RESTRICT:
if (qual & Q_RESTRICT)
CError_Error(CErrorStr121);
qual |= Q_RESTRICT;
continue;
default:
break;
}
break;
}
if (IS_TYPE_REFERENCE(declinfo->thetype) || ((qual & Q_REFERENCE) && IS_TYPE_VOID(declinfo->thetype))) {
CError_Error(CErrorStr196);
return;
}
if (nspace) {
makememberpointertype(declinfo, nspace->theclass, qual);
nspace = NULL;
} else {
makethetypepointer(declinfo, qual);
}
switch (tk) {
case '*':
continue;
case '&':
if (!copts.cplusplus) {
if (flag)
scandirectdeclarator(declinfo, NULL);
return;
}
continue;
case TK_IDENTIFIER:
if (!copts.cplusplus)
break;
if (copts.cpp_extensions && cscope_current->theclass && cscope_current->theclass->classname == tkidentifier && lookahead() == TK_COLON_COLON) {
tk = lex();
tk = lex();
break;
}
case TK_COLON_COLON:
if (CScope_ParseQualifiedNameSpace(&pr, 1, 0)) {
if ((nspace = pr.nspace_0)) {
if (nspace->theclass && tk == '*')
continue;
} else {
if (pr.x8 && IS_TYPE_TEMPLATE(pr.x8) && declinfo->x30) {
if (CTempl_IsQualifiedMember(declinfo, pr.x8, &nspace))
scandirectdeclarator(declinfo, nspace);
else
declinfo->x20 = pr.x8;
return;
}
CError_Error(CErrorStr121);
}
}
break;
}
break;
}
if (flag)
scandirectdeclarator(declinfo, nspace);
}
static void CDecl_TemplatePTM(DeclInfo *declinfo, Type *type) {
TypeMemberPointer *tmemp = galloc(sizeof(TypeMemberPointer));
tmemp->type = TYPEMEMBERPOINTER;
if (IS_TYPE_FUNC(declinfo->thetype)) {
CDecl_MakePTMFuncType((TypeFunc *) declinfo->thetype);
tmemp->size = 12;
} else {
tmemp->size = 4;
}
tmemp->ty1 = declinfo->thetype;
tmemp->ty2 = type;
tmemp->qual = 0;
declinfo->thetype = (Type *) tmemp;
}
void scandeclarator(DeclInfo *declinfo) {
CScopeParseResult pr;
NameSpace *nspace;
switch (tk) {
case '&':
if (!copts.cplusplus)
break;
case '*':
CDecl_ScanPointer(declinfo, NULL, 1);
if (tk == TK_UU_ATTRIBUTE_UU)
CParser_ParseAttribute(NULL, declinfo);
return;
case TK_IDENTIFIER:
if (!copts.cplusplus)
break;
case TK_COLON_COLON:
if (CScope_ParseQualifiedNameSpace(&pr, 1, 0)) {
nspace = pr.nspace_0;
if (nspace) {
if (nspace->theclass && tk == '*')
CDecl_ScanPointer(declinfo, nspace, 1);
else
scandirectdeclarator(declinfo, nspace);
return;
}
if (pr.x8 && IS_TYPE_TEMPLATE(pr.x8)) {
if (declinfo->x30 && CTempl_IsQualifiedMember(declinfo, pr.x8, &nspace)) {
scandirectdeclarator(declinfo, nspace);
return;
} else if (declinfo->x30 && tk == TK_OPERATOR) {
declinfo->x20 = pr.x8;
return;
} else if ((tk = lex()) == TK_COLON_COLON && (tk = lex()) == '*') {
CDecl_TemplatePTM(declinfo, pr.x8);
tk = lex();
break;
} else if (declinfo->x30) {
declinfo->x20 = pr.x8;
return;
}
}
CError_Error(CErrorStr121);
}
break;
}
scandirectdeclarator(declinfo, NULL);
if (tk == TK_UU_ATTRIBUTE_UU)
CParser_ParseAttribute(NULL, declinfo);
}
void conversion_type_name(DeclInfo *declinfo) {
CScopeParseResult pr;
DeclInfo subdeclinfo;
memclrw(&subdeclinfo, sizeof(DeclInfo));
CParser_GetDeclSpecs(&subdeclinfo, 0);
switch (tk) {
case '&':
case '*':
CDecl_ScanPointer(&subdeclinfo, NULL, 0);
break;
case TK_IDENTIFIER:
case TK_COLON_COLON:
if (CScope_ParseQualifiedNameSpace(&pr, 0, 0)) {
if (pr.nspace_0 && pr.nspace_0->theclass && tk == '*')
CDecl_ScanPointer(&subdeclinfo, pr.nspace_0, 0);
else
CError_Error(CErrorStr121);
}
break;
}
declinfo->name = subdeclinfo.name;
declinfo->thetype = subdeclinfo.thetype;
declinfo->qual |= subdeclinfo.qual;
}
static void scaninlinefunc(Object *obj) {
short array[256];
short r29;
CInt64 val;
if (tk == '{') {
tk = lex();
r29 = 0;
while (1) {
if (r29 >= 256) {
CError_Error(CErrorStr127);
r29 = 255;
}
val = CExpr_IntegralConstExpr();
array[r29++] = CInt64_GetULong(&val);
if (tk != '}') {
if (tk != ',')
CError_Error(CErrorStr116);
tk = lex();
} else {
tk = lex();
break;
}
}
} else {
val = CExpr_IntegralConstExpr();
array[0] = CInt64_GetULong(&val);
r29 = 1;
}
obj->datatype = DINLINEFUNC;
obj->u.ifunc.size = r29 * 2;
obj->u.ifunc.data = galloc(obj->u.ifunc.size);
obj->u.ifunc.xrefs = NULL;
memcpy(obj->u.ifunc.data, array, obj->u.ifunc.size);
if (tk != ';')
CError_Error(CErrorStr123);
}
typedef enum {
OverloadMode0,
OverloadMode1,
OverloadMode2,
OverloadMode3
} OverloadMode;
static Object *CDecl_OverloadFunctionObject(NameSpaceObjectList *list, DeclInfo *declinfo, Boolean *outflag, OverloadMode mode, Boolean flag2) {
TypeFunc *scanfunc;
NameSpaceObjectList *scan;
TypeFunc *tfunc;
FuncArg *args;
FuncArg *scanargs;
Object *obj;
Boolean r24;
short compareresult;
if (outflag)
*outflag = 0;
tfunc = (TypeFunc *) declinfo->thetype;
args = tfunc->args;
r24 = 0;
for (scan = list; scan; scan = scan->next) {
obj = OBJECT(scan->object);
if (obj->otype != OT_OBJECT)
continue;
scanfunc = TYPE_FUNC(obj->type);
if (!IS_TYPE_FUNC(scanfunc))
continue;
scanargs = scanfunc->args;
if (scanfunc->flags & FUNC_FLAGS_100000)
r24 = 1;
if (IS_TYPEFUNC_METHOD(scanfunc)) {
switch (mode) {
case OverloadMode0:
CError_Error(CErrorStr197);
break;
case OverloadMode1:
if (!TYPE_METHOD(scanfunc)->x26)
continue;
break;
case OverloadMode2:
if (TYPE_METHOD(scanfunc)->x26)
continue;
break;
case OverloadMode3:
if (!TYPE_METHOD(scanfunc)->x26) {
if (scanargs->qual & (Q_CONST | Q_VOLATILE))
continue;
scanargs = scanargs->next;
}
break;
}
} else {
if (mode)
CError_Error(CErrorStr197);
}
compareresult = CParser_CompareArgLists(args, scanargs);
if (compareresult == 1) {
if (scanfunc->flags & FUNC_FLAGS_40) {
if (!(tfunc->flags & FUNC_FLAGS_40)) {
CError_Error(CErrorStr197);
break;
}
if (!is_typesame(tfunc->functype, scanfunc->functype))
continue;
if ((tfunc->qual & (Q_CONST | Q_PASCAL)) != (scanfunc->qual & (Q_CONST | Q_PASCAL)))
continue;
if ((tfunc->flags & (FUNC_FLAGS_F0000000 | FUNC_FLAGS_PASCAL)) != (scanfunc->flags & (FUNC_FLAGS_F0000000 | FUNC_FLAGS_PASCAL))) {
CError_Error(CErrorStr197);
break;
}
if (tfunc->exspecs || scanfunc->exspecs)
CExcept_CompareSpecifications(tfunc->exspecs, scanfunc->exspecs);
return obj;
}
if (tfunc->flags & FUNC_FLAGS_40) {
CError_Error(CErrorStr197);
break;
}
if (!is_typesame(tfunc->functype, scanfunc->functype) || ((tfunc->qual & (Q_CONST | Q_PASCAL)) != (scanfunc->qual & (Q_CONST | Q_PASCAL))) || ((tfunc->flags & (FUNC_FLAGS_F0000000 | FUNC_FLAGS_PASCAL)) != (scanfunc->flags & (FUNC_FLAGS_F0000000 | FUNC_FLAGS_PASCAL)))) {
CError_Error(CErrorStr197);
break;
}
if (tfunc->exspecs || scanfunc->exspecs) {
if (obj->name != newp_fobj->name && obj->name != newa_fobj->name && obj->name != delp_fobj->name && obj->name != dela_fobj->name)
CExcept_CompareSpecifications(tfunc->exspecs, scanfunc->exspecs);
}
return obj;
} else if (compareresult == 2) {
CError_Error(CErrorStr197);
break;
}
}
if (r24 && (flag2 || declinfo->x3C)) {
if ((obj = CTempl_TemplateFunctionCheck(declinfo, list)))
return obj;
}
if (!outflag) {
CError_Error(CErrorStr197);
return NULL;
}
if (declinfo->nspace)
CError_Error(CErrorStr336);
*outflag = 1;
obj = CParser_NewFunctionObject(declinfo);
CheckDefaultArgs(TYPE_FUNC(obj->type)->args);
if (tfunc->flags & FUNC_FLAGS_PASCAL) {
for (scan = list; scan; scan = scan->next) {
if (scan->object->otype == OT_OBJECT && IS_TYPE_FUNC(OBJECT(scan->object)->type)) {
if (TYPE_FUNC(OBJECT(scan->object)->type)->flags & FUNC_FLAGS_PASCAL)
CError_Error(CErrorStr226);
}
}
}
if (copts.cplusplus && declinfo->x4E) {
for (scan = list; scan; scan = scan->next) {
if (scan->object->otype == OT_OBJECT && !(OBJECT(scan->object)->qual & Q_80000))
CError_Error(CErrorStr197);
}
}
CScope_AddObject(cscope_current, declinfo->name, OBJ_BASE(obj));
if (cscope_current->theclass && (cscope_current->theclass->flags & CLASS_FLAGS_100) &&
CTemplTool_IsTemplateArgumentDependentType(declinfo->thetype))
CTemplClass_RegisterObjectDef(TEMPL_CLASS(cscope_current->theclass), OBJ_BASE(obj));
return obj;
}
void MergeDefaultArgs(FuncArg *a, FuncArg *b) {
FuncArg *scan_a;
FuncArg *scan_b;
if (a == &oldstyle || b == &oldstyle)
return;
scan_a = a;
scan_b = b;
while (scan_a && scan_b) {
if (scan_a->dexpr) {
while (scan_b) {
if (scan_b->dexpr) {
while (a) {
a->dexpr = NULL;
a = a->next;
}
while (b) {
b->dexpr = NULL;
b = b->next;
}
CError_Error(CErrorStr205);
return;
}
scan_b = scan_b->next;
}
break;
} else if (scan_b->dexpr) {
do {
scan_a = scan_a->next;
scan_b = scan_b->next;
if (!scan_a) goto secondpart;
if (scan_a == &elipsis) goto secondpart;
if (scan_a->dexpr && scan_b->dexpr) break;
} while (scan_a->dexpr || scan_b->dexpr);
while (a) {
a->dexpr = NULL;
a = a->next;
}
while (b) {
b->dexpr = NULL;
b = b->next;
}
CError_Error(CErrorStr205);
return;
} else {
scan_a = scan_a->next;
scan_b = scan_b->next;
}
}
secondpart:
while (a && b) {
if (b->dexpr)
a->dexpr = b->dexpr;
else
b->dexpr = a->dexpr;
a = a->next;
b = b->next;
}
}
void CheckDefaultArgs(FuncArg *args) {
FuncArg *scan;
scan = args;
while (scan && !scan->dexpr)
scan = scan->next;
while (scan && scan != &elipsis && scan != &oldstyle) {
if (!scan->dexpr) {
while (args) {
args->dexpr = NULL;
args = args->next;
}
CError_Error(CErrorStr205);
return;
}
scan = scan->next;
}
}
static void CDecl_FuncRedeclCheck(Object *obj, DeclInfo *declinfo, Boolean flag) {
if (declinfo->storageclass == TK_STATIC && obj->sclass != TK_STATIC) {
if (copts.cplusplus)
CError_Error(CErrorStr260);
else
obj->sclass = TK_STATIC;
}
obj->qual |= declinfo->qual;
if (flag)
CheckDefaultArgs(TYPE_FUNC(obj->type)->args);
else
MergeDefaultArgs(TYPE_FUNC(obj->type)->args, TYPE_FUNC(declinfo->thetype)->args);
if (!declinfo->x45)
TYPE_FUNC(obj->type)->args = TYPE_FUNC(declinfo->thetype)->args;
}
Object *CDecl_GetFunctionObject(DeclInfo *declinfo, NameSpace *nspace, Boolean *pflag, Boolean someotherflag) {
Boolean r27;
Object *obj;
Type *type;
NameSpace *nspace2;
NameSpaceObjectList *list;
TypeMemberFunc tmp;
Boolean outflag;
r27 = 0;
if (pflag)
*pflag = 0;
nspace2 = declinfo->nspace;
if (!nspace2)
nspace2 = cscope_current;
CError_QualifierCheck(declinfo->qual & ~(Q_ALIGNED_MASK | Q_OVERLOAD | Q_20000 | Q_INLINE | Q_PASCAL | Q_ASM | Q_VOLATILE | Q_CONST));
switch (TYPE_FUNC(declinfo->thetype)->functype->type) {
case TYPEFUNC:
case TYPEARRAY:
CError_Error(CErrorStr128);
TYPE_FUNC(declinfo->thetype)->functype = (Type *) &stsignedint;
break;
}
if (nspace2->theclass) {
CError_ASSERT(1969, declinfo->name);
if (!nspace2->theclass->size)
CDecl_CompleteType((Type *) nspace2->theclass);
if (!(list = CScope_GetLocalObject(nspace2, declinfo->name))) {
CError_Error(CErrorStr140, declinfo->name->name);
return NULL;
}
obj = OBJECT(list->object);
type = obj->type;
if (!IS_TYPE_FUNC(type)) {
CError_Error(CErrorStr249, CError_GetObjectName(obj), type, obj->qual, declinfo->thetype, declinfo->qual);
return NULL;
}
if (declinfo->has_expltargs)
return CTempl_TemplateFunctionCheck(declinfo, list);
if (declinfo->x3C || (list->next && list->next->object->otype == OT_OBJECT)) {
if (TYPE_FUNC(declinfo->thetype)->flags & (FUNC_FLAGS_CONST | FUNC_FLAGS_VOLATILE)) {
CDecl_AddThisPointerArgument(TYPE_FUNC(declinfo->thetype), nspace2->theclass);
obj = CDecl_OverloadFunctionObject(list, declinfo, NULL, OverloadMode2, someotherflag);
if (!obj)
return NULL;
} else {
obj = CDecl_OverloadFunctionObject(list, declinfo, NULL, OverloadMode3, someotherflag);
if (!obj)
return NULL;
if (!TYPE_METHOD(obj->type)->x26)
CDecl_AddThisPointerArgument(TYPE_FUNC(declinfo->thetype), nspace2->theclass);
}
} else {
if (TYPE_METHOD(type)->x26) {
if (nspace2->theclass->sominfo)
CSOM_FixNewDeleteFunctype(TYPE_FUNC(declinfo->thetype));
} else {
CDecl_AddThisPointerArgument(TYPE_FUNC(declinfo->thetype), nspace2->theclass);
}
if (copts.cpp_extensions) {
declinfo->qual |= obj->qual & (Q_PASCAL | Q_CONST);
TYPE_FUNC(declinfo->thetype)->qual |= TYPE_FUNC(obj->type)->qual & (Q_PASCAL | Q_CONST);
TYPE_FUNC(declinfo->thetype)->flags |= TYPE_FUNC(obj->type)->flags & (FUNC_FLAGS_4000000 | FUNC_FLAGS_10000000);
}
if (!is_typesame(declinfo->thetype, obj->type) || (declinfo->qual & (Q_PASCAL | Q_CONST)) != (obj->qual & (Q_PASCAL | Q_CONST))) {
tmp = *TYPE_METHOD(obj->type);
*(TYPE_FUNC(&tmp)) = *TYPE_FUNC(declinfo->thetype);
tmp.flags |= FUNC_FLAGS_METHOD;
CError_Error(CErrorStr249, CError_GetObjectName(obj), obj->type, obj->qual, &tmp, declinfo->qual);
}
if (TYPE_FUNC(declinfo->thetype)->exspecs || TYPE_FUNC(obj->type)->exspecs)
CExcept_CompareSpecifications(TYPE_FUNC(declinfo->thetype)->exspecs, TYPE_FUNC(obj->type)->exspecs);
}
CDecl_FuncRedeclCheck(obj, declinfo, 0);
if (declinfo->x3C) {
if (obj->nspace->theclass && !(obj->nspace->theclass->flags & CLASS_FLAGS_800))
CError_Error(CErrorStr335);
declinfo->x3C = 0;
}
} else {
if (TYPE_FUNC(declinfo->thetype)->flags & (FUNC_FLAGS_VOLATILE | FUNC_FLAGS_CONST))
CError_Error(CErrorStr384);
if (declinfo->x3E && !CDecl_CheckOperatorType(declinfo, 0))
return NULL;
list = CScope_GetLocalObject(nspace2, declinfo->name);
if (declinfo->has_expltargs)
return CTempl_TemplateFunctionCheck(declinfo, list);
if (list) {
if (copts.cplusplus) {
obj = CDecl_OverloadFunctionObject(list, declinfo, &outflag, OverloadMode0, someotherflag);
if (!obj)
return NULL;
if (pflag)
*pflag = outflag;
if (nspace)
obj->nspace = nspace;
} else {
obj = OBJECT(list->object);
if (!is_typesame(declinfo->thetype, obj->type) || (declinfo->qual & (Q_CONST | Q_PASCAL)) != (obj->qual & (Q_CONST | Q_PASCAL))) {
CError_Error(CErrorStr249, CError_GetObjectName(obj), obj->type, obj->qual, declinfo->thetype, declinfo->qual);
r27 = 1;
if (!IS_TYPE_FUNC(obj->type))
return NULL;
}
}
if (!r27 && pflag)
CDecl_FuncRedeclCheck(obj, declinfo, *pflag);
} else {
if (declinfo->nspace)
CError_Error(CErrorStr336);
if (declinfo->has_expltargs) {
if (declinfo->name)
CError_Error(CErrorStr140, declinfo->name->name);
else
CError_Error(CErrorStr127);
}
obj = CParser_NewFunctionObject(declinfo);
if (nspace)
obj->nspace = nspace;
if (pflag)
*pflag = 1;
else
CError_Error(CErrorStr127);
CheckDefaultArgs(TYPE_FUNC(obj->type)->args);
CScope_AddObject(nspace2, declinfo->name, OBJ_BASE(obj));
}
}
return obj;
}
void CDecl_TypedefDeclarator(DeclInfo *declinfo) {
NameSpace *nspace;
NameSpaceObjectList *list;
ObjType *objt;
nspace = declinfo->nspace;
if (!nspace)
nspace = cscope_current;
CError_QualifierCheck(declinfo->qual & ~(Q_ALIGNED_MASK | Q_REFERENCE | Q_PASCAL | Q_VOLATILE | Q_CONST));
if (declinfo->x48 || declinfo->x44)
CError_Error(CErrorStr121);
if (declinfo->x3E)
CError_Error(CErrorStr193);
objt = NULL;
list = CScope_FindName(nspace, declinfo->name);
if (list) {
switch (list->object->otype) {
case OT_TYPE:
objt = OBJ_TYPE(list->object);
break;
case OT_TYPETAG:
break;
case OT_NAMESPACE:
CError_Error(CErrorStr321);
return;
case OT_ENUMCONST:
case OT_OBJECT:
CError_Error(CErrorStr322);
return;
default:
CError_FATAL(2156);
}
}
if (objt) {
const UInt32 mask = Q_ALIGNED_MASK | Q_REFERENCE | Q_PASCAL | Q_VOLATILE | Q_CONST;
if (!is_typesame(objt->type, declinfo->thetype) || (objt->qual & mask) != (declinfo->qual & mask)) {
CError_Error(CErrorStr249, declinfo->name->name, objt->type, objt->qual, declinfo->thetype, declinfo->qual);
} else if (!copts.cplusplus && (copts.pedantic || copts.ANSIstrict)) {
if (copts.pedantic)
CError_Warning(CErrorStr122, declinfo->name->name);
else
CError_Error(CErrorStr122, declinfo->name->name);
}
return;
}
objt = galloc(sizeof(ObjType));
memclrw(objt, sizeof(ObjType));
objt->otype = OT_TYPE;
objt->access = ACCESSPUBLIC;
objt->type = declinfo->thetype;
objt->qual = declinfo->qual;
CScope_AddObject(nspace, declinfo->name, OBJ_BASE(objt));
if (nspace->theclass && (nspace->theclass->flags & CLASS_FLAGS_100) &&
CTemplTool_IsTemplateArgumentDependentType(declinfo->thetype))
CTemplClass_RegisterObjectDef(TEMPL_CLASS(nspace->theclass), OBJ_BASE(objt));
if (copts.cplusplus) {
if (IS_TYPE_CLASS(declinfo->thetype) && IsTempName(TYPE_CLASS(declinfo->thetype)->classname)) {
TYPE_CLASS(declinfo->thetype)->classname = declinfo->name;
TYPE_CLASS(declinfo->thetype)->nspace->name = declinfo->name;
}
if (IS_TYPE_ENUM(declinfo->thetype) && IsTempName(TYPE_ENUM(declinfo->thetype)->enumname)) {
TYPE_ENUM(declinfo->thetype)->enumname = declinfo->name;
}
}
if (cparamblkptr->browseoptions.recordTypedefs && declinfo->file->recordbrowseinfo)
CBrowse_NewTypedef(nspace, declinfo->name, declinfo->file, declinfo->file2, declinfo->x60, CPrep_BrowserFileOffset());
}
static void CDecl_DataDeclarator(DeclInfo *declinfo, short access, Boolean flag) {
NameSpaceObjectList *list;
Object *obj;
NameSpace *nspace;
Boolean tmpflag;
ENode *expr;
nspace = declinfo->nspace;
if (!nspace)
nspace = cscope_current;
CError_QualifierCheck(declinfo->qual & ~(Q_ALIGNED_MASK | Q_OVERLOAD | Q_20000 | Q_PASCAL | Q_VOLATILE | Q_CONST));
if (declinfo->x48 || declinfo->x44)
CError_Error(CErrorStr121);
if (declinfo->x3E)
CError_Error(CErrorStr193);
obj = NULL;
list = CScope_FindName(nspace, declinfo->name);
if (list) {
switch (list->object->otype) {
case OT_OBJECT:
obj = OBJECT(list->object);
if (flag)
CError_Error(CErrorStr122, declinfo->name->name);
break;
case OT_TYPETAG:
break;
case OT_NAMESPACE:
CError_Error(CErrorStr321);
return;
case OT_ENUMCONST:
case OT_TYPE:
CError_Error(CErrorStr322);
break;
case OT_MEMBERVAR:
CError_Error(CErrorStr221);
break;
default:
CError_FATAL(2281);
}
}
if (copts.cplusplus) {
if (!flag)
CDecl_CompleteType(declinfo->thetype);
switch (declinfo->storageclass) {
case TK_EXTERN:
if (tk == '=' || tk == '(')
declinfo->storageclass = 0;
break;
case 0:
if (CParser_IsConst(declinfo->thetype, declinfo->qual)) {
if ((!obj && !nspace->theclass) || (obj && obj->sclass != TK_EXTERN && !obj->nspace->theclass))
declinfo->storageclass = TK_STATIC;
}
break;
}
} else {
if (declinfo->storageclass == TK_EXTERN && tk == '=')
declinfo->storageclass = 0;
}
if (IS_TYPE_ARRAY(declinfo->thetype) && !declinfo->thetype->size && !declinfo->storageclass && tk != '=')
declinfo->storageclass = TK_EXTERN;
if (obj) {
if ((!obj->type->size || !declinfo->thetype->size) && IS_TYPE_ARRAY(declinfo->thetype) && IS_TYPE_ARRAY(obj->type))
tmpflag = is_typesame(TYPE_POINTER(declinfo->thetype)->target, TYPE_POINTER(obj->type)->target);
else
tmpflag = is_typesame(declinfo->thetype, obj->type);
if (!tmpflag || (obj->qual & (Q_PASCAL | Q_VOLATILE | Q_CONST)) != (declinfo->qual & (Q_PASCAL | Q_VOLATILE | Q_CONST)))
CError_Error(CErrorStr249, CError_GetObjectName(obj), obj->type, obj->qual, declinfo->thetype, declinfo->qual);
if (obj->qual & Q_10000) {
if (tk == ',' || tk == ';')
return;
CError_Error(CErrorStr333, obj);
}
if (declinfo->storageclass != TK_EXTERN) {
if (obj->sclass != TK_EXTERN && declinfo->storageclass && obj->sclass != declinfo->storageclass)
CError_Error(CErrorStr333, obj);
if (tmpflag) {
obj->sclass = declinfo->storageclass;
obj->qual |= declinfo->qual;
if (declinfo->thetype->size)
obj->type = declinfo->thetype;
}
CParser_UpdateObject(obj, declinfo);
} else {
flag = 1;
}
} else {
if (declinfo->nspace)
CError_Error(CErrorStr336);
if (IS_TYPE_CLASS(declinfo->thetype) && TYPE_CLASS(declinfo->thetype)->sominfo)
CError_Error(CErrorStr288);
if (!CanCreateObject(declinfo->thetype))
declinfo->thetype = (Type *) &stsignedint;
obj = CParser_NewGlobalDataObject(declinfo);
obj->access = access;
CScope_AddObject(nspace, declinfo->name, OBJ_BASE(obj));
if (nspace->theclass && (nspace->theclass->flags & CLASS_FLAGS_100) &&
CTemplTool_IsTemplateArgumentDependentType(declinfo->thetype))
CTemplClass_RegisterObjectDef(TEMPL_CLASS(nspace->theclass), OBJ_BASE(obj));
if (flag && nspace->theclass && cparamblkptr->browseoptions.recordClasses)
CBrowse_AddClassMemberData(obj, CPrep_BrowserTokenOffset(&member_fileoffset) + 1, CPrep_BrowserFileOffset());
}
if (!flag) {
if (declinfo->nspace) {
CScopeSave save;
CScope_SetNameSpaceScope(declinfo->nspace, &save);
CInit_InitializeData(obj);
CScope_RestoreScope(&save);
if (declinfo->x3C && obj->nspace->theclass && (TYPE_CLASS(obj->nspace->theclass)->flags & CLASS_FLAGS_800))
declinfo->x3C = 0;
} else {
CInit_InitializeData(obj);
}
if (declinfo->file->recordbrowseinfo && obj->sclass != TK_EXTERN)
CBrowse_NewData(obj, declinfo->file, declinfo->file2, declinfo->x60, CPrep_BrowserFileOffset());
} else if (tk == '=') {
tk = lex();
expr = CExpr_IntegralConstOrDepExpr();
if (IS_TYPE_TEMPLATE(obj->type) || !ENODE_IS(expr, EINTCONST)) {
CError_ASSERT(2426, nspace->theclass && (nspace->theclass->flags & CLASS_FLAGS_100));
CTemplClass_RegisterObjectInit(TEMPL_CLASS(nspace->theclass), obj, expr);
} else if ((obj->qual & Q_CONST) && IS_TYPE_INT_OR_ENUM(obj->type)) {
obj->u.data.u.intconst = expr->data.intval;
obj->qual |= Q_10000 | Q_20000;
} else {
CError_Error(CErrorStr354, obj->name->name);
}
}
}
Boolean CDecl_FunctionDeclarator(DeclInfo *declinfo, NameSpace *nspace, Boolean flag, Boolean flag2) {
Object *obj;
Boolean pflag;
obj = CDecl_GetFunctionObject(declinfo, nspace, &pflag, 0);
if (obj) {
if (declinfo->x44 || tk == '{' || tk == TK_TRY || (declinfo->x4B && tk == ':') || (!copts.cplusplus && isdeclaration(0, 0, 0, 0))) {
if (!flag || cscope_currentfunc) {
CError_Error(CErrorStr127);
if (cscope_currentfunc)
return 0;
}
if (obj->nspace == cscope_root && !strcmp(obj->name->name, "main")) {
if (obj->sclass == TK_STATIC || (copts.ANSIstrict && TYPE_FUNC(obj->type)->functype != (Type *) &stsignedint))
CError_Error(CErrorStr334);
} else if (copts.checkprotos && (pflag || declinfo->x64)) {
if (obj->sclass != TK_STATIC && !(obj->qual & Q_INLINE) && !obj->nspace->is_unnamed)
CError_Warning(CErrorStr178);
}
CFunc_ParseFuncDef(obj, declinfo, NULL, 0, 0, NULL);
if (declinfo->file->recordbrowseinfo)
CBrowse_NewFunction(
obj,
declinfo->file,
declinfo->file2,
declinfo->x60,
CPrep_BrowserFileOffset());
if (copts.cplusplus && lookahead() == ';')
tk = lex();
return 0;
}
}
return 1;
}
static void CDecl_ParseSpecialMember(DeclInfo *declinfo, Boolean flag) {
Object *r28;
NameSpace *r25;
if (!(r28 = declinfo->x10)) {
CError_ASSERT(2544, declinfo->x14);
r28 = OBJECT(declinfo->x14->object);
CError_ASSERT(2546, r28->otype == OT_OBJECT);
}
if (!r28->nspace->theclass) {
CError_Error(CErrorStr121);
return;
}
if (IS_TYPE_FUNC(r28->type)) {
if (TYPE_FUNC(r28->type)->flags & (FUNC_FLAGS_1000 | FUNC_FLAGS_2000)) {
if (r28->nspace->theclass->sominfo)
declinfo->thetype = TYPE(&stvoid);
else
declinfo->thetype = TYPE(&void_ptr);
declinfo->nspace = r28->nspace;
declinfo->name = r28->name;
if (TYPE_FUNC(r28->type)->flags & FUNC_FLAGS_1000)
declinfo->x4B = 1;
if ((tk = lex()) == '(') {
tk = lex();
r25 = cscope_current;
cscope_current = r28->nspace;
CDecl_ParseDirectFuncDecl(declinfo);
cscope_current = r25;
if (IS_TYPE_FUNC(declinfo->thetype)) {
if (TYPE_FUNC(r28->type)->flags & FUNC_FLAGS_1000) {
if ((r28->nspace->theclass->flags & CLASS_FLAGS_20) && !r28->nspace->theclass->sominfo)
CDecl_AddArgument(TYPE_FUNC(declinfo->thetype), TYPE(&stsignedshort));
} else {
if (!r28->nspace->theclass->sominfo)
CDecl_AddArgument(TYPE_FUNC(declinfo->thetype), TYPE(&stsignedshort));
}
if (flag)
CDecl_FunctionDeclarator(declinfo, NULL, 1, 1);
} else {
CError_Error(CErrorStr121);
}
} else {
CError_Error(CErrorStr114);
}
return;
} else if (TYPE_FUNC(r28->type)->flags & FUNC_FLAGS_40) {
CError_FATAL(2603);
declinfo->thetype = TYPE_FUNC(r28->type)->functype;
declinfo->qual |= TYPE_FUNC(r28->type)->qual;
declinfo->nspace = r28->nspace;
declinfo->name = r28->name;
if ((tk = lex()) == '(') {
tk = lex();
CDecl_ParseDirectFuncDecl(declinfo);
if (IS_TYPE_FUNC(declinfo->thetype)) {
TYPE_FUNC(declinfo->thetype)->flags |= FUNC_FLAGS_40;
if (flag)
CDecl_FunctionDeclarator(declinfo, NULL, 1, 1);
} else {
CError_Error(CErrorStr121);
}
} else {
CError_Error(CErrorStr114);
}
return;
} else {
declinfo->thetype = TYPE(&stsignedint);
declinfo->nspace = r28->nspace;
declinfo->name = r28->name;
if ((tk = lex()) == '(') {
tk = lex();
r25 = cscope_current;
cscope_current = r28->nspace;
CDecl_ParseDirectFuncDecl(declinfo);
cscope_current = r25;
if (IS_TYPE_FUNC(declinfo->thetype)) {
if (flag)
CDecl_FunctionDeclarator(declinfo, NULL, 1, 1);
return;
}
} else {
CError_Error(CErrorStr114);
}
}
}
CError_Error(CErrorStr121);
}
void CDecl_ScanDeclarator(DeclInfo *declinfo) {
if (declinfo->x14 || declinfo->x10) {
CDecl_ParseSpecialMember(declinfo, 0);
CDecl_GetFunctionObject(declinfo, NULL, NULL, 1);
return;
}
if (IS_TYPE_FUNC(declinfo->thetype)) {
TypeFunc *copy = galloc(sizeof(TypeFunc));
*copy = *TYPE_FUNC(declinfo->thetype);
declinfo->thetype = TYPE(copy);
}
scandeclarator(declinfo);
if (!declinfo->name) {
CError_Error(CErrorStr121);
return;
}
if (declinfo->storageclass && declinfo->storageclass != TK_EXTERN)
CError_Error(CErrorStr177);
if (IS_TYPE_FUNC(declinfo->thetype)) {
CDecl_GetFunctionObject(declinfo, NULL, NULL, 1);
return;
}
if (declinfo->x48 || declinfo->x44)
CError_Error(CErrorStr121);
if (declinfo->x3E)
CError_Error(CErrorStr193);
if (
(declinfo->qual & ~(Q_ALIGNED_MASK | Q_OVERLOAD | Q_20000 | Q_PASCAL | Q_VOLATILE | Q_CONST)) ||
(declinfo->storageclass == TK_TYPEDEF && (declinfo->qual & ~(Q_ALIGNED_MASK | Q_REFERENCE | Q_PASCAL | Q_VOLATILE | Q_CONST)))
)
CError_Error(CErrorStr176);
}
void scandeclaratorlist(DeclInfo *declinfo) {
CScopeSave savescope;
Type *r30;
UInt32 r29;
Boolean r28;
if (declinfo->x14 || declinfo->x10) {
CDecl_ParseSpecialMember(declinfo, 1);
return;
}
CScope_GetScope(&savescope);
CError_ASSERT(2707, declinfo->thetype);
r28 = 1;
while (1) {
r30 = declinfo->thetype;
r29 = declinfo->qual;
declinfo->nspace = NULL;
declinfo->x3E = 0;
if (IS_TYPE_FUNC(r30)) {
declinfo->thetype = galloc(sizeof(TypeFunc));
*TYPE_FUNC(declinfo->thetype) = *TYPE_FUNC(r30);
}
declinfo->name = NULL;
scandeclarator(declinfo);
if (!declinfo->name) {
CError_Error(CErrorStr121);
break;
}
if (declinfo->storageclass != TK_TYPEDEF) {
if (IS_TYPE_FUNC(declinfo->thetype)) {
if (!CDecl_FunctionDeclarator(declinfo, NULL, r28, 1))
return;
} else {
CDecl_DataDeclarator(declinfo, ACCESSPUBLIC, 0);
}
} else {
CDecl_TypedefDeclarator(declinfo);
}
CScope_RestoreScope(&savescope);
declinfo->thetype = r30;
declinfo->qual = r29;
if (tk != ',')
break;
tk = lex();
r28 = 0;
}
if (tk != ';')
CError_Error(CErrorStr123);
}
static TypeIntegral *CDecl_FindSignedType(short size) {
if (stsignedchar.size == size)
return &stsignedchar;
if (stsignedshort.size == size)
return &stsignedshort;
if (stsignedint.size == size)
return &stsignedint;
if (stsignedlong.size == size)
return &stsignedlong;
if (copts.longlong && copts.longlong_enums && stsignedlonglong.size == size)
return &stsignedlonglong;
return &stsignedlong;
}
static TypeIntegral *CDecl_FindUnsignedType(short size) {
if (stunsignedchar.size == size)
return &stunsignedchar;
if (stunsignedshort.size == size)
return &stunsignedshort;
if (stunsignedint.size == size)
return &stunsignedint;
if (stunsignedlong.size == size)
return &stunsignedlong;
if (copts.longlong && copts.longlong_enums && stunsignedlonglong.size == size)
return &stunsignedlonglong;
return &stunsignedlong;
}
static TypeIntegral *CDecl_IterateIntegralEnumType(int *t) {
switch (*t) {
case 0:
*t = 1;
return &stsignedchar;
case 1:
if (stsignedshort.size > stsignedchar.size) {
*t = 2;
return &stsignedshort;
}
case 2:
if (stsignedint.size > stsignedshort.size) {
*t = 3;
return &stsignedint;
}
case 3:
if (stsignedlong.size > stsignedint.size) {
*t = 4;
return &stsignedlong;
}
case 4:
*t = 5;
if (stsignedlonglong.size > stsignedlong.size && copts.longlong && copts.longlong_enums)
return &stsignedlonglong;
default:
return NULL;
}
}
static TypeIntegral *CDecl_IterateUIntegralEnumType(int *t) {
switch (*t) {
case 0:
*t = 1;
return &stunsignedchar;
case 1:
if (stunsignedshort.size > stunsignedchar.size) {
*t = 2;
return &stunsignedshort;
}
case 2:
if (stunsignedint.size > stunsignedshort.size) {
*t = 3;
return &stunsignedint;
}
case 3:
if (stunsignedlong.size > stunsignedint.size) {
*t = 4;
return &stunsignedlong;
}
case 4:
*t = 5;
if (stunsignedlonglong.size > stunsignedlong.size && copts.longlong && copts.longlong_enums)
return &stunsignedlonglong;
default:
return NULL;
}
}
static TypeEnum *CDecl_OldParseEnumList(TypeEnum *tenum, HashNameNode *name) {
AccessType access;
Boolean has_template_value;
Boolean r24;
Boolean r23;
ObjEnumConst *oec;
ObjEnumConst *last;
Boolean overflowed;
CInt64 val;
CInt64 minimum;
CInt64 maximum;
CInt64 var_74;
CInt64 unused;
Type *basetype;
Type *basetype2;
CPrepFileInfo *fileinfo;
SInt32 offset;
ENode *expr;
Type *tmp;
if (!tenum) {
tenum = galloc(sizeof(TypeEnum));
memclrw(tenum, sizeof(TypeEnum));
tenum->type = TYPEENUM;
tenum->nspace = cscope_current;
if (name) {
tenum->enumname = name;
CScope_DefineTypeTag(cscope_current, name, TYPE(tenum));
}
if (!cscope_current->is_global) {
do {
tenum->nspace = tenum->nspace->parent;
} while (!tenum->nspace->is_global);
if (tenum->enumname)
tenum->enumname = CParser_AppendUniqueNameFile(tenum->enumname->name);
}
}
if (cscope_current->theclass && (cscope_current->theclass->flags & CLASS_FLAGS_100)) {
CTemplClass_RegisterEnumType(TEMPL_CLASS(cscope_current->theclass), tenum);
}
access = cscope_current->theclass ? global_access : ACCESSPUBLIC;
last = NULL;
unused = cint64_zero;
val = cint64_zero;
minimum = cint64_zero;
maximum = cint64_zero;
r23 = 0;
if (copts.enumsalwaysint) {
basetype = TYPE(&stsignedint);
r24 = 1;
} else {
basetype = TYPE(&stunsignedchar);
r24 = 0;
}
tk = lex();
if (!copts.cplusplus || tk != '}') {
do {
if (tk != TK_IDENTIFIER) {
if (tk == '}') {
if (copts.cpp_extensions)
break;
if (!copts.warn_extracomma)
break;
}
CError_Warning(CErrorStr107);
break;
}
oec = galloc(sizeof(ObjEnumConst));
memclrw(oec, sizeof(ObjEnumConst));
oec->otype = OT_ENUMCONST;
oec->access = access;
oec->type = TYPE(tenum);
oec->name = tkidentifier;
CPrep_BrowserFilePosition(&fileinfo, &offset);
overflowed = 0;
if ((tk = lex()) == '=') {
tk = lex();
val = CExpr_IntegralConstExprType(&basetype2);
if (!CInt64_IsNegative(&val) || is_unsigned(basetype2)) {
if (CInt64_GreaterU(val, minimum)) {
minimum = val;
overflowed = 1;
}
} else {
if (CInt64_Less(val, maximum)) {
maximum = val;
overflowed = 1;
}
if (!r24) {
basetype = TYPE(&stsignedchar);
r24 = 1;
}
}
r23 = 0;
} else {
if (r23)
CError_Error(CErrorStr154);
if (!r24 || !CInt64_IsNegative(&val)) {
if (CInt64_GreaterU(val, minimum)) {
minimum = val;
overflowed = 1;
}
} else {
if (CInt64_Less(val, maximum)) {
maximum = val;
overflowed = 1;
}
}
}
if (copts.enumsalwaysint) {
if (copts.ANSIstrict) {
if (!CInt64_IsInRange(val, stsignedint.size))
CError_Error(CErrorStr154);
} else {
if (!CInt64_IsInRange(val, stsignedint.size) && !CInt64_IsInURange(val, stunsignedint.size))
CError_Error(CErrorStr154);
}
} else if (r24) {
switch (basetype->size) {
case 1:
if (CInt64_IsInRange(minimum, 1) && CInt64_IsInRange(maximum, 1))
break;
basetype = TYPE(CDecl_FindSignedType(2));
case 2:
if (CInt64_IsInRange(minimum, 2) && CInt64_IsInRange(maximum, 2))
break;
basetype = TYPE(CDecl_FindSignedType(4));
case 4:
if (CInt64_IsInRange(minimum, 4) && CInt64_IsInRange(maximum, 4))
break;
basetype = TYPE(CDecl_FindSignedType(8));
if (basetype->size != 8) {
if (!copts.ANSIstrict && CInt64_IsInRange(maximum, 4) && CInt64_IsInURange(minimum, 4))
break;
if (overflowed)
CError_Error(CErrorStr154);
break;
}
case 8:
if (CInt64_Equal(val, minimum) && CInt64_IsNegative(&val))
CError_Error(CErrorStr154);
break;
default:
CError_FATAL(3071);
}
} else {
switch (basetype->size) {
case 1:
if (CInt64_IsInURange(minimum, 1))
break;
basetype = TYPE(CDecl_FindUnsignedType(2));
case 2:
if (CInt64_IsInURange(minimum, 2))
break;
basetype = TYPE(CDecl_FindUnsignedType(4));
case 4:
if (CInt64_IsInURange(minimum, 4))
break;
basetype = TYPE(CDecl_FindUnsignedType(8));
if (basetype->size != 8) {
if (overflowed)
CError_Error(CErrorStr154);
break;
}
case 8:
break;
default:
CError_FATAL(3099);
}
}
tenum->size = basetype->size;
tenum->enumtype = basetype;
oec->val = val;
CScope_AddObject(cscope_current, oec->name, OBJ_BASE(oec));
if (last) {
last->next = oec;
last = oec;
} else {
last = oec;
tenum->enumlist = oec;
}
if (cparamblkptr->browseoptions.recordEnums) {
CPrepFileInfo *f = CPrep_BrowserCurrentFile();
if (f->recordbrowseinfo) {
CBrowse_NewEnumConstant(cscope_current, oec->name, f, fileinfo, offset, CPrep_BrowserFileOffset());
}
}
var_74 = CInt64_Add(val, cint64_one);
if (r24) {
if (CInt64_IsNegative(&var_74) && !CInt64_IsNegative(&val))
r23 = 1;
} else {
if (CInt64_IsZero(&var_74))
r23 = 1;
}
val = var_74;
if (tk != ',')
break;
tk = lex();
} while (1);
}
tenum->size = basetype->size;
tenum->enumtype = basetype;
for (oec = tenum->enumlist; oec; oec = oec->next)
oec->type = TYPE(tenum);
if (tk != '}')
CError_ErrorSkip(CErrorStr130);
else
tk = lex();
return tenum;
}
static Type *CDecl_MaxType(Type *a, Type *b) {
if (a->size > b->size)
return a;
if (b->size > a->size)
return b;
if (is_unsigned(b))
return b;
else
return a;
}
void CDecl_ComputeUnderlyingEnumType(TypeEnum *tenum) {
ObjEnumConst *oec;
ObjEnumConst *oec2;
Type *r26;
int t;
if (!copts.enumsalwaysint) {
for (oec2 = tenum->enumlist; oec2; oec2 = oec2->next) {
if (CInt64_IsNegative(&oec2->val) && !is_unsigned(oec2->type))
break;
}
if (oec2) {
CInt64 unused = cint64_zero;
CInt64 minimum = cint64_zero;
CInt64 maximum = cint64_zero;
for (oec = tenum->enumlist; oec; oec = oec->next) {
if (CInt64_IsNegative(&oec->val) && !is_unsigned(oec->type)) {
if (CInt64_Less(oec->val, minimum))
minimum = oec->val;
} else {
if (CInt64_GreaterU(oec->val, maximum))
maximum = oec->val;
}
}
if (CInt64_IsNegative(&maximum))
CError_Error(CErrorStr154);
t = 0;
do {
r26 = TYPE(CDecl_IterateIntegralEnumType(&t));
if (!r26) {
r26 = TYPE(&stsignedlong);
CError_Error(CErrorStr154);
break;
}
if (CInt64_IsInRange(maximum, r26->size) && CInt64_IsInRange(minimum, r26->size))
break;
if (r26->size == stsignedlong.size && !copts.ANSIstrict && CInt64_IsInRange(minimum, r26->size) && CInt64_IsInURange(maximum, r26->size))
break;
} while (1);
} else {
CInt64 val = cint64_zero;
for (oec = tenum->enumlist; oec; oec = oec->next) {
if (CInt64_GreaterU(oec->val, val))
val = oec->val;
}
t = 0;
do {
r26 = TYPE(CDecl_IterateUIntegralEnumType(&t));
if (!r26) {
r26 = TYPE(&stunsignedlong);
CError_Error(CErrorStr154);
break;
}
if (CInt64_IsInURange(val, r26->size))
break;
} while (1);
}
} else {
r26 = TYPE(&stsignedint);
}
tenum->size = r26->size;
tenum->enumtype = r26;
for (oec = tenum->enumlist; oec; oec = oec->next)
oec->type = TYPE(tenum);
}
static Type *CDecl_FindUnderlyingType(short size, CInt64 *a, CInt64 *b) {
if (CInt64_IsZero(a)) {
if (size <= stsignedchar.size && CInt64_IsInURange(*b, stunsignedchar.size))
return TYPE(&stunsignedchar);
if (size <= stsignedshort.size && CInt64_IsInURange(*b, stunsignedshort.size))
return TYPE(&stunsignedshort);
if (size <= stsignedint.size && CInt64_IsInURange(*b, stunsignedint.size))
return TYPE(&stunsignedint);
if (size <= stsignedlong.size && CInt64_IsInURange(*b, stunsignedlong.size))
return TYPE(&stunsignedlong);
if (size <= stsignedlonglong.size && copts.longlong && copts.longlong_enums && CInt64_IsInURange(*b, stunsignedlonglong.size))
return TYPE(&stunsignedlonglong);
} else {
if (size <= stsignedchar.size && CInt64_IsInRange(*a, stsignedchar.size) && CInt64_IsInRange(*b, stsignedchar.size))
return TYPE(&stsignedchar);
if (size <= stsignedshort.size && CInt64_IsInRange(*a, stsignedshort.size) && CInt64_IsInRange(*b, stsignedshort.size))
return TYPE(&stsignedshort);
if (size <= stsignedint.size && CInt64_IsInRange(*a, stsignedint.size) && CInt64_IsInRange(*b, stsignedint.size))
return TYPE(&stsignedint);
if (size <= stsignedlong.size && CInt64_IsInRange(*a, stsignedlong.size) && CInt64_IsInRange(*b, stsignedlong.size))
return TYPE(&stsignedlong);
if (size <= stsignedlonglong.size && copts.longlong && copts.longlong_enums && CInt64_IsInRange(*a, stsignedlonglong.size) && CInt64_IsInRange(*b, stsignedlonglong.size))
return TYPE(&stsignedlonglong);
if (!copts.ANSIstrict && size <= stsignedlong.size && CInt64_IsInRange(*a, stsignedlong.size) && CInt64_IsInURange(*b, stunsignedlong.size))
return TYPE(&stsignedlong);
}
return NULL;
}
static TypeEnum *CDecl_ParseEnumList(TypeEnum *tenum, HashNameNode *name) {
AccessType access;
TemplClass *tmclass;
ObjEnumConst *oec;
Boolean has_template_value;
Boolean overflowed;
Boolean is_first;
CInt64 val;
CInt64 minimum;
CInt64 maximum;
CInt64 unused;
Type *basetype;
CPrepFileInfo *fileinfo;
SInt32 offset;
ENode *expr;
Type *tmp;
ObjEnumConst *last;
if (!tenum) {
tenum = galloc(sizeof(TypeEnum));
memclrw(tenum, sizeof(TypeEnum));
tenum->type = TYPEENUM;
tenum->nspace = cscope_current;
if (name) {
tenum->enumname = name;
CScope_DefineTypeTag(cscope_current, name, TYPE(tenum));
}
if (!cscope_current->is_global) {
do {
tenum->nspace = tenum->nspace->parent;
} while (!tenum->nspace->is_global);
if (tenum->enumname)
tenum->enumname = CParser_AppendUniqueNameFile(tenum->enumname->name);
}
}
if (cscope_current->theclass && (cscope_current->theclass->flags & CLASS_FLAGS_100)) {
tmclass = TEMPL_CLASS(cscope_current->theclass);
CTemplClass_RegisterEnumType(tmclass, tenum);
} else {
tmclass = NULL;
}
access = cscope_current->theclass ? global_access : ACCESSPUBLIC;
last = NULL;
is_first = 1;
has_template_value = 0;
unused = cint64_zero;
val = cint64_zero;
minimum = cint64_zero;
maximum = cint64_zero;
basetype = copts.enumsalwaysint ? TYPE(&stsignedint) : TYPE(&stsignedchar);
tenum->size = basetype->size;
tenum->enumtype = basetype;
do {
if ((tk = lex()) != TK_IDENTIFIER) {
if (tk == '}') {
if (is_first) {
if (copts.cplusplus)
break;
} else {
if (!copts.warn_extracomma)
break;
if (copts.c9x)
break;
if (copts.cpp_extensions)
break;
}
CError_Warning(CErrorStr107);
} else {
CError_Error(CErrorStr107);
}
break;
}
oec = galloc(sizeof(ObjEnumConst));
memclrw(oec, sizeof(ObjEnumConst));
oec->otype = OT_ENUMCONST;
oec->access = access;
oec->name = tkidentifier;
CPrep_BrowserFilePosition(&fileinfo, &offset);
overflowed = 0;
if ((tk = lex()) == '=') {
tk = lex();
if (tmclass) {
expr = CExpr_IntegralConstOrDepExpr();
if (ENODE_IS(expr, EINTCONST)) {
val = expr->data.intval;
basetype = expr->rtype;
has_template_value = 0;
} else {
val = cint64_zero;
basetype = TYPE(tenum);
CTemplClass_RegisterEnumerator(tmclass, oec, expr);
has_template_value = 1;
}
} else {
val = CExpr_IntegralConstExprType(&basetype);
has_template_value = 0;
}
} else if (has_template_value) {
CTemplClass_RegisterEnumerator(tmclass, oec, NULL);
} else if (!is_first) {
if (is_unsigned(basetype)) {
val = CInt64_Add(val, cint64_one);
if (CInt64_IsZero(&val))
overflowed = 1;
} else if (!CInt64_IsNegative(&val)) {
val = CInt64_Add(val, cint64_one);
if (CInt64_IsNegative(&val))
overflowed = 1;
} else {
val = CInt64_Add(val, cint64_one);
}
}
if (!has_template_value) {
if (copts.enumsalwaysint) {
if (!CInt64_IsInRange(val, stsignedint.size) && (copts.ANSIstrict || !CInt64_IsInURange(val, stunsignedint.size)))
overflowed = 1;
basetype = TYPE(&stsignedint);
} else if (CInt64_IsNegative(&val) && !is_unsigned(basetype)) {
if (CInt64_Less(val, minimum)) {
minimum = val;
if ((tmp = CDecl_FindUnderlyingType(tenum->size, &minimum, &maximum))) {
tenum->size = tmp->size;
tenum->enumtype = tmp;
} else {
overflowed = 1;
}
}
} else {
if (CInt64_GreaterU(val, maximum)) {
maximum = val;
if ((tmp = CDecl_FindUnderlyingType(tenum->size, &minimum, &maximum))) {
tenum->size = tmp->size;
tenum->enumtype = tmp;
} else {
overflowed = 1;
}
}
}
}
if (overflowed)
CError_Error(CErrorStr154);
oec->val = val;
oec->type = basetype;
CScope_AddObject(cscope_current, oec->name, OBJ_BASE(oec));
if (last) {
last->next = oec;
last = oec;
} else {
last = oec;
tenum->enumlist = oec;
}
if (cparamblkptr->browseoptions.recordEnums) {
CPrepFileInfo *f = CPrep_BrowserCurrentFile();
if (f->recordbrowseinfo) {
CBrowse_NewEnumConstant(cscope_current, oec->name, f, fileinfo, offset, CPrep_BrowserFileOffset());
}
}
is_first = 0;
} while (tk == ',');
for (oec = tenum->enumlist; oec; oec = oec->next)
oec->type = TYPE(tenum);
if (tk != '}')
CError_ErrorSkip(CErrorStr130);
else
tk = lex();
return tenum;
}
void scanenum(DeclInfo *declinfo) {
HashNameNode *name;
Type *type;
CScopeParseResult pr;
if (tk == '{') {
declinfo->thetype = TYPE(CDecl_ParseEnumList(NULL, NULL));
TYPE_ENUM(declinfo->thetype)->enumname = CParser_AppendUniqueNameFile("@enum");
return;
}
if (tk == TK_IDENTIFIER) {
name = tkidentifier;
if (lookahead() == '{') {
type = CScope_GetLocalTagType(cscope_current, name);
if (type) {
lex();
do_shit:
if (type->size || !IS_TYPE_ENUM(type)) {
CError_Error(CErrorStr122, name->name);
declinfo->thetype = TYPE(CDecl_ParseEnumList(NULL, NULL));
return;
}
declinfo->thetype = TYPE(CDecl_ParseEnumList(TYPE_ENUM(type), NULL));
} else {
lex();
declinfo->thetype = TYPE(CDecl_ParseEnumList(NULL, name));
}
if (cparamblkptr->browseoptions.recordEnums && declinfo->file->recordbrowseinfo)
CBrowse_NewEnum(
cscope_current,
TYPE_ENUM(declinfo->thetype)->enumname,
declinfo->file,
declinfo->file2,
declinfo->x60,
CPrep_BrowserFileOffset());
return;
} else {
CError_ASSERT(3851, !copts.cplusplus || tk != ';');
tkidentifier = name;
}
}
if (CScope_ParseElaborateName(&pr)) {
if ((type = pr.x8)) {
if (!IS_TYPE_ENUM(type))
CError_Error(CErrorStr121);
if ((tk = lex()) == '{')
goto do_shit;
declinfo->thetype = type;
return;
} else {
CError_ASSERT(3865, pr.name_4);
if ((tk = lex()) == '{') {
declinfo->thetype = TYPE(CDecl_ParseEnumList(NULL, pr.name_4));
return;
} else {
CError_Error(CErrorStr140, pr.name_4->name);
}
}
} else {
CError_Error(CErrorStr121);
}
declinfo->thetype = TYPE(&stsignedint);
}
void CDecl_ScanStructDeclarator(BigDeclInfo *bde) {
ENode *expr;
short val;
short bits;
Boolean is_bitfield;
TypeTemplDep *ttempl;
TypeBitfield *tbitfield;
Type *type;
bde->declinfo2 = bde->declinfo;
bde->declinfo2.name = NULL;
bde->declinfo2.x3E = 0;
bde->xCD = 0;
is_bitfield = 0;
if (tk == ':') {
bde->declinfo2.name = no_name_node;
is_bitfield = 1;
} else {
bde->declinfo2.x50 = 1;
scandeclarator(&bde->declinfo2);
if (!bde->declinfo2.name) {
CError_Error(CErrorStr131);
return;
}
if ((!copts.ANSIstrict || copts.c9x) && !bde->declinfo2.thetype->size && IS_TYPE_ARRAY(bde->declinfo2.thetype)) {
if (bde->declinfo2.storageclass != TK_STATIC && bde->declinfo2.storageclass != TK_TYPEDEF) {
type = TYPE_POINTER(bde->declinfo2.thetype)->target;
while (IS_TYPE_ARRAY(type))
type = TYPE_POINTER(type)->target;
if (!IsCompleteType(type))
return;
if (tk != ';' || lookahead() != '}') {
CError_Error(CErrorStr145);
return;
}
}
} else {
if (bde->declinfo2.storageclass != TK_STATIC && bde->declinfo2.storageclass != TK_TYPEDEF) {
if (!IS_TYPE_FUNC(bde->declinfo2.thetype) && !IsCompleteType(bde->declinfo2.thetype))
return;
}
}
if (IS_TYPE_CLASS(bde->declinfo2.thetype) && TYPE_CLASS(bde->declinfo2.thetype)->sominfo) {
CError_Error(CErrorStr287);
return;
}
if (tk != ':')
goto not_a_bitfield;
}
if (!IS_TYPE_INT_OR_ENUM(bde->declinfo2.thetype)) {
if (CTemplTool_IsTemplateArgumentDependentType(bde->declinfo2.thetype))
goto fuckup;
CError_Error(CErrorStr138);
bde->declinfo2.thetype = TYPE(&stunsignedint);
} else if (copts.ANSIstrict && !copts.cplusplus) {
if (bde->declinfo2.thetype != TYPE(&stsignedint) && bde->declinfo2.thetype != TYPE(&stunsignedint)) {
CError_Error(CErrorStr138);
bde->declinfo2.thetype = TYPE(&stunsignedint);
}
}
switch (bde->declinfo2.thetype->size) {
case 1:
bits = 8;
break;
case 2:
bits = 16;
break;
case 4:
bits = 32;
break;
default:
CError_Error(CErrorStr138);
return;
}
fuckup:
tk = lex();
expr = CExpr_IntegralConstOrDepExpr();
if (!ENODE_IS(expr, EINTCONST)) {
ttempl = TYPE_TEMPLATE(CDecl_NewTemplDepType(TEMPLDEP_BITFIELD));
ttempl->u.bitfield.type = bde->declinfo2.thetype;
ttempl->u.bitfield.size = CInline_CopyExpression(expr, CopyMode1);
bde->declinfo2.thetype = TYPE(ttempl);
bde->xCD = 1;
return;
}
val = CInt64_GetULong(&expr->data.intval);
if (is_bitfield) {
if (val < 0 || val > bits) {
CError_Error(CErrorStr138);
return;
}
} else {
if (val <= 0 || val > bits) {
CError_Error(CErrorStr138);
return;
}
}
tbitfield = galloc(sizeof(TypeBitfield));
memclrw(tbitfield, sizeof(TypeBitfield));
tbitfield->type = TYPEBITFIELD;
tbitfield->size = bde->declinfo2.thetype->size;
tbitfield->bitfieldtype = bde->declinfo2.thetype;
tbitfield->unkB = val;
bde->declinfo2.thetype = TYPE(tbitfield);
if (tk == TK_UU_ATTRIBUTE_UU)
CParser_ParseAttribute(NULL, &bde->declinfo2);
not_a_bitfield:
bde->xCD = 1;
}
static void CDecl_LayoutStruct(TypeStruct *tstruct) {
StructMember *member;
SInt32 r28;
StructMember *innermember;
SInt32 innerbase;
StructMember *newmember;
StructMember **memberp;
TypeBitfield *bf;
SInt32 r24;
Boolean r23;
SInt32 tmp;
r28 = 0;
r23 = 0;
CMach_StructLayoutInitOffset(0);
for (member = tstruct->members; member; member = member->next) {
if (tstruct->stype == STRUCT_TYPE_UNION)
CMach_StructLayoutInitOffset(0);
if (IS_TYPE_BITFIELD(member->type))
member->offset = CMach_StructLayoutBitfield(TYPE_BITFIELD(member->type), member->qual);
else
member->offset = CMach_StructLayoutGetOffset(member->type, member->qual);
if (tstruct->stype == STRUCT_TYPE_UNION) {
tmp = CMach_StructLayoutGetCurSize();
if (tmp > r28)
r28 = tmp;
}
if (member->name == no_name_node)
r23 = 1;
if (!member->name) {
CError_ASSERT(4064, IS_TYPE_STRUCT(member->type));
innerbase = member->offset;
innermember = TYPE_STRUCT(member->type)->members;
r23 = 1;
while (innermember) {
if (ismember(tstruct, innermember->name))
CError_Error(CErrorStr133, innermember->name->name);
if (r23) {
member->type = innermember->type;
member->name = innermember->name;
member->qual = innermember->qual;
member->offset = innerbase + innermember->offset;
} else {
newmember = galloc(sizeof(StructMember));
memclrw(newmember, sizeof(StructMember));
newmember->next = member->next;
newmember->type = innermember->type;
newmember->name = innermember->name;
newmember->qual = innermember->qual | Q_OVERLOAD;
newmember->offset = innerbase + innermember->offset;
member->next = newmember;
member = newmember;
}
if (copts.reverse_bitfields && IS_TYPE_BITFIELD(member->type)) {
bf = galloc(sizeof(TypeBitfield));
*bf = *TYPE_BITFIELD(member->type);
CABI_ReverseBitField(bf);
member->type = TYPE(bf);
}
r23 = 0;
innermember = innermember->next;
}
r23 = 1;
}
}
if (r23) {
memberp = &tstruct->members;
while (*memberp) {
if ((*memberp)->name == no_name_node || !(*memberp)->name)
*memberp = (*memberp)->next;
else
memberp = &(*memberp)->next;
}
}
if (tstruct->stype == STRUCT_TYPE_UNION)
r24 = r28;
else
r24 = CMach_StructLayoutGetCurSize();
tstruct->size = r24;
tstruct->align = CMach_GetStructAlign(tstruct);
tstruct->size = r24 + CABI_StructSizeAlignValue(TYPE(tstruct), r24);
if (copts.reverse_bitfields) {
for (member = tstruct->members; member; member = member->next) {
if (IS_TYPE_BITFIELD(member->type))
CABI_ReverseBitField(TYPE_BITFIELD(member->type));
}
}
if (copts.warn_padding && tstruct->stype != STRUCT_TYPE_UNION) {
StructMember *prev;
member = tstruct->members;
prev = NULL;
while (member) {
if (prev && (prev->offset + prev->type->size) < member->offset) {
CError_Warning(CErrorStr350, member->offset - (prev->offset + prev->type->size), prev->name->name);
}
prev = member;
member = member->next;
}
if (prev && (prev->offset + prev->type->size) < tstruct->size) {
CError_Warning(CErrorStr350, tstruct->size - (prev->offset + prev->type->size), prev->name->name);
}
}
}
static SInt32 scanstructdeclarationlist(TypeStruct *tstruct, Boolean flag) {
SInt32 offset;
StructMember *member;
BigDeclInfo bde;
offset = -1;
memclrw(&bde, sizeof(BigDeclInfo));
if (tk == TK_AT_DEFS) {
CPrep_NewFileOffsetInfo(&member_fileoffset, NULL);
CObjC_ParseDefs(tstruct);
if ((tk = lex()) != '}')
CError_Error(CErrorStr130);
} else {
do {
CPrep_NewFileOffsetInfo(&member_fileoffset, NULL);
memclrw(&bde.declinfo, sizeof(DeclInfo));
CParser_GetDeclSpecs(&bde.declinfo, 0);
if (bde.declinfo.storageclass || bde.declinfo.x44) {
CError_Error(CErrorStr131);
tstruct->members = NULL;
return -1;
}
if (tk != ';') {
while (1) {
CDecl_ScanStructDeclarator(&bde);
if (!CanCreateObject(bde.declinfo2.thetype)) {
CError_Error(CErrorStr131);
bde.xCD = 0;
}
if (bde.declinfo2.x3E) {
CError_Error(CErrorStr131);
bde.xCD = 0;
}
if (bde.xCD) {
if (bde.declinfo2.name == no_name_node || !ismember(tstruct, bde.declinfo2.name)) {
member = galloc(sizeof(StructMember));
memclrw(member, sizeof(StructMember));
member->type = bde.declinfo2.thetype;
member->name = bde.declinfo2.name;
member->qual = bde.declinfo2.qual;
appendmember(tstruct, member);
if (flag) {
CBrowse_AddStructMember(member, CPrep_BrowserTokenOffset(&member_fileoffset) + 1, CPrep_BrowserFileOffset());
}
} else {
CError_Error(CErrorStr133, bde.declinfo2.name->name);
}
}
if (tk != ',')
break;
tk = lex();
}
} else if (!copts.ANSIstrict && IS_TYPE_STRUCT(bde.declinfo.thetype)) {
member = galloc(sizeof(StructMember));
memclrw(member, sizeof(StructMember));
member->type = bde.declinfo.thetype;
appendmember(tstruct, member);
} else {
CError_Error(CErrorStr131);
}
if (tk != ';') {
tstruct->members = NULL;
CError_Error(CErrorStr123);
return -1;
}
CPrep_TokenStreamFlush();
} while ((tk = lex()) != '}');
CDecl_LayoutStruct(tstruct);
}
if (flag) {
offset = CPrep_BrowserFileOffset();
if (tk == ';')
offset++;
}
tk = lex();
return offset;
}
static TypeStruct *CDecl_DefineStruct(HashNameNode *name, short stype) {
TypeStruct *tstruct;
tstruct = galloc(sizeof(TypeStruct));
memclrw(tstruct, sizeof(TypeStruct));
tstruct->type = TYPESTRUCT;
tstruct->align = 1;
tstruct->stype = stype;
if (name) {
tstruct->name = name;
CScope_DefineTypeTag((in_func_arglist && !copts.cplusplus) ? cscope_root : cscope_current, name, (Type *) tstruct);
}
return tstruct;
}
void scanstruct(DeclInfo *declinfo, short structtype) {
Type *type;
HashNameNode *name;
TypeStruct typecopy;
Boolean add_to_browse;
GList gl;
SInt32 offset;
if (copts.cplusplus) {
CDecl_ParseClass(declinfo, structtype, 1, 0);
return;
}
if (tk == TK_IDENTIFIER) {
name = tkidentifier;
type = CScope_GetTagType(cscope_current, name);
if (type) {
if (IS_TYPE_CLASS(type)) {
CDecl_ParseClass(declinfo, structtype, 1, 0);
return;
}
tk = lex();
if (!CScope_GetLocalTagType(cscope_current, name) && (tk == ';' || tk == '{'))
type = (Type *) CDecl_DefineStruct(name, structtype);
if (!IS_TYPE_STRUCT(type) || TYPE_STRUCT(type)->stype != structtype) {
CError_Error(CErrorStr132, name->name);
declinfo->thetype = type;
return;
}
if (tk != '{') {
declinfo->thetype = type;
return;
}
if (type->size) {
CError_Error(CErrorStr132, name->name);
type = (Type *) CDecl_DefineStruct(NULL, structtype);
}
} else {
type = (Type *) CDecl_DefineStruct(name, structtype);
if ((tk = lex()) != '{') {
declinfo->thetype = type;
return;
}
}
} else if (tk != '{') {
CError_Error(CErrorStr131);
declinfo->thetype = (Type *) &stsignedint;
return;
} else {
type = (Type *) CDecl_DefineStruct(NULL, structtype);
}
if ((add_to_browse = cparamblkptr->browseoptions.recordClasses && declinfo->file->recordbrowseinfo))
CBrowse_BeginStruct(declinfo, TYPE_STRUCT(type), &gl);
typecopy = *TYPE_STRUCT(type);
tk = lex();
offset = scanstructdeclarationlist(&typecopy, add_to_browse);
*TYPE_STRUCT(type) = typecopy;
declinfo->thetype = type;
if (add_to_browse)
CBrowse_EndStruct(offset, &gl);
}
static void InlineFunctionObject(Object *obj, TypeClass *tclass) {
TokenStream stream;
CPrepFileInfo *file;
obj->qual |= Q_INLINE;
TYPE_FUNC(obj->type)->flags |= FUNC_FLAGS_2;
CPrep_StreamGetBlock(&stream, NULL, 1);
if (stream.tokens) {
if (IS_TYPEFUNC_METHOD(TYPE_FUNC(obj->type)) && (TYPE_METHOD(obj->type)->theclass->flags & CLASS_FLAGS_100)) {
TYPE_FUNC(obj->type)->flags |= FUNC_FLAGS_800000;
CTemplClass_DefineMember(TEMPL_CLASS(TYPE_METHOD(obj->type)->theclass), obj, &member_fileoffset, &stream);
} else {
CInline_AddInlineFunctionAction(obj, tclass, &member_fileoffset, &stream, 0);
}
}
file = CPrep_BrowserCurrentFile();
if (file->recordbrowseinfo) {
CBrowse_NewFunction(
obj, file,
member_fileoffset.file,
CPrep_BrowserTokenOffset(&member_fileoffset) + 1,
CPrep_BrowserFileOffset());
}
if (lookahead() == ';')
tk = lex();
else
tk = ';';
}
void CDecl_ExtractClassExportFlags(DeclInfo *declinfo, UInt8 flags) {
if (flags & CLASS_EFLAGS_INTERNAL)
declinfo->exportflags |= EXPORT_FLAGS_INTERNAL;
if (flags & CLASS_EFLAGS_IMPORT)
declinfo->exportflags |= EXPORT_FLAGS_IMPORT;
if (flags & CLASS_EFLAGS_EXPORT)
declinfo->exportflags |= EXPORT_FLAGS_EXPORT;
}
TypeMemberFunc *CDecl_MakeTypeMemberFunc(TypeFunc *tfunc, TypeClass *tclass, Boolean flag) {
TypeMemberFunc *method;
method = galloc(sizeof(TypeMemberFunc));
memclrw(method, sizeof(TypeMemberFunc));
*TYPE_FUNC(method) = *tfunc;
method->theclass = tclass;
method->x26 = flag;
method->flags |= FUNC_FLAGS_METHOD;
if (!flag)
CDecl_AddThisPointerArgument(TYPE_FUNC(method), tclass);
if ((flag || (tfunc->flags & (FUNC_FLAGS_1000 | FUNC_FLAGS_2000))) && (tfunc->flags & (FUNC_FLAGS_CONST | FUNC_FLAGS_VOLATILE)))
CError_Error(CErrorStr384);
return method;
}
static void CDecl_MakeFunctionVirtual(TypeClass *tclass, Object *func) {
if (is_pascal_object(func))
CError_Error(CErrorStr219);
if (tclass->mode == CLASS_MODE_1)
CError_Error(CErrorStr352, func);
func->datatype = DVFUNC;
}
static void CDecl_AddFunctionMember(DeclE *decle, TypeClass *tclass, DeclInfo *declinfo, short access, Boolean flag1, Boolean flag2, Boolean flag3, Boolean flag4) {
NameSpaceObjectList *list; // r20
Object *obj; // also r20
TypeMemberFunc *tfunc; // r19
Boolean r31;
Boolean outflag;
if (IS_TYPE_ARRAY(TYPE_FUNC(declinfo->thetype)->functype) || IS_TYPE_FUNC(TYPE_FUNC(declinfo->thetype)->functype)) {
CError_Error(CErrorStr128);
TYPE_FUNC(declinfo->thetype)->functype = (Type *) &stsignedint;
}
if (tclass->sominfo)
CSOM_CheckFuncType(TYPE_FUNC(declinfo->thetype));
r31 = 0;
if (declinfo->qual & Q_VIRTUAL) {
declinfo->qual &= ~Q_VIRTUAL;
r31 = 1;
flag1 = 1;
}
if ((list = CScope_FindName(tclass->nspace, declinfo->name))) {
if (list->object->otype != OT_TYPETAG) {
if (list->object->otype != OT_OBJECT || !IS_TYPE_FUNC(OBJECT(list->object)->type))
CError_Error(CErrorStr133, declinfo->name->name);
} else {
list = NULL;
}
}
if (!IS_TYPEFUNC_METHOD(TYPE_FUNC(declinfo->thetype))) {
tfunc = CDecl_MakeTypeMemberFunc(TYPE_FUNC(declinfo->thetype), tclass, flag4);
declinfo->thetype = (Type *) tfunc;
} else {
tfunc = TYPE_METHOD(declinfo->thetype);
CError_ASSERT(4579, !tclass->sominfo);
}
CDecl_ExtractClassExportFlags(declinfo, tclass->eflags);
CError_ASSERT(4597, cscope_current == tclass->nspace);
if (list) {
obj = CDecl_OverloadFunctionObject(list, declinfo, &outflag, flag4 ? OverloadMode1 : OverloadMode2, 0);
if (!obj)
return;
if (outflag)
tfunc->x1E = ++decle->x8;
else
CError_Error(CErrorStr133, CError_GetObjectName(obj));
} else {
tfunc->x1E = ++decle->x8;
obj = CParser_NewFunctionObject(declinfo);
if ((tclass->flags & CLASS_FLAGS_100) && CTemplTool_IsTemplateArgumentDependentType(declinfo->thetype))
CTemplClass_RegisterObjectDef(TEMPL_CLASS(tclass), OBJ_BASE(obj));
CScope_AddObject(tclass->nspace, declinfo->name, OBJ_BASE(obj));
}
obj->access = access;
CheckDefaultArgs(TYPE_FUNC(obj->type)->args);
if (flag2) {
tfunc->flags |= FUNC_FLAGS_40;
tclass->flags |= CLASS_FLAGS_40;
}
if (r31) {
CDecl_MakeFunctionVirtual(tclass, obj);
decle->xC = 1;
}
if ((flag1 || r31) && flag3 && (tk == '=')) {
if ((tk = lex()) == TK_INTCONST) {
if (!CInt64_IsZero(&tkintconst))
CError_Error(CErrorStr121);
tfunc->flags |= FUNC_FLAGS_8;
tclass->flags |= CLASS_FLAGS_ABSTRACT;
tk = lex();
} else {
CError_Error(CErrorStr121);
}
}
if (flag3 && ((tk == '{') || (tk == TK_TRY) || ((tk == ':') && CClass_IsConstructor(obj)))) {
if (declinfo->x49)
CError_Error(CErrorStr127);
InlineFunctionObject(obj, NULL);
}
if (cparamblkptr->browseoptions.recordClasses)
CBrowse_AddClassMemberFunction(obj, CPrep_BrowserTokenOffset(&member_fileoffset) + 1, CPrep_BrowserFileOffset());
}
static Boolean CDecl_IsAccessDeclaration(TypeClass *tclass, short access) {
SInt32 state;
Boolean flag;
CPrep_TokenStreamGetState(&state);
flag = 0;
restart:
switch (tk) {
case TK_IDENTIFIER:
if ((tk = lex()) != ';')
break;
case TK_OPERATOR:
CPrep_TokenStreamSetCurState(&state);
if (flag) {
CScope_ParseUsingDeclaration(tclass->nspace, access, 1);
return 1;
}
return 0;
default:
CPrep_TokenStreamSetCurState(&state);
return 0;
}
switch (tk) {
case TK_COLON_COLON:
flag = 1;
tk = lex();
goto restart;
case '<':
tk = lex();
while (1) {
switch (tk) {
case 0:
case ';':
case '{':
case '}':
CPrep_TokenStreamSetCurState(&state);
return 0;
case '>':
if ((tk = lex()) == TK_COLON_COLON) {
flag = 1;
tk = lex();
goto restart;
}
default:
tk = lex();
}
}
}
CPrep_TokenStreamSetCurState(&state);
return 0;
}
void CDecl_PackDeclInfo(PackedDeclInfo *packed, DeclInfo *declinfo) {
packed->thetype = declinfo->thetype;
packed->qual = declinfo->qual;
packed->nspace = declinfo->nspace;
packed->name = declinfo->name;
packed->expltargs = CTemplTool_MakeGlobalTemplArgCopy(declinfo->expltargs);
packed->storageclass = declinfo->storageclass;
packed->section = declinfo->section;
packed->exportflags = declinfo->exportflags;
packed->has_expltargs = declinfo->has_expltargs;
}
void CDecl_UnpackDeclInfo(DeclInfo *declinfo, PackedDeclInfo *packed) {
memclrw(declinfo, sizeof(DeclInfo));
declinfo->thetype = packed->thetype;
declinfo->qual = packed->qual;
declinfo->nspace = packed->nspace;
declinfo->name = packed->name;
declinfo->expltargs = packed->expltargs;
declinfo->storageclass = packed->storageclass;
declinfo->section = packed->section;
declinfo->exportflags = packed->exportflags;
declinfo->has_expltargs = packed->has_expltargs;
}
void CDecl_AddFriend(TypeClass *tclass, Object *friendfunc, TypeClass *friendclass) {
ClassFriend *scan;
ClassFriend *newfriend;
if (friendfunc) {
for (scan = tclass->friends; scan; scan = scan->next) {
if (!scan->isclass && scan->u.obj == friendfunc)
break;
}
if (!scan) {
newfriend = galloc(sizeof(ClassFriend));
memclrw(newfriend, sizeof(ClassFriend));
newfriend->next = tclass->friends;
tclass->friends = newfriend;
newfriend->u.obj = friendfunc;
newfriend->isclass = 0;
}
}
if (friendclass) {
for (scan = tclass->friends; scan; scan = scan->next) {
if (scan->isclass && scan->u.theclass == friendclass)
break;
}
if (!scan) {
newfriend = galloc(sizeof(ClassFriend));
memclrw(newfriend, sizeof(ClassFriend));
newfriend->next = tclass->friends;
tclass->friends = newfriend;
newfriend->u.theclass = friendclass;
newfriend->isclass = 1;
}
}
}
static void CDecl_ParseFriendDecl(TypeClass *tclass) {
DeclInfo declinfo;
DeclInfo declinfo_copy;
Boolean is_templ;
Boolean r27;
Boolean pflag;
CScopeSave save;
Object *obj;
NameSpace *nspace;
is_templ = (tclass->flags & CLASS_FLAGS_100) ? 1 : 0;
r27 = (tk == TK_CLASS || tk == TK_STRUCT || tk == TK_UNION);
memclrw(&declinfo, sizeof(DeclInfo));
declinfo.x4C = 1;
CParser_GetDeclSpecs(&declinfo, 1);
if (declinfo.storageclass) {
CError_Error(CErrorStr177);
declinfo.storageclass = 0;
}
declinfo.x4C = 0;
if (tk == ';') {
if (!r27)
CError_Error(CErrorStr201);
if (IS_TYPE_CLASS(declinfo.thetype)) {
if (!(TYPE_CLASS(declinfo.thetype)->flags & CLASS_FLAGS_100) || CParser_CheckTemplateClassUsage(TEMPL_CLASS(declinfo.thetype), 1)) {
if (!is_templ)
CDecl_AddFriend(tclass, NULL, TYPE_CLASS(declinfo.thetype));
else
CTemplClass_RegisterFriend(TEMPL_CLASS(tclass), &declinfo);
}
} else {
if (IS_TYPE_TEMPLATE(declinfo.thetype) && is_templ)
CTemplClass_RegisterFriend(TEMPL_CLASS(tclass), &declinfo);
else
CError_Error(CErrorStr201);
}
} else {
if (declinfo.x14 || declinfo.x10) {
CDecl_ParseSpecialMember(&declinfo, 0);
if (declinfo.name) {
obj = CDecl_GetFunctionObject(&declinfo, NULL, &pflag, 0);
if (obj)
CDecl_AddFriend(tclass, obj, NULL);
if (tk != ';')
CError_Error(CErrorStr123);
else
tk = lex();
}
return;
} else {
nspace = CScope_FindGlobalNS(cscope_current);
declinfo_copy = declinfo;
while (1) {
declinfo = declinfo_copy;
declinfo.x4D = 1;
declinfo.x51 = 1;
scandeclarator(&declinfo);
if (IS_TYPE_FUNC(declinfo.thetype)) {
if (!is_templ) {
CScope_SetNameSpaceScope(nspace, &save);
obj = CDecl_GetFunctionObject(&declinfo, NULL, &pflag, 0);
CScope_RestoreScope(&save);
if (obj) {
CDecl_AddFriend(tclass, obj, NULL);
if (!declinfo.nspace && tk == '{') {
InlineFunctionObject(obj, tclass);
} else {
if (!obj->sclass)
obj->sclass = TK_EXTERN;
}
}
} else {
CTemplClass_RegisterFriend(TEMPL_CLASS(tclass), &declinfo);
}
} else {
CError_Error(CErrorStr201);
}
if (tk != ',')
break;
tk = lex();
}
}
}
if (tk == ';')
tk = lex();
else
CError_Error(CErrorStr123);
}
static ObjMemberVar *CDecl_InstanceDataDeclarator(DeclE *decle, TypeClass *tclass, Type *type, UInt32 qual, HashNameNode *name, short access) {
NameSpaceObjectList *list;
ObjMemberVar *ivar;
ObjMemberVar *scan;
if (name && (list = CScope_FindName(tclass->nspace, name))) {
switch (list->object->otype) {
case OT_NAMESPACE:
CError_Error(CErrorStr321);
return NULL;
case OT_ENUMCONST:
case OT_TYPE:
case OT_OBJECT:
CError_Error(CErrorStr322);
return NULL;
case OT_MEMBERVAR:
CError_Error(CErrorStr122, name->name);
return NULL;
case OT_TYPETAG:
break;
default:
CError_FATAL(4989);
}
}
ivar = galloc(sizeof(ObjMemberVar));
memclrw(ivar, sizeof(ObjMemberVar));
ivar->otype = OT_MEMBERVAR;
ivar->access = access;
ivar->name = name;
ivar->type = type;
ivar->qual = qual;
if (!tclass->sominfo)
decle->x8++;
if ((scan = tclass->ivars)) {
while (scan->next)
scan = scan->next;
scan->next = ivar;
} else {
tclass->ivars = ivar;
}
if (name && name != no_name_node) {
CScope_AddObject(tclass->nspace, name, OBJ_BASE(ivar));
if ((tclass->flags & CLASS_FLAGS_100) && CTemplTool_IsTemplateArgumentDependentType(type))
CTemplClass_RegisterObjectDef(TEMPL_CLASS(tclass), OBJ_BASE(ivar));
if (cparamblkptr->browseoptions.recordClasses)
CBrowse_AddClassMemberVar(ivar, CPrep_BrowserTokenOffset(&member_fileoffset) + 1, CPrep_BrowserFileOffset());
}
return ivar;
}
void CDecl_CheckCtorIntegrity(FuncArg *args, TypeClass *tclass) {
if (args && args->type == TYPE(tclass)) {
if (!args->next || args->next->dexpr) {
CError_Error(CErrorStr239);
args->type = &stvoid;
}
}
}
static void CDecl_ParseClassMembers(DeclE *decle, TypeClass *tclass, short mode) {
short access;
UInt32 r22;
UInt32 r21;
UInt8 r20;
Boolean r19;
UInt8 r18;
Boolean r17;
BigDeclInfo bde;
DeclInfo declinfo;
//Type *newtype
ObjMemberVar *ivar;
ObjMemberVar *scanivar;
Type *tmptype;
short t;
r17 = (tclass->flags & CLASS_FLAGS_100) && TEMPL_CLASS(tclass)->pspec_owner;
memclrw(&bde, sizeof(BigDeclInfo));
if (mode == CLASS_MODE_2)
access = ACCESSPRIVATE;
else
access = ACCESSPUBLIC;
global_access = access;
//global_access = (mode == CLASS_MODE_2) ? ACCESSPRIVATE : ACCESSPUBLIC;
//access = (mode == CLASS_MODE_2) ? ACCESSPRIVATE : ACCESSPUBLIC;
restart:
while (tk != '}') {
CPrep_NewFileOffsetInfo(&member_fileoffset, NULL);
r21 = 0;
r22 = 0;
r20 = 0;
r18 = 0;
if (tk == TK_TEMPLATE) {
NameSpace *nspace = cscope_current;
TemplClass *tmclass;
if (nspace->theclass && (nspace->theclass->flags & CLASS_FLAGS_100)) {
tmclass = TEMPL_CLASS(nspace->theclass);
} else {
for (; nspace; nspace = nspace->parent) {
if (!nspace->name && !nspace->theclass && nspace->parent && !nspace->is_templ) {
CError_Error(CErrorStr347);
break;
}
}
}
CTempl_Parse(TEMPL_CLASS(tclass), access);
tk = lex();
continue;
}
restart2:
r19 = 0;
switch (tk) {
case TK_UU_DECLSPEC:
if ((tk = lex()) != '(')
CError_Error(CErrorStr114);
memclrw(&declinfo, sizeof(DeclInfo));
CParser_ParseDeclSpec(&declinfo, 1);
r21 |= declinfo.qual;
r20 |= declinfo.exportflags;
r18 = declinfo.section;
if ((tk = lex()) != ')')
CError_Error(CErrorStr115);
tk = lex();
goto restart2;
case TK_PRIVATE:
global_access = access = ACCESSPRIVATE;
goto check_access;
case TK_PROTECTED:
global_access = access = ACCESSPROTECTED;
goto check_access;
case TK_PUBLIC:
global_access = access = ACCESSPUBLIC;
check_access:
if (r22 || r20)
CError_Error(CErrorStr121);
if ((tk = lex()) != ':')
CError_Error(CErrorStr170);
else
tk = lex();
goto restart;
case TK_EXPLICIT:
CError_QualifierCheck(r22 & Q_EXPLICIT);
r22 |= Q_EXPLICIT;
tk = lex();
goto restart2;
case TK_INLINE:
CError_QualifierCheck(r22 & Q_INLINE);
r22 |= Q_INLINE;
tk = lex();
goto restart2;
case TK_ASM:
CError_QualifierCheck(r22 & Q_ASM);
r22 |= Q_ASM;
tk = lex();
goto restart2;
case TK_VIRTUAL:
CError_QualifierCheck(r22 & Q_VIRTUAL);
r22 |= Q_VIRTUAL;
tk = lex();
goto restart2;
case TK_IDENTIFIER:
while (1) {
if (tkidentifier == tclass->classname) {
t = lookahead();
tkidentifier = tclass->classname;
r19 = 1;
if (copts.cpp_extensions && t == TK_COLON_COLON) {
lex();
tk = lex();
if (tk == TK_IDENTIFIER)
continue;
if (tk == '~')
goto restart2;
CError_Error(CErrorStr107);
}
if (t == '(') {
redo_thing:
CError_QualifierCheck(r22 & ~(Q_EXPLICIT | Q_INLINE | Q_ASM));
memclrw(&bde.declinfo2, sizeof(DeclInfo));
if (tclass->sominfo)
bde.declinfo2.thetype = &stvoid;
else
bde.declinfo2.thetype = TYPE(&void_ptr);
bde.declinfo2.qual = r22;
bde.declinfo2.exportflags = r20;
bde.declinfo2.section = r18;
bde.declinfo2.x4B = 1;
scandeclarator(&bde.declinfo2);
if (IS_TYPE_FUNC(bde.declinfo2.thetype)) {
if (r17)
bde.declinfo2.thetype = CTemplTool_ResolveMemberSelfRefs(TEMPL_CLASS(tclass), bde.declinfo2.thetype, &bde.declinfo2.qual);
if (tclass->sominfo) {
if (TYPE_FUNC(bde.declinfo2.thetype)->args)
CError_Error(CErrorStr272);
bde.declinfo2.qual |= Q_VIRTUAL;
} else {
CDecl_CheckCtorIntegrity(TYPE_FUNC(bde.declinfo2.thetype)->args, tclass);
if (tclass->flags & CLASS_FLAGS_20)
CDecl_AddArgument(TYPE_FUNC(bde.declinfo2.thetype), TYPE(&stsignedshort));
bde.declinfo2.qual &= ~Q_VIRTUAL;
}
TYPE_FUNC(bde.declinfo2.thetype)->flags |= FUNC_FLAGS_1000;
bde.declinfo2.name = constructor_name_node;
bde.declinfo2.qual |= r21;
CDecl_AddFunctionMember(decle, tclass, &bde.declinfo2, access, 0, 0, 1, 0);
} else {
CError_Error(CErrorStr241);
}
if (tk == ';')
tk = lex();
else
CError_Error(CErrorStr123);
goto restart;
}
}
// 6F8D8
if (!r22 && CDecl_IsAccessDeclaration(tclass, access)) {
tk = lex();
goto restart;
}
break;
}
break;
case TK_USING:
CError_QualifierCheck(r22);
tk = lex();
CScope_ParseUsingDeclaration(tclass->nspace, access, 0);
tk = lex();
goto restart;
case '~':
if ((tk = lex()) != TK_IDENTIFIER || tkidentifier != tclass->classname) {
CError_Error(CErrorStr241);
goto restart;
}
CError_QualifierCheck(r22 & ~(Q_VIRTUAL | Q_INLINE | Q_ASM));
if (tclass->flags & CLASS_FLAGS_900) {
t = lookahead();
tkidentifier = tclass->classname;
if (t == '<') {
memclrw(&bde.declinfo, sizeof(DeclInfo));
CParser_GetDeclSpecs(&bde.declinfo, 0);
if (tk != '(' || bde.declinfo.thetype != TYPE(tclass) || bde.declinfo.nspace) {
CError_Error(CErrorStr241);
goto restart;
}
CPrep_UnLex();
tk = TK_IDENTIFIER;
tkidentifier = tclass->classname;
}
}
memclrw(&bde.declinfo2, sizeof(DeclInfo));
bde.declinfo2.qual = r22;
bde.declinfo2.exportflags = r20;
bde.declinfo2.section = r18;
if (tclass->sominfo)
bde.declinfo2.thetype = &stvoid;
else
bde.declinfo2.thetype = TYPE(&void_ptr);
scandeclarator(&bde.declinfo2);
if (IS_TYPE_FUNC(bde.declinfo2.thetype) && !TYPE_FUNC(bde.declinfo2.thetype)->args) {
if (!CScope_FindName(tclass->nspace, destructor_name_node)) {
if (tclass->sominfo)
bde.declinfo2.qual |= Q_VIRTUAL;
else
CDecl_AddArgument(TYPE_FUNC(bde.declinfo2.thetype), TYPE(&stsignedshort));
bde.declinfo2.name = destructor_name_node;
TYPE_FUNC(bde.declinfo2.thetype)->flags |= FUNC_FLAGS_2000;
bde.declinfo2.qual |= r21;
CDecl_AddFunctionMember(decle, tclass, &bde.declinfo2, access, 1, 0, 1, 0);
} else {
CError_Error(CErrorStr133, CError_GetFunctionName(tclass->nspace, destructor_name_node, NULL));
}
} else {
CError_Error(CErrorStr146);
}
if (tk == ';')
tk = lex();
else
CError_Error(CErrorStr123);
goto restart;
case TK_OPERATOR:
if (CMangler_OperatorName(lookahead())) {
memclrw(&bde.declinfo, sizeof(DeclInfo));
bde.declinfo.thetype = TYPE(&stsignedint);
goto after_various_things;
} else {
tk = lex();
CError_QualifierCheck(r22 & ~(Q_VIRTUAL | Q_INLINE | Q_ASM));
memclrw(&bde.declinfo2, sizeof(DeclInfo));
bde.declinfo2.qual = r22;
bde.declinfo2.exportflags = r20;
bde.declinfo2.section = r18;
conversion_type_name(&bde.declinfo2);
bde.declinfo2.qual |= r21;
tmptype = bde.declinfo2.thetype;
CDecl_NewConvFuncType(&bde.declinfo2);
if ((tclass->flags & CLASS_FLAGS_100) && CTemplTool_IsTemplateArgumentDependentType(tmptype))
bde.declinfo2.name = CParser_GetUniqueName();
CDecl_AddFunctionMember(decle, tclass, &bde.declinfo2, access, 1, 1, 1, 0);
if (tk == ';')
tk = lex();
else
CError_Error(CErrorStr123);
goto restart;
}
case TK_FRIEND:
tk = lex();
CDecl_ParseFriendDecl(tclass);
goto restart;
}
CError_QualifierCheck(r22 & Q_EXPLICIT);
global_access = access;
memclrw(&bde.declinfo, sizeof(DeclInfo));
bde.declinfo.qual = r22;
bde.declinfo.exportflags = r20;
bde.declinfo.section = r18;
CParser_GetDeclSpecs(&bde.declinfo, 0);
if (r19 && tk == '(' && (tclass->flags & CLASS_FLAGS_900) && bde.declinfo.thetype == TYPE(tclass) && !bde.declinfo.nspace) {
CPrep_UnLex();
tk = TK_IDENTIFIER;
tkidentifier = tclass->classname;
r22 = bde.declinfo.qual;
goto redo_thing;
}
after_various_things:
switch (bde.declinfo.storageclass) {
case 0:
case TK_STATIC:
case TK_TYPEDEF:
case TK_MUTABLE:
break;
default:
CError_Error(CErrorStr177);
bde.declinfo.storageclass = 0;
}
if (tk != ';') {
while (1) {
CDecl_ScanStructDeclarator(&bde);
if (r17)
bde.declinfo2.thetype = CTemplTool_ResolveMemberSelfRefs(TEMPL_CLASS(tclass), bde.declinfo2.thetype, &bde.declinfo2.qual);
if (bde.declinfo2.nspace)
CError_Error(CErrorStr200);
if (bde.declinfo2.x3E) {
if (bde.declinfo.storageclass == TK_MUTABLE)
CError_QualifierCheck(Q_MUTABLE);
r19 = 0;
switch (bde.declinfo2.x3E) {
case TK_NEW:
case TK_NEW_ARRAY:
CError_QualifierCheck(bde.declinfo2.qual & Q_VIRTUAL);
r19 = 1;
break;
case TK_DELETE:
case TK_DELETE_ARRAY:
CError_QualifierCheck(bde.declinfo2.qual & Q_VIRTUAL);
r19 = 1;
break;
default:
if (bde.declinfo2.storageclass == TK_STATIC)
CError_Error(CErrorStr193);
if (tclass->sominfo)
CError_Error(CErrorStr193);
}
bde.declinfo2.storageclass = 0;
if (IS_TYPE_FUNC(bde.declinfo2.thetype)) {
bde.declinfo2.qual |= r21;
CDecl_AddFunctionMember(decle, tclass, &bde.declinfo2, access, r19 == 0, 0, 1, r19);
CDecl_CheckOperatorType(&bde.declinfo2, 1);
if (tclass->sominfo)
CSOM_FixNewDeleteFunctype(TYPE_FUNC(bde.declinfo2.thetype));
} else {
CError_Error(CErrorStr121);
}
} else if (bde.xCD) {
if (bde.declinfo2.name == constructor_name_node || bde.declinfo2.name == destructor_name_node)
CError_Error(CErrorStr241);
switch (bde.declinfo2.storageclass) {
case TK_TYPEDEF:
CError_QualifierCheck(bde.declinfo2.qual & Q_VIRTUAL);
CDecl_TypedefDeclarator(&bde.declinfo2);
break;
case TK_STATIC:
CError_QualifierCheck(bde.declinfo2.qual & Q_VIRTUAL);
if (tclass->sominfo)
CError_Error(CErrorStr271);
if (IS_TYPE_FUNC(bde.declinfo2.thetype)) {
bde.declinfo2.qual |= r21;
bde.declinfo2.storageclass = 0;
if (bde.declinfo2.name == tclass->classname)
CError_Error(CErrorStr241);
CDecl_AddFunctionMember(decle, tclass, &bde.declinfo2, access, 0, 0, 1, 1);
} else {
CDecl_ExtractClassExportFlags(&bde.declinfo2, tclass->eflags);
bde.declinfo2.storageclass = 0;
CDecl_DataDeclarator(&bde.declinfo2, access, 1);
}
break;
case 0:
case TK_MUTABLE:
if (IS_TYPE_FUNC(bde.declinfo2.thetype)) {
if (bde.declinfo2.name == tclass->classname)
CError_Error(CErrorStr241);
if (bde.declinfo.storageclass == TK_MUTABLE)
CError_QualifierCheck(Q_MUTABLE);
bde.declinfo2.qual |= r21;
CDecl_AddFunctionMember(decle, tclass, &bde.declinfo2, access, 1, 0, 1, 0);
} else {
CDecl_CompleteType(bde.declinfo2.thetype);
CanCreateObject(bde.declinfo2.thetype);
CError_QualifierCheck(bde.declinfo2.qual & (Q_VIRTUAL | Q_INLINE));
if (bde.declinfo2.storageclass == TK_MUTABLE)
bde.declinfo2.qual |= Q_MUTABLE;
CDecl_InstanceDataDeclarator(decle, tclass, bde.declinfo2.thetype, bde.declinfo2.qual, bde.declinfo2.name, access);
}
break;
default:
CError_Error(CErrorStr177);
}
}
// this should be 70058
if (tk != ',')
break; // goes to 70148
tk = lex();
}
} else if (CParser_IsAnonymousUnion(&bde.declinfo, 1)) {
if ((ivar = CDecl_InstanceDataDeclarator(decle, tclass, bde.declinfo.thetype, 0, NULL, access)))
ivar->anonunion = 1;
for (scanivar = TYPE_CLASS(bde.declinfo.thetype)->ivars; scanivar; scanivar = scanivar->next) {
tmptype = scanivar->type;
if (IS_TYPE_BITFIELD(tmptype) && copts.reverse_bitfields) {
TypeBitfield *newtype = galloc(sizeof(TypeBitfield));
*newtype = *TYPE_BITFIELD(tmptype);
CABI_ReverseBitField(newtype);
tmptype = TYPE(newtype);
}
if ((ivar = CDecl_InstanceDataDeclarator(decle, tclass, tmptype, scanivar->qual, scanivar->name, access)))
ivar->offset = scanivar->offset | 0x80000000;
}
}
// this should be 70148 i think
if (tk != ';') {
CError_Error(CErrorStr123);
return;
}
CPrep_TokenStreamFlush();
tk = lex();
}
}
static VClassList *AddVBaseToList(TypeClass *tclass, TypeClass *baseclass) {
VClassList *scan;
VClassList *vbase;
for (scan = tclass->vbases; scan; scan = scan->next) {
if (scan->base == baseclass)
return NULL;
}
vbase = galloc(sizeof(VClassList));
memclrw(vbase, sizeof(VClassList));
vbase->base = baseclass;
if ((scan = tclass->vbases)) {
while (scan->next)
scan = scan->next;
scan->next = vbase;
} else {
tclass->vbases = vbase;
}
return vbase;
}
void CDecl_MakeVBaseList(TypeClass *tclass) {
ClassList *base;
VClassList *vbase;
VClassList *new_vbase;
SInt32 offset;
if (copts.vbase_ctor_offset)
tclass->flags |= CLASS_FLAGS_8000;
for (base = tclass->bases, offset = tclass->size; base; base = base->next) {
for (vbase = base->base->vbases; vbase; vbase = vbase->next) {
if ((new_vbase = AddVBaseToList(tclass, vbase->base))) {
new_vbase->offset = offset + CMach_MemberAlignValue(TYPE(vbase->base), offset);
offset = new_vbase->offset + vbase->base->size;
}
}
if (base->is_virtual && (new_vbase = AddVBaseToList(tclass, base->base))) {
new_vbase->offset = offset + CMach_MemberAlignValue(TYPE(base->base), offset);
offset = new_vbase->offset + base->base->size;
}
}
}
Boolean CDecl_CheckNewBase(TypeClass *tclass, TypeClass *baseclass, Boolean is_virtual) {
ClassList *scan;
if (tclass == baseclass) {
CError_Error(CErrorStr131);
return 0;
}
if (!(baseclass->flags & CLASS_FLAGS_2)) {
CError_Error(CErrorStr136, baseclass, 0);
return 0;
}
if (baseclass->flags & CLASS_FLAGS_10) {
if (is_virtual || tclass->bases) {
CError_Error(CErrorStr191);
return 0;
}
tclass->flags |= CLASS_FLAGS_10;
}
if (baseclass->flags & CLASS_FLAGS_1) {
if (is_virtual || tclass->bases) {
CError_Error(CErrorStr191);
return 0;
}
tclass->flags |= CLASS_FLAGS_1;
}
if (baseclass->sominfo) {
if (!is_virtual)
CError_Error(CErrorStr268);
CSOM_MakeSOMClass(tclass);
} else if (tclass->sominfo) {
CError_Error(CErrorStr267);
}
if (tclass->bases && (tclass->flags & CLASS_FLAGS_10) && (tclass->flags & CLASS_FLAGS_10)) {
CError_Error(CErrorStr131);
return 0;
}
if (copts.ecplusplus && (is_virtual || tclass->bases)) {
CError_Error(CErrorStr339);
return 0;
}
for (scan = tclass->bases; scan; scan = scan->next) {
if (scan->base == baseclass) {
CError_Error(CErrorStr131);
return 0;
}
}
if (baseclass->flags & CLASS_FLAGS_2000)
tclass->flags |= CLASS_FLAGS_2000;
if (baseclass->flags & CLASS_FLAGS_40)
tclass->flags |= CLASS_FLAGS_40;
if (baseclass->flags & CLASS_FLAGS_20)
tclass->flags |= CLASS_FLAGS_20;
if (is_virtual)
tclass->flags |= CLASS_FLAGS_20;
return 1;
}
static void CDecl_ParseBaseClassList(TypeClass *tclass, short mode, Boolean is_templ) {
Boolean is_virtual;
short access;
CScopeParseResult pr;
ObjType *inherited_type;
ClassList *base;
ClassList *scan;
TypeClass *baseclass;
do {
if (mode == CLASS_MODE_2)
access = ACCESSPRIVATE;
else
access = ACCESSPUBLIC;
is_virtual = 0;
if ((tk = lex()) == TK_VIRTUAL) {
tk = lex();
is_virtual = 1;
}
switch (tk) {
case TK_PRIVATE:
access = ACCESSPRIVATE;
tk = lex();
break;
case TK_PUBLIC:
access = ACCESSPUBLIC;
tk = lex();
break;
case TK_PROTECTED:
if (!copts.ARMconform) {
access = ACCESSPROTECTED;
tk = lex();
}
break;
}
if (tk == TK_VIRTUAL) {
if (is_virtual)
CError_Error(CErrorStr121);
is_virtual = 1;
tk = lex();
}
if (CScope_ParseDeclName(&pr)) {
if (!pr.x8) {
if (!pr.name_4) {
CError_Error(CErrorStr121);
} else if (tk == TK_IDENTIFIER && pr.name_4 == tkidentifier) {
goto special_parsing;
}
CError_Error(CErrorStr140, tkidentifier->name);
continue;
}
CDecl_CompleteType(pr.x8);
if (is_templ && CTemplTool_IsTemplateArgumentDependentType(pr.x8)) {
if (!IS_TYPE_CLASS(pr.x8) || !(TYPE_CLASS(pr.x8)->flags & CLASS_FLAGS_100) ||
CParser_CheckTemplateClassUsage(TEMPL_CLASS(pr.x8), 1)) {
CTemplClass_RegisterBaseClass(TEMPL_CLASS(tclass), pr.x8, access, is_virtual);
if (is_virtual)
tclass->flags |= CLASS_FLAGS_20;
}
continue;
}
if (!IS_TYPE_CLASS(pr.x8) || (TYPE_CLASS(pr.x8)->flags & CLASS_FLAGS_100)) {
CError_Error(CErrorStr131);
continue;
}
baseclass = TYPE_CLASS(pr.x8);
} else {
special_parsing:
if (!strcmp(tkidentifier->name, "HandleObject")) {
if (tclass->bases)
CError_Error(CErrorStr191);
tclass->flags |= CLASS_FLAGS_10 | CLASS_FLAGS_1;
tk = lex();
break;
}
if (!strcmp(tkidentifier->name, "SingleObject") || !strcmp(tkidentifier->name, "SingleInheritance")) {
if (tclass->bases)
CError_Error(CErrorStr191);
tclass->flags |= CLASS_FLAGS_10;
tk = lex();
break;
}
if (!strcmp(tkidentifier->name, "__comobject")) {
tclass->flags |= CLASS_FLAGS_2000;
tk = lex();
break;
}
if (!strcmp(tkidentifier->name, "__somobject")) {
if (!is_virtual)
CError_Error(CErrorStr268);
CSOM_MakeSOMClass(tclass);
tk = lex();
break;
}
if (!strcmp(tkidentifier->name, "__javaobject")) {
tk = lex();
tclass->action = CLASS_ACTION_3;
break;
}
CError_Error(CErrorStr140, tkidentifier->name);
continue;
}
if (CDecl_CheckNewBase(tclass, baseclass, is_virtual)) {
base = galloc(sizeof(ClassList));
memclrw(base, sizeof(ClassList));
base->base = baseclass;
base->access = access;
base->is_virtual = is_virtual;
if ((scan = tclass->bases)) {
while (scan->next)
scan = scan->next;
scan->next = base;
} else {
tclass->bases = base;
}
}
} while ((tk = lex()) == ',');
if (tclass->flags & CLASS_FLAGS_20)
CDecl_MakeVBaseList(tclass);
if (copts.def_inherited && tclass->bases && !tclass->bases->next) {
inherited_type = galloc(sizeof(ObjType));
memclrw(inherited_type, sizeof(ObjType));
inherited_type->otype = OT_TYPE;
inherited_type->access = ACCESSPUBLIC;
inherited_type->type = TYPE(tclass->bases->base);
CScope_AddObject(tclass->nspace, GetHashNameNodeExport("inherited"), OBJ_BASE(inherited_type));
}
}
static short getaccesstype(AccessType a, AccessType b, AccessType c) {
if (a == ACCESSNONE || b == ACCESSNONE || b == ACCESSPRIVATE)
return ACCESSNONE;
if (c == ACCESSPUBLIC && b != ACCESSPUBLIC)
return ACCESSNONE;
return ACCESSPUBLIC;
}
static TypeMemberFunc *CDecl_MakeDefaultCtorType(TypeClass *tclass) {
TypeMemberFunc *tmeth = galloc(sizeof(TypeMemberFunc));
memclrw(tmeth, sizeof(TypeMemberFunc));
tmeth->type = TYPEFUNC;
tmeth->functype = TYPE(&void_ptr);
tmeth->flags = FUNC_FLAGS_1000 | FUNC_FLAGS_100 | FUNC_FLAGS_METHOD;
tmeth->theclass = tclass;
CDecl_SetFuncFlags(TYPE_FUNC(tmeth), 1);
if (tclass->flags & CLASS_FLAGS_20)
CDecl_AddArgument(TYPE_FUNC(tmeth), TYPE(&stsignedshort));
CDecl_AddThisPointerArgument(TYPE_FUNC(tmeth), tclass);
return tmeth;
}
static void CDecl_AddDefArgConstructor(TypeClass *tclass) {
// empty
}
static void CDecl_AddMemberFunctionObject(TypeClass *tclass, HashNameNode *name, TypeMemberFunc *tmeth, short access) {
Object *obj = CParser_NewCompilerDefFunctionObject();
obj->name = name;
obj->type = TYPE(tmeth);
obj->qual = Q_80000;
obj->access = access;
obj->nspace = tclass->nspace;
obj->qual |= Q_INLINE;
CScope_AddObject(tclass->nspace, obj->name, OBJ_BASE(obj));
}
static void CDecl_AddDefaultConstructor(DeclE *decle, TypeClass *tclass) {
ClassList *base;
ObjMemberVar *ivar;
Object *obj;
Boolean has_ctor;
if (CClass_Constructor(tclass)) {
CDecl_AddDefArgConstructor(tclass);
return;
}
has_ctor = 0;
if (tclass->flags & CLASS_FLAGS_20)
has_ctor = 1;
if (decle->xC)
has_ctor = 1;
for (base = tclass->bases; base; base = base->next) {
if (CClass_Constructor(base->base))
has_ctor = 1;
}
for (ivar = tclass->ivars; ivar; ivar = ivar->next) {
Type *type = ivar->type;
while (IS_TYPE_ARRAY(type))
type = TYPE_POINTER(type)->target;
if (IS_TYPE_CLASS(type) && CClass_Constructor(TYPE_CLASS(type)))
has_ctor = 1;
}
if (has_ctor) {
CDecl_AddMemberFunctionObject(
tclass,
constructor_name_node,
CDecl_MakeDefaultCtorType(tclass),
ACCESSPUBLIC
);
}
}
static TypeMemberFunc *CDecl_MakeCopyCtorType(TypeClass *tclass, Boolean is_const) {
FuncArg *arg;
TypeMemberFunc *tmeth = galloc(sizeof(TypeMemberFunc));
memclrw(tmeth, sizeof(TypeMemberFunc));
tmeth->type = TYPEFUNC;
tmeth->functype = TYPE(&void_ptr);
tmeth->flags = FUNC_FLAGS_1000 | FUNC_FLAGS_100 | FUNC_FLAGS_METHOD;
tmeth->theclass = tclass;
CDecl_SetFuncFlags(TYPE_FUNC(tmeth), 1);
arg = CParser_NewFuncArg();
if (is_const)
arg->qual = Q_CONST;
arg->type = CDecl_NewRefPointerType(TYPE(tclass));
tmeth->args = arg;
if (tclass->flags & CLASS_FLAGS_20)
CDecl_AddArgument(TYPE_FUNC(tmeth), TYPE(&stsignedshort));
CDecl_AddThisPointerArgument(TYPE_FUNC(tmeth), tclass);
return tmeth;
}
static void CDecl_AddDefaultCopyConstructor(DeclE *decle, TypeClass *tclass) {
ClassList *base;
ObjMemberVar *ivar;
Object *obj;
short access;
Boolean has_copyctor;
Boolean is_const;
FuncArg *arg;
if (CClass_CopyConstructor(tclass))
return;
access = ACCESSPUBLIC;
is_const = 1;
has_copyctor = 0;
if (CClass_Constructor(tclass))
has_copyctor = 1;
if ((tclass->flags & CLASS_FLAGS_20) || decle->xC)
has_copyctor = 1;
for (base = tclass->bases; base; base = base->next) {
if ((obj = CClass_CopyConstructor(base->base))) {
has_copyctor = 1;
access = getaccesstype(access, obj->access, ACCESSPRIVATE);
arg = TYPE_FUNC(obj->type)->args->next;
if (base->base->flags & CLASS_FLAGS_20)
arg = arg->next;
if (!(arg->qual & Q_CONST))
is_const = 0;
}
}
for (ivar = tclass->ivars; ivar; ivar = ivar->next) {
Type *type = ivar->type;
while (IS_TYPE_ARRAY(type))
type = TYPE_POINTER(type)->target;
if (IS_TYPE_CLASS(type) && (obj = CClass_CopyConstructor(TYPE_CLASS(type)))) {
has_copyctor = 1;
access = getaccesstype(access, obj->access, ACCESSPUBLIC);
arg = TYPE_FUNC(obj->type)->args->next;
if (TYPE_CLASS(type)->flags & CLASS_FLAGS_20)
arg = arg->next;
if (!(arg->qual & Q_CONST))
is_const = 0;
}
}
if (has_copyctor) {
CDecl_AddMemberFunctionObject(
tclass,
constructor_name_node,
CDecl_MakeCopyCtorType(tclass, is_const),
access
);
}
}
static TypeMemberFunc *CDecl_MakeAssignmentOperatorType(TypeClass *tclass, Boolean is_const) {
FuncArg *arg;
TypeMemberFunc *tmeth = galloc(sizeof(TypeMemberFunc));
memclrw(tmeth, sizeof(TypeMemberFunc));
tmeth->type = TYPEFUNC;
tmeth->functype = CDecl_NewRefPointerType(TYPE(tclass));
tmeth->flags = FUNC_FLAGS_100 | FUNC_FLAGS_METHOD;
tmeth->theclass = tclass;
CDecl_SetFuncFlags(TYPE_FUNC(tmeth), 1);
arg = CParser_NewFuncArg();
if (is_const)
arg->qual = Q_CONST;
arg->type = CDecl_NewRefPointerType(TYPE(tclass));
tmeth->args = arg;
CDecl_AddThisPointerArgument(TYPE_FUNC(tmeth), tclass);
return tmeth;
}
static void CDecl_AddDefaultAssignmentOperator(DeclE *decle, TypeClass *tclass) {
ClassList *base;
ObjMemberVar *ivar;
Object *obj;
short access;
Boolean is_const;
Boolean has_ass;
DeclInfo declinfo;
is_const = 1;
has_ass = 0;
access = ACCESSPUBLIC;
if (!CClass_AssignmentOperator(tclass)) {
if (!copts.old_argmatch)
has_ass = 1;
if ((tclass->flags & CLASS_FLAGS_20) || decle->xC || CClass_MemberObject(tclass, asop_name_node))
has_ass = 1;
for (base = tclass->bases; base; base = base->next) {
if ((obj = CClass_AssignmentOperator(base->base))) {
has_ass = 1;
access = getaccesstype(access, obj->access, ACCESSPRIVATE);
if (!(TYPE_FUNC(obj->type)->args->next->qual & Q_CONST))
is_const = 0;
}
}
for (ivar = tclass->ivars; ivar; ivar = ivar->next) {
Type *type = ivar->type;
while (IS_TYPE_ARRAY(type))
type = TYPE_POINTER(type)->target;
if (IS_TYPE_CLASS(type) && (obj = CClass_AssignmentOperator(TYPE_CLASS(type)))) {
has_ass = 1;
access = getaccesstype(access, obj->access, ACCESSPUBLIC);
if (!(TYPE_FUNC(obj->type)->args->next->qual & Q_CONST))
is_const = 0;
}
}
}
if (has_ass) {
memclrw(&declinfo, sizeof(DeclInfo));
declinfo.qual |= Q_INLINE;
declinfo.thetype = (Type *) CDecl_MakeAssignmentOperatorType(tclass, is_const);
declinfo.name = asop_name_node;
CDecl_AddFunctionMember(decle, tclass, &declinfo, access, 1, 0, 0, 0);
}
}
TypeMemberFunc *CDecl_MakeDefaultDtorType(TypeClass *tclass, Boolean is_virtual) {
TypeMemberFunc *tmeth = galloc(sizeof(TypeMemberFunc));
memclrw(tmeth, sizeof(TypeMemberFunc));
tmeth->type = TYPEFUNC;
tmeth->functype = (Type *) &void_ptr;
tmeth->flags = FUNC_FLAGS_2000 | FUNC_FLAGS_100 | FUNC_FLAGS_METHOD;
tmeth->theclass = tclass;
CDecl_SetFuncFlags(TYPE_FUNC(tmeth), 1);
if (is_virtual)
CDecl_AddArgument(TYPE_FUNC(tmeth), TYPE(&stsignedshort));
CDecl_AddThisPointerArgument(TYPE_FUNC(tmeth), tclass);
return tmeth;
}
static void CDecl_AddDefaultDestructor(DeclE *decle, TypeClass *tclass) {
ClassList *base;
ObjMemberVar *ivar;
Object *obj;
short access;
Boolean has_dtor;
Boolean is_virtual;
DeclInfo declinfo;
if (CClass_Destructor(tclass))
return;
has_dtor = 0;
is_virtual = 0;
access = ACCESSPUBLIC;
for (base = tclass->bases; base; base = base->next) {
if ((obj = CClass_Destructor(base->base))) {
has_dtor = 1;
if (obj->datatype == DVFUNC)
is_virtual = 1;
access = getaccesstype(access, obj->access, ACCESSPRIVATE);
}
}
for (ivar = tclass->ivars; ivar; ivar = ivar->next) {
Type *type = ivar->type;
while (IS_TYPE_ARRAY(type))
type = TYPE_POINTER(type)->target;
if (IS_TYPE_CLASS(type) && (obj = CClass_Destructor(TYPE_CLASS(type)))) {
has_dtor = 1;
access = getaccesstype(access, obj->access, ACCESSPUBLIC);
}
}
if (has_dtor) {
memclrw(&declinfo, sizeof(DeclInfo));
declinfo.qual |= Q_INLINE;
if (is_virtual)
declinfo.qual |= Q_VIRTUAL;
declinfo.thetype = (Type *) CDecl_MakeDefaultDtorType(tclass, 1);
declinfo.name = destructor_name_node;
CDecl_AddFunctionMember(decle, tclass, &declinfo, access, 1, 0, 0, 0);
}
}
static void CDecl_SetupClassLayout(DeclE *decle, TypeClass *tclass, ObjBase **objbuf) {
SInt32 index;
SInt32 i;
Object *obj;
CScopeObjectIterator iter;
ObjMemberVar *ivar;
SInt32 bufsize;
if (decle->x8 > 32) {
bufsize = decle->x8 * sizeof(ObjBase *);
objbuf = lalloc(bufsize);
} else {
bufsize = 32 * sizeof(ObjBase *);
}
memclrw(objbuf, bufsize);
decle->objlist = objbuf;
CScope_InitObjectIterator(&iter, tclass->nspace);
index = 0;
while (1) {
obj = OBJECT(CScope_NextObjectIteratorObject(&iter));
if (!obj) break;
if (!IS_TYPE_FUNC(obj->type))
continue;
if (!IS_TYPEFUNC_METHOD(TYPE_FUNC(obj->type)))
continue;
if (obj->datatype == DALIAS)
continue;
i = TYPE_METHOD(obj->type)->x1E;
if (i > 0) {
CError_ASSERT(6363, (i - 1) < decle->x8 && !objbuf[(int) (i - 1)]);
objbuf[(int) (i - 1)] = OBJ_BASE(obj);
index++;
if (obj->datatype != DVFUNC && !TYPE_METHOD(obj->type)->x26 && CClass_OverridesBaseMember(tclass, obj->name, obj))
CDecl_MakeFunctionVirtual(tclass, obj);
if (obj->datatype == DVFUNC) {
decle->xC = 1;
if (!tclass->vtable) {
CABI_AddVTable(tclass);
decle->xA = i - 1;
} else {
if ((i - 1) < decle->xA)
decle->xA = i - 1;
}
} else if (TYPE_FUNC(obj->type)->flags & FUNC_FLAGS_8) {
CError_Error(CErrorStr351, obj);
TYPE_FUNC(obj->type)->flags &= ~FUNC_FLAGS_8;
}
} else {
CError_ASSERT(6412, i == 0);
}
if (!tclass->sominfo)
TYPE_METHOD(obj->type)->x1E = 0;
}
if (!tclass->action) {
for (i = 0; i < decle->x8; i++) {
Object *obj2 = OBJECT(objbuf[i]);
if (obj2 && obj2->datatype == DVFUNC && !(obj2->qual & Q_INLINE) && !(TYPE_FUNC(obj2->type)->flags & FUNC_FLAGS_8)) {
tclass->action = CLASS_ACTION_1;
TYPE_FUNC(obj2->type)->flags |= FUNC_FLAGS_4;
break;
}
}
}
if (!tclass->sominfo) {
for (i = 0, ivar = tclass->ivars; i < decle->x8; i++) {
if (!objbuf[i]) {
CError_ASSERT(6449, ivar);
objbuf[i] = OBJ_BASE(ivar);
ivar = ivar->next;
index++;
}
}
CError_ASSERT(6455, ivar == NULL);
}
CError_ASSERT(6458, index == decle->x8);
}
void CDecl_CompleteClass(DeclE *decle, TypeClass *tclass) {
ClassList *base;
ObjBase *buf[32];
for (base = tclass->bases; base; base = base->next) {
if (base->base->vtable)
decle->xC = 1;
}
if (!tclass->sominfo) {
CDecl_AddDefaultDestructor(decle, tclass);
CDecl_AddDefaultAssignmentOperator(decle, tclass);
CDecl_AddDefaultConstructor(decle, tclass);
CDecl_AddDefaultCopyConstructor(decle, tclass);
}
CDecl_SetupClassLayout(decle, tclass, buf);
if (decle->xC)
CClass_CheckOverrides(tclass);
CABI_LayoutClass(decle, tclass);
if (tclass->sominfo)
CSOM_ClassComplete(tclass);
if ((tclass->flags & CLASS_FLAGS_800) && !TEMPL_CLASS_INST(tclass)->is_specialized)
tclass->action = CLASS_ACTION_0;
if (!tclass->action)
CClass_MakeStaticActionClass(tclass);
CClass_ClassDefaultFuncAction(tclass);
}
TypeClass *CDecl_DefineClass(NameSpace *nspace, HashNameNode *name, TypeClass *tclass, short mode, Boolean flag2, Boolean flag3) {
NameSpace *mynspace;
ObjType *objtype;
if (!tclass && nspace->theclass && (nspace->theclass->flags & CLASS_FLAGS_100)) {
CError_ASSERT(6556, !flag2);
return TYPE_CLASS(CTemplClass_DefineNestedClass(TEMPL_CLASS(nspace->theclass), name, mode));
}
mynspace = CScope_NewListNameSpace(name, 1);
if (!tclass) {
tclass = galloc(sizeof(TypeClass));
memclrw(tclass, sizeof(TypeClass));
}
tclass->type = TYPECLASS;
tclass->align = 1;
tclass->mode = mode;
tclass->action = CLASS_ACTION_0;
if (name) {
tclass->classname = name;
if (flag3) {
if (flag2) {
objtype = galloc(sizeof(ObjType));
memclrw(objtype, sizeof(ObjType));
objtype->otype = OT_TYPE;
objtype->access = ACCESSPUBLIC;
objtype->type = (Type *) tclass;
CScope_AddObject(nspace, name, OBJ_BASE(objtype));
} else {
CScope_DefineTypeTag(nspace, name, (Type *) tclass);
}
}
CScope_DefineTypeTag(mynspace, name, (Type *) tclass);
if (cscope_currentfunc)
mynspace->name = CParser_AppendUniqueNameFile(name->name);
if (copts.direct_to_som && nspace == cscope_root && !strcmp(name->name, "SOMObject"))
CSOM_MakeSOMClass(tclass);
} else {
tclass->classname = CParser_AppendUniqueNameFile("@class");
mynspace->name = tclass->classname;
}
tclass->nspace = mynspace;
mynspace->theclass = tclass;
mynspace->parent = nspace;
if (!nspace->is_global)
CParser_RegisterNonGlobalClass(tclass);
return tclass;
}
void CDecl_ParseClassDeclSpec(UInt8 *declspec) {
DeclInfo declinfo;
if ((tk = lex()) == '(') {
memclrw(&declinfo, sizeof(DeclInfo));
CParser_ParseDeclSpec(&declinfo, 1);
if (declinfo.exportflags & EXPORT_FLAGS_INTERNAL)
*declspec |= CLASS_EFLAGS_INTERNAL;
if (declinfo.exportflags & EXPORT_FLAGS_IMPORT)
*declspec |= CLASS_EFLAGS_IMPORT;
if (declinfo.exportflags & EXPORT_FLAGS_EXPORT)
*declspec |= CLASS_EFLAGS_EXPORT;
if ((tk = lex()) != ')')
CError_Error(CErrorStr115);
else
tk = lex();
} else {
CError_Error(CErrorStr114);
}
}
static TemplClass *CDecl_SpecializeTemplateClass(TemplClass *tmclass) {
tmclass->theclass.nspace->names = 0;
tmclass->theclass.nspace->data.list = NULL;
tmclass->theclass.ivars = NULL;
tmclass->theclass.bases = NULL;
tmclass->theclass.vbases = NULL;
tmclass->theclass.friends = NULL;
tmclass->theclass.vtable = NULL;
tmclass->members = NULL;
tmclass->instances = NULL;
tmclass->pspec_owner = NULL;
tmclass->pspecs = NULL;
tmclass->actions = NULL;
tmclass->lex_order_count = 0;
tmclass->align = 0;
tmclass->flags = TEMPLCLASS_FLAGS_2;
return tmclass;
}
void CDecl_ParseClass(DeclInfo *declinfo, short mode, Boolean flag1, UInt8 class_declspec) {
DeclE decle;
TypeClass *tclass;
HashNameNode *classname;
Type *search;
short t;
NameSpace *nspace;
CScopeParseResult pr;
CScopeSave scopesave;
GList gl;
FileOffsetInfo offsetsave;
SInt32 offset;
Boolean is_templ;
Boolean add_to_browse;
memclrw(&decle, sizeof(DeclE));
if (declinfo->x28) {
tclass = TYPE_CLASS(declinfo->x28);
} else {
if (tk == TK_UU_DECLSPEC)
CDecl_ParseClassDeclSpec(&class_declspec);
switch (tk) {
case ':':
case '{':
tclass = CDecl_DefineClass(cscope_current, NULL, NULL, mode, 0, 1);
tclass->eflags |= class_declspec;
break;
case TK_IDENTIFIER:
classname = tkidentifier;
if (!declinfo->x4C && !declinfo->x4F && ((t = lookahead()) == ':' || t == ';' || t == '{')) {
tk = lex();
search = CScope_GetLocalTagType(cscope_current, classname);
if (search) {
tagtype_search:
if (!IS_TYPE_CLASS(search)) {
if ((IS_TYPE_TEMPLATE(search) || IS_TYPE_STRUCT(search)) && tk != '{' && tk != ':') {
declinfo->thetype = search;
return;
}
if (!IS_TYPE_TEMPLATE(search) || !(tclass = TYPE_CLASS(CTemplTool_GetSelfRefTemplate(search)))) {
CError_Error(CErrorStr132, classname->name);
tclass = CDecl_DefineClass(cscope_current, NULL, NULL, mode, 0, 1);
break;
}
} else {
tclass = TYPE_CLASS(search);
}
if (tclass->mode != mode) {
if ((mode == CLASS_FLAGS_2 && tclass->mode == CLASS_MODE_0) || (mode == CLASS_MODE_0 && tclass->mode == CLASS_MODE_2)) {
if (copts.warn_structclass)
CError_Warning(CErrorStr343);
} else {
CError_Error(CErrorStr132, classname);
}
}
tclass->eflags |= class_declspec;
break;
} else {
tclass = CDecl_DefineClass(cscope_current, classname, NULL, mode, 0, 1);
tclass->eflags |= class_declspec;
break;
}
} else {
tkidentifier = classname;
}
default:
if (!CScope_ParseElaborateName(&pr)) {
CError_Error(CErrorStr121);
declinfo->thetype = (Type *) &stsignedint;
return;
}
tk = lex();
if ((search = pr.x8)) {
goto tagtype_search;
}
CError_ASSERT(6786, pr.name_4);
tclass = CDecl_DefineClass(CScope_FindNonClassNonFunctionNS(cscope_current), pr.name_4, NULL, mode, 0, 1);
tclass->eflags |= class_declspec;
}
}
declinfo->thetype = (Type *) tclass;
if (tk == ':' || tk == '{') {
if (declinfo->x4C)
CError_Error(CErrorStr201);
if (tclass->flags & CLASS_FLAGS_2) {
if ((tclass->flags & CLASS_FLAGS_100) && !TEMPL_CLASS(tclass)->instances && !(TEMPL_CLASS(tclass)->flags & TEMPLCLASS_FLAGS_2)) {
tclass = TYPE_CLASS(CDecl_SpecializeTemplateClass(TEMPL_CLASS(tclass)));
} else {
CError_Error(CErrorStr132, tclass->classname->name);
tclass = CDecl_DefineClass(cscope_current, NULL, NULL, mode, 0, 1);
}
}
for (nspace = cscope_current; nspace; nspace = nspace->parent) {
if (nspace == tclass->nspace) {
CError_Error(CErrorStr132, tclass->classname->name);
tclass = CDecl_DefineClass(cscope_current, NULL, NULL, mode, 0, 1);
break;
}
}
is_templ = (tclass->flags & CLASS_FLAGS_100) ? 1 : 0;
if (tclass->flags & CLASS_FLAGS_800) {
TEMPL_CLASS_INST(tclass)->is_instantiated = 1;
if (!declinfo->x28)
TEMPL_CLASS_INST(tclass)->is_specialized = 1;
}
CError_ASSERT(6853, copts.structalignment >= 0 && copts.structalignment <= 14);
tclass->eflags |= (UInt8) ((copts.structalignment + 1) << 4);
if (tk == ':')
CDecl_ParseBaseClassList(tclass, mode, is_templ);
CScope_SetClassDefScope(tclass, &scopesave);
if (tk == '{') {
tk = lex();
if ((add_to_browse = cparamblkptr->browseoptions.recordClasses && declinfo->file->recordbrowseinfo)) {
offsetsave = member_fileoffset;
CBrowse_BeginClass(declinfo, &gl);
}
CDecl_ParseClassMembers(&decle, tclass, mode);
offset = CPrep_BrowserFileOffset();
if (flag1)
tk = lex();
if (add_to_browse) {
member_fileoffset = offsetsave;
if (flag1 && tk == ';')
CPrep_BrowserFileOffset();
CBrowse_EndClass(offset, &gl);
}
} else {
CError_Error(CErrorStr135);
}
if (is_templ)
CTemplClass_CompleteClass(TEMPL_CLASS(tclass), &decle);
else
CDecl_CompleteClass(&decle, tclass);
CScope_RestoreScope(&scopesave);
}
}