summaryrefslogtreecommitdiff
path: root/compiler_and_linker/FrontEnd/C/CDecl.c
diff options
context:
space:
mode:
authorAsh Wolf <ninji@wuffs.org>2023-01-26 11:30:47 +0000
committerAsh Wolf <ninji@wuffs.org>2023-01-26 11:30:47 +0000
commit094b96ca1df4a035b5f93c351f773306c0241f3f (patch)
tree95ce05e3ebe816c7ee7996206bb37ea17d8ca33c /compiler_and_linker/FrontEnd/C/CDecl.c
parentfc0c4c0df7b583b55a08317cf1ef6a71d27c0440 (diff)
downloadMWCC-094b96ca1df4a035b5f93c351f773306c0241f3f.tar.gz
MWCC-094b96ca1df4a035b5f93c351f773306c0241f3f.zip
move lots of source files around to match their actual placement in the original treemain
Diffstat (limited to 'compiler_and_linker/FrontEnd/C/CDecl.c')
-rw-r--r--compiler_and_linker/FrontEnd/C/CDecl.c4845
1 files changed, 4845 insertions, 0 deletions
diff --git a/compiler_and_linker/FrontEnd/C/CDecl.c b/compiler_and_linker/FrontEnd/C/CDecl.c
new file mode 100644
index 0000000..43ca92e
--- /dev/null
+++ b/compiler_and_linker/FrontEnd/C/CDecl.c
@@ -0,0 +1,4845 @@
+#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_CONST)
+ CError_Warning(CErrorStr313, "const");
+ tfunc->flags |= FUNC_CONST;
+ tk = lex();
+ } else if (tk == TK_VOLATILE) {
+ if (tfunc->flags & FUNC_VOLATILE)
+ CError_Warning(CErrorStr313, "volatile");
+ tfunc->flags |= FUNC_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_CONVERSION;
+ 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_COMPLETED | CLASS_IS_TEMPL_INST)) == CLASS_IS_TEMPL_INST)
+ 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_COMPLETED) &&
+ (
+ !(TYPE_CLASS(type)->flags & CLASS_IS_TEMPL_INST) ||
+ !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_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_HANDLEOBJECT) {
+ 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_CONST)
+ arg->qual |= Q_CONST;
+ if (tfunc->flags & FUNC_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_CONST)
+ arg1->qual |= Q_CONST;
+ if (tfunc->flags & FUNC_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_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->operator_token) {
+ CError_Error(CErrorStr121);
+ return 0;
+ }
+
+ declinfo->operator_token = 0;
+ if (!CParser_ParseOperatorName(&declinfo->operator_token, declinfo->x4A && cscope_current->theclass, 0))
+ return 0;
+
+ if (!declinfo->operator_token) {
+ 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);
+}
+
+static Boolean CDecl_CheckOperatorType(DeclInfo *declinfo, Boolean flag) {
+ FuncArg *args;
+ FuncArg *secondarg;
+ Type *functype;
+ short argCount;
+ Boolean isMethod;
+
+ 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) {
+ argCount = 1;
+ if (args->dexpr) {
+ switch (declinfo->operator_token) {
+ case TK_NEW:
+ case TK_DELETE:
+ case TK_NEW_ARRAY:
+ case TK_DELETE_ARRAY:
+ break;
+ default:
+ CError_Error(CErrorStr205);
+ }
+ }
+
+ secondarg = args->next;
+ if (secondarg) {
+ argCount = ((secondarg != &elipsis && !secondarg->next) != 0) ? 2 : 3;
+ if (secondarg->dexpr) {
+ switch (declinfo->operator_token) {
+ case '(':
+ case TK_NEW:
+ case TK_DELETE:
+ case TK_NEW_ARRAY:
+ case TK_DELETE_ARRAY:
+ break;
+ default:
+ CError_Error(CErrorStr205);
+ }
+ }
+ }
+ } else {
+ argCount = 3;
+ }
+ } else {
+ CError_Error(CErrorStr193);
+ return 0;
+ }
+
+ isMethod = flag &&
+ IS_TYPEFUNC_METHOD(TYPE_FUNC(declinfo->thetype)) &&
+ !TYPE_METHOD(declinfo->thetype)->is_static;
+
+ switch (declinfo->operator_token) {
+ case TK_NEW:
+ case TK_NEW_ARRAY:
+ if (isMethod || !is_typesame(functype, TYPE(&void_ptr)) || argCount < 1 || args->type != CABI_GetSizeTType()) {
+ CError_Error(CErrorStr193);
+ return 0;
+ }
+ return 1;
+ case TK_DELETE:
+ case TK_DELETE_ARRAY:
+ if (isMethod || !IS_TYPE_VOID(functype) || argCount < 1 || !is_typesame(args->type, TYPE(&void_ptr))) {
+ CError_Error(CErrorStr193);
+ return 0;
+ }
+ return 1;
+ case '=':
+ if (!isMethod) {
+ CError_Error(CErrorStr193);
+ return 0;
+ }
+ break;
+ case '(':
+ if (!isMethod) {
+ CError_Error(CErrorStr193);
+ return 0;
+ }
+ return 1;
+ case '[':
+ if (!isMethod) {
+ CError_Error(CErrorStr193);
+ return 0;
+ }
+ break;
+ case TK_ARROW:
+ if (argCount != 1 || isMethod == 0) {
+ CError_Error(CErrorStr193);
+ return 0;
+ }
+ return 1;
+ case TK_INCREMENT:
+ case TK_DECREMENT:
+ if (argCount == 2 && secondarg->type != TYPE(&stsignedint)) {
+ CError_Error(CErrorStr193);
+ return 0;
+ }
+ break;
+ }
+
+ if (flag && !isMethod) {
+ CError_Error(CErrorStr193);
+ return 0;
+ }
+
+ switch (declinfo->operator_token) {
+ case '&':
+ case '*':
+ case '+':
+ case '-':
+ case TK_INCREMENT:
+ case TK_DECREMENT:
+ if (argCount != 1)
+ goto whatever;
+ case '!':
+ case '~':
+ if (argCount == 1) {
+ 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 (argCount == 2) {
+ 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_CONVERSION;
+ 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_HANDLEOBJECT) {
+ 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) {
+ NameResult 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.type && IS_TYPE_TEMPLATE(pr.type) && declinfo->x30) {
+ if (CTempl_IsQualifiedMember(declinfo, pr.type, &nspace))
+ scandirectdeclarator(declinfo, nspace);
+ else
+ declinfo->x20 = pr.type;
+ 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) {
+ NameResult 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.type && IS_TYPE_TEMPLATE(pr.type)) {
+ if (declinfo->x30 && CTempl_IsQualifiedMember(declinfo, pr.type, &nspace)) {
+ scandirectdeclarator(declinfo, nspace);
+ return;
+ } else if (declinfo->x30 && tk == TK_OPERATOR) {
+ declinfo->x20 = pr.type;
+ return;
+ } else if ((tk = lex()) == TK_COLON_COLON && (tk = lex()) == '*') {
+ CDecl_TemplatePTM(declinfo, pr.type);
+ tk = lex();
+ break;
+ } else if (declinfo->x30) {
+ declinfo->x20 = pr.type;
+ return;
+ }
+ }
+ CError_Error(CErrorStr121);
+ }
+ break;
+ }
+
+ scandirectdeclarator(declinfo, NULL);
+ if (tk == TK_UU_ATTRIBUTE_UU)
+ CParser_ParseAttribute(NULL, declinfo);
+}
+
+void conversion_type_name(DeclInfo *declinfo) {
+ NameResult 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_IS_TEMPL)
+ r24 = 1;
+
+ if (IS_TYPEFUNC_METHOD(scanfunc)) {
+ switch (mode) {
+ case OverloadMode0:
+ CError_Error(CErrorStr197);
+ break;
+ case OverloadMode1:
+ if (!TYPE_METHOD(scanfunc)->is_static)
+ continue;
+ break;
+ case OverloadMode2:
+ if (TYPE_METHOD(scanfunc)->is_static)
+ continue;
+ break;
+ case OverloadMode3:
+ if (!TYPE_METHOD(scanfunc)->is_static) {
+ if (scanargs->qual & Q_CV)
+ continue;
+ scanargs = scanargs->next;
+ }
+ break;
+ }
+ } else {
+ if (mode)
+ CError_Error(CErrorStr197);
+ }
+
+ compareresult = CParser_CompareArgLists(args, scanargs);
+ if (compareresult == 1) {
+ if (scanfunc->flags & FUNC_CONVERSION) {
+ if (!(tfunc->flags & FUNC_CONVERSION)) {
+ CError_Error(CErrorStr197);
+ break;
+ }
+ if (!is_typesame(tfunc->functype, scanfunc->functype))
+ continue;
+ if ((tfunc->qual & Q_CV) != (scanfunc->qual & Q_CV))
+ continue;
+ if ((tfunc->flags & FUNC_CALL_CONV_MASK) != (scanfunc->flags & FUNC_CALL_CONV_MASK)) {
+ CError_Error(CErrorStr197);
+ break;
+ }
+ if (tfunc->exspecs || scanfunc->exspecs)
+ CExcept_CompareSpecifications(tfunc->exspecs, scanfunc->exspecs);
+ return obj;
+ }
+
+ if (tfunc->flags & FUNC_CONVERSION) {
+ 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_CALL_CONV_MASK) != (scanfunc->flags & FUNC_CALL_CONV_MASK))
+ )
+ {
+ 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_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_PASCAL)
+ CError_Error(CErrorStr226);
+ }
+ }
+ }
+
+ if (copts.cplusplus && declinfo->is_extern_c) {
+ for (scan = list; scan; scan = scan->next) {
+ if (scan->object->otype == OT_OBJECT && !(OBJECT(scan->object)->qual & Q_MANGLE_NAME))
+ CError_Error(CErrorStr197);
+ }
+ }
+
+ CScope_AddObject(cscope_current, declinfo->name, OBJ_BASE(obj));
+ if (cscope_current->theclass && (cscope_current->theclass->flags & CLASS_IS_TEMPL) &&
+ 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) {
+ NameSpace *nspace2;
+ Type *type;
+ Object *obj;
+ NameSpaceObjectList *list;
+ TypeMemberFunc tmp;
+ Boolean r27;
+ Boolean outflag;
+
+ r27 = 0;
+ if (pflag)
+ *pflag = 0;
+
+ nspace2 = declinfo->nspace;
+ if (!nspace2)
+ nspace2 = cscope_current;
+
+ CError_QualifierCheck(declinfo->qual & ~(Q_ALIGNED_MASK | Q_WEAK | 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_CONST | FUNC_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)->is_static)
+ CDecl_AddThisPointerArgument(TYPE_FUNC(declinfo->thetype), nspace2->theclass);
+ }
+ } else {
+ if (TYPE_METHOD(type)->is_static) {
+ 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_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_IS_TEMPL_INST))
+ CError_Error(CErrorStr335);
+ declinfo->x3C = 0;
+ }
+ } else {
+ if (TYPE_FUNC(declinfo->thetype)->flags & (FUNC_VOLATILE | FUNC_CONST))
+ CError_Error(CErrorStr384);
+
+ if (declinfo->operator_token && !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->operator_token)
+ 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_IS_TEMPL) &&
+ 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->sourceoffset, CPrep_BrowserFileOffset());
+}
+
+static void CDecl_DataDeclarator(DeclInfo *declinfo, AccessType 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_WEAK | Q_20000 | Q_PASCAL | Q_VOLATILE | Q_CONST));
+ if (declinfo->x48 || declinfo->x44)
+ CError_Error(CErrorStr121);
+ if (declinfo->operator_token)
+ 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_INLINE_DATA) {
+ 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_IS_TEMPL) &&
+ 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_IS_TEMPL_INST))
+ declinfo->x3C = 0;
+ } else {
+ CInit_InitializeData(obj);
+ }
+
+ if (declinfo->file->recordbrowseinfo && obj->sclass != TK_EXTERN)
+ CBrowse_NewData(obj, declinfo->file, declinfo->file2, declinfo->sourceoffset, 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_IS_TEMPL));
+ 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_INLINE_DATA | 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->sourceoffset,
+ 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_IS_CTOR | FUNC_IS_DTOR)) {
+ 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_IS_CTOR)
+ 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_IS_CTOR) {
+ if ((r28->nspace->theclass->flags & CLASS_HAS_VBASES) && !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_CONVERSION) {
+ 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_CONVERSION;
+ 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->operator_token)
+ CError_Error(CErrorStr193);
+
+ if (
+ (declinfo->qual & ~(Q_ALIGNED_MASK | Q_WEAK | 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->operator_token = 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_IS_TEMPL)) {
+ 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_IS_TEMPL)) {
+ 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;
+ NameResult 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->sourceoffset,
+ CPrep_BrowserFileOffset());
+ return;
+ } else {
+ CError_ASSERT(3851, !copts.cplusplus || tk != ';');
+ tkidentifier = name;
+ }
+ }
+
+ if (CScope_ParseElaborateName(&pr)) {
+ if ((type = pr.type)) {
+ 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.operator_token = 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->bitlength = 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_WEAK;
+ 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.operator_token) {
+ 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_DEFINED;
+
+ CPrep_StreamGetBlock(&stream, NULL, 1);
+ if (stream.tokens) {
+ if (IS_TYPEFUNC_METHOD(TYPE_FUNC(obj->type)) && (TYPE_METHOD(obj->type)->theclass->flags & CLASS_IS_TEMPL)) {
+ TYPE_FUNC(obj->type)->flags |= FUNC_IS_TEMPL_INSTANCE;
+ 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 = declinfo->exportflags | EXPORT_FLAGS_INTERNAL;
+ if (flags & CLASS_EFLAGS_IMPORT)
+ declinfo->exportflags = declinfo->exportflags | EXPORT_FLAGS_IMPORT;
+ if (flags & CLASS_EFLAGS_EXPORT)
+ declinfo->exportflags = 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->is_static = flag;
+ method->flags |= FUNC_METHOD;
+ if (!flag)
+ CDecl_AddThisPointerArgument(TYPE_FUNC(method), tclass);
+
+ if ((flag || (tfunc->flags & (FUNC_IS_CTOR | FUNC_IS_DTOR))) && (tfunc->flags & (FUNC_CONST | FUNC_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_UNION)
+ CError_Error(CErrorStr352, func);
+ func->datatype = DVFUNC;
+}
+
+static void CDecl_AddFunctionMember(ClassLayout *decle, TypeClass *tclass, DeclInfo *declinfo, AccessType 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->vtbl_index = ++decle->lex_order_count;
+ else
+ CError_Error(CErrorStr133, CError_GetObjectName(obj));
+ } else {
+ tfunc->vtbl_index = ++decle->lex_order_count;
+ obj = CParser_NewFunctionObject(declinfo);
+ if ((tclass->flags & CLASS_IS_TEMPL) && 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_CONVERSION;
+ tclass->flags = tclass->flags | CLASS_IS_CONVERTIBLE;
+ }
+
+ if (r31) {
+ CDecl_MakeFunctionVirtual(tclass, obj);
+ decle->has_vtable = 1;
+ }
+
+ if ((flag1 || r31) && flag3 && (tk == '=')) {
+ if ((tk = lex()) == TK_INTCONST) {
+ if (!CInt64_IsZero(&tkintconst))
+ CError_Error(CErrorStr121);
+ tfunc->flags |= FUNC_PURE;
+ tclass->flags = tclass->flags | CLASS_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, AccessType 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_IS_TEMPL) != 0;
+ r27 = (tk == TK_CLASS || tk == TK_STRUCT || tk == TK_UNION);
+ memclrw(&declinfo, sizeof(DeclInfo));
+
+ declinfo.in_friend_decl = 1;
+ CParser_GetDeclSpecs(&declinfo, 1);
+ if (declinfo.storageclass) {
+ CError_Error(CErrorStr177);
+ declinfo.storageclass = 0;
+ }
+ declinfo.in_friend_decl = 0;
+
+ if (tk == ';') {
+ if (!r27)
+ CError_Error(CErrorStr201);
+
+ if (IS_TYPE_CLASS(declinfo.thetype)) {
+ if (!(TYPE_CLASS(declinfo.thetype)->flags & CLASS_IS_TEMPL) || 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(ClassLayout *decle, TypeClass *tclass, Type *type, UInt32 qual, HashNameNode *name, AccessType 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->lex_order_count++;
+
+ 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_IS_TEMPL) && 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(ClassLayout *decle, TypeClass *tclass, short mode) {
+ AccessType access;
+ Boolean r17;
+ BigDeclInfo bde;
+ DeclInfo declinfo;
+ //Type *newtype
+ ObjMemberVar *ivar;
+ ObjMemberVar *scanivar;
+ Type *tmptype;
+ UInt32 r22;
+ UInt32 r21;
+ UInt8 r20;
+ UInt8 r18;
+ Boolean r19;
+ short t;
+
+ r17 = (tclass->flags & CLASS_IS_TEMPL) && TEMPL_CLASS(tclass)->pspec_owner;
+ memclrw(&bde, sizeof(BigDeclInfo));
+
+ access = (mode == CLASS_MODE_CLASS) ? ACCESSPRIVATE : ACCESSPUBLIC;
+ global_access = access;
+
+ 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_IS_TEMPL)) {
+ 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_HAS_VBASES)
+ CDecl_AddArgument(TYPE_FUNC(bde.declinfo2.thetype), TYPE(&stsignedshort));
+ bde.declinfo2.qual &= ~Q_VIRTUAL;
+ }
+ TYPE_FUNC(bde.declinfo2.thetype)->flags |= FUNC_IS_CTOR;
+ 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_IS_TEMPL_ANY) {
+ 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_IS_DTOR;
+ 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_IS_TEMPL) && 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_IS_TEMPL_ANY) && 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.operator_token) {
+ if (bde.declinfo.storageclass == TK_MUTABLE)
+ CError_QualifierCheck(Q_MUTABLE);
+ r19 = 0;
+ switch (bde.declinfo2.operator_token) {
+ 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 = 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_COMPLETED)) {
+ CError_Error(CErrorStr136, baseclass, 0);
+ return 0;
+ }
+
+ if (baseclass->flags & CLASS_SINGLE_OBJECT) {
+ if (is_virtual || tclass->bases) {
+ CError_Error(CErrorStr191);
+ return 0;
+ }
+ tclass->flags = tclass->flags | CLASS_SINGLE_OBJECT;
+ }
+
+ if (baseclass->flags & CLASS_HANDLEOBJECT) {
+ if (is_virtual || tclass->bases) {
+ CError_Error(CErrorStr191);
+ return 0;
+ }
+ tclass->flags = tclass->flags | CLASS_HANDLEOBJECT;
+ }
+
+ 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_SINGLE_OBJECT) && (tclass->flags & CLASS_SINGLE_OBJECT)) {
+ 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_COM_OBJECT)
+ tclass->flags = tclass->flags | CLASS_COM_OBJECT;
+ if (baseclass->flags & CLASS_IS_CONVERTIBLE)
+ tclass->flags = tclass->flags | CLASS_IS_CONVERTIBLE;
+ if (baseclass->flags & CLASS_HAS_VBASES)
+ tclass->flags = tclass->flags | CLASS_HAS_VBASES;
+
+ if (is_virtual)
+ tclass->flags = tclass->flags | CLASS_HAS_VBASES;
+
+ return 1;
+}
+
+static void CDecl_ParseBaseClassList(TypeClass *tclass, short mode, Boolean is_templ) {
+ Boolean is_virtual;
+ AccessType access;
+ NameResult pr;
+ ObjType *inherited_type;
+ ClassList *base;
+ ClassList *scan;
+ TypeClass *baseclass;
+
+ do {
+ if (mode == CLASS_MODE_CLASS)
+ 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.type) {
+ 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.type);
+ if (is_templ && CTemplTool_IsTemplateArgumentDependentType(pr.type)) {
+ if (!IS_TYPE_CLASS(pr.type) || !(TYPE_CLASS(pr.type)->flags & CLASS_IS_TEMPL) ||
+ CParser_CheckTemplateClassUsage(TEMPL_CLASS(pr.type), 1)) {
+ CTemplClass_RegisterBaseClass(TEMPL_CLASS(tclass), pr.type, access, is_virtual);
+ if (is_virtual)
+ tclass->flags = tclass->flags | CLASS_HAS_VBASES;
+ }
+ continue;
+ }
+
+ if (!IS_TYPE_CLASS(pr.type) || (TYPE_CLASS(pr.type)->flags & CLASS_IS_TEMPL)) {
+ CError_Error(CErrorStr131);
+ continue;
+ }
+ baseclass = TYPE_CLASS(pr.type);
+ } else {
+ special_parsing:
+ if (!strcmp(tkidentifier->name, "HandleObject")) {
+ if (tclass->bases)
+ CError_Error(CErrorStr191);
+ tclass->flags |= CLASS_SINGLE_OBJECT | CLASS_HANDLEOBJECT;
+ tk = lex();
+ break;
+ }
+ if (!strcmp(tkidentifier->name, "SingleObject") || !strcmp(tkidentifier->name, "SingleInheritance")) {
+ if (tclass->bases)
+ CError_Error(CErrorStr191);
+ tclass->flags = tclass->flags | CLASS_SINGLE_OBJECT;
+ tk = lex();
+ break;
+ }
+ if (!strcmp(tkidentifier->name, "__comobject")) {
+ tclass->flags = tclass->flags | CLASS_COM_OBJECT;
+ 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_HAS_VBASES)
+ 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 AccessType 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_IS_CTOR | FUNC_AUTO_GENERATED | FUNC_METHOD;
+ tmeth->theclass = tclass;
+ CDecl_SetFuncFlags(TYPE_FUNC(tmeth), 1);
+
+ if (tclass->flags & CLASS_HAS_VBASES)
+ 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, AccessType access) {
+ Object *obj = CParser_NewCompilerDefFunctionObject();
+ obj->name = name;
+ obj->type = TYPE(tmeth);
+ obj->qual = Q_MANGLE_NAME;
+ obj->access = access;
+ obj->nspace = tclass->nspace;
+ obj->qual = obj->qual | Q_INLINE;
+ CScope_AddObject(tclass->nspace, obj->name, OBJ_BASE(obj));
+}
+
+static void CDecl_AddDefaultConstructor(ClassLayout *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_HAS_VBASES)
+ has_ctor = 1;
+ if (decle->has_vtable)
+ 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_IS_CTOR | FUNC_AUTO_GENERATED | FUNC_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_HAS_VBASES)
+ CDecl_AddArgument(TYPE_FUNC(tmeth), TYPE(&stsignedshort));
+
+ CDecl_AddThisPointerArgument(TYPE_FUNC(tmeth), tclass);
+ return tmeth;
+}
+
+static void CDecl_AddDefaultCopyConstructor(ClassLayout *decle, TypeClass *tclass) {
+ ClassList *base;
+ ObjMemberVar *ivar;
+ Object *obj;
+ AccessType 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_HAS_VBASES) || decle->has_vtable)
+ 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_HAS_VBASES)
+ 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_HAS_VBASES)
+ 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_AUTO_GENERATED | FUNC_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(ClassLayout *decle, TypeClass *tclass) {
+ ClassList *base;
+ ObjMemberVar *ivar;
+ Object *obj;
+ AccessType 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_HAS_VBASES) || decle->has_vtable || 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_IS_DTOR | FUNC_AUTO_GENERATED | FUNC_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(ClassLayout *decle, TypeClass *tclass) {
+ ClassList *base;
+ ObjMemberVar *ivar;
+ Object *obj;
+ AccessType 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(ClassLayout *decle, TypeClass *tclass, ObjBase **objbuf) {
+ SInt32 index;
+ SInt32 i;
+ Object *obj;
+ CScopeObjectIterator iter;
+ ObjMemberVar *ivar;
+ SInt32 bufsize;
+
+ if (decle->lex_order_count > 32) {
+ bufsize = decle->lex_order_count * 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)->vtbl_index;
+ if (i > 0) {
+ CError_ASSERT(6363, (i - 1) < decle->lex_order_count && !objbuf[(int) (i - 1)]);
+ objbuf[(int) (i - 1)] = OBJ_BASE(obj);
+ index++;
+ if (obj->datatype != DVFUNC && !TYPE_METHOD(obj->type)->is_static && CClass_OverridesBaseMember(tclass, obj->name, obj))
+ CDecl_MakeFunctionVirtual(tclass, obj);
+
+ if (obj->datatype == DVFUNC) {
+ decle->has_vtable = 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_PURE) {
+ CError_Error(CErrorStr351, obj);
+ TYPE_FUNC(obj->type)->flags &= ~FUNC_PURE;
+ }
+ } else {
+ CError_ASSERT(6412, i == 0);
+ }
+
+ if (!tclass->sominfo)
+ TYPE_METHOD(obj->type)->vtbl_index = 0;
+ }
+
+ if (!tclass->action) {
+ for (i = 0; i < decle->lex_order_count; i++) {
+ Object *obj2 = OBJECT(objbuf[i]);
+ if (obj2 && obj2->datatype == DVFUNC && !(obj2->qual & Q_INLINE) && !(TYPE_FUNC(obj2->type)->flags & FUNC_PURE)) {
+ 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->lex_order_count; 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->lex_order_count);
+}
+
+void CDecl_CompleteClass(ClassLayout *decle, TypeClass *tclass) {
+ ClassList *base;
+ ObjBase *buf[32];
+
+ for (base = tclass->bases; base; base = base->next) {
+ if (base->base->vtable)
+ decle->has_vtable = 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->has_vtable)
+ CClass_CheckOverrides(tclass);
+ CABI_LayoutClass(decle, tclass);
+ if (tclass->sominfo)
+ CSOM_ClassComplete(tclass);
+
+ if ((tclass->flags & CLASS_IS_TEMPL_INST) && !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_IS_TEMPL)) {
+ 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 = *declspec | CLASS_EFLAGS_INTERNAL;
+ if (declinfo.exportflags & EXPORT_FLAGS_IMPORT)
+ *declspec = *declspec | CLASS_EFLAGS_IMPORT;
+ if (declinfo.exportflags & EXPORT_FLAGS_EXPORT)
+ *declspec = *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) {
+ ClassLayout decle;
+ TypeClass *tclass;
+ HashNameNode *classname;
+ Type *search;
+ short t;
+ NameSpace *nspace;
+ NameResult pr;
+ CScopeSave scopesave;
+ GList gl;
+ FileOffsetInfo offsetsave;
+ SInt32 offset;
+ Boolean is_templ;
+ Boolean add_to_browse;
+
+ memclrw(&decle, sizeof(ClassLayout));
+ 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->in_friend_decl && !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_MODE_CLASS && tclass->mode == CLASS_MODE_STRUCT) ||
+ (mode == CLASS_MODE_STRUCT && tclass->mode == CLASS_MODE_CLASS)
+ )
+ {
+ 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.type)) {
+ 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->in_friend_decl)
+ CError_Error(CErrorStr201);
+
+ if (tclass->flags & CLASS_COMPLETED) {
+ if (
+ (tclass->flags & CLASS_IS_TEMPL) &&
+ !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_IS_TEMPL) != 0;
+ if (tclass->flags & CLASS_IS_TEMPL_INST) {
+ 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 = tclass->eflags | (((copts.structalignment + 1) << 4) & 0xF0);
+ 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);
+ }
+}