home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 40 / IOPROG_40.ISO / SOFT / NETFrameworkSDK.exe / comsdk.cab / samples1.exe / smc / comp.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-23  |  353.5 KB  |  12,261 lines

  1. /*****************************************************************************/
  2.  
  3. #include "smcPCH.h"
  4. #pragma hdrstop
  5.  
  6. #include "comp.h"
  7. #include "genIL.h"
  8. #ifdef  OLD_IL
  9. #include "oldIL.h"
  10. #endif
  11.  
  12. /*****************************************************************************/
  13.  
  14. #if     0
  15. #ifdef  DEBUG
  16. #define SHOW_CODE_OF_THIS_FNC   "parsePrepSrc"
  17. #endif
  18. #endif
  19.  
  20. /*****************************************************************************
  21.  *
  22.  *  In the single-threaded configuration the following points to *the* one
  23.  *  compiler and scanner instance.
  24.  */
  25.  
  26. #ifdef  DEBUG
  27. Compiler            TheCompiler;
  28. Scanner             TheScanner;
  29. #endif
  30.  
  31. /*****************************************************************************
  32.  *
  33.  *  A little helper to declare "interesting" names.
  34.  */
  35.  
  36. static
  37. Ident               declBuiltinName(HashTab hash, const char *name)
  38. {
  39.     Ident           iden = hash->hashString(name);
  40.  
  41.     hashTab::setIdentFlags(iden, IDF_PREDEF);
  42.  
  43.     return  iden;
  44. }
  45.  
  46. /*****************************************************************************
  47.  *
  48.  *  Initialize the compiler: called once per session.
  49.  */
  50.  
  51. bool                compiler::cmpInit()
  52. {
  53.     bool            result;
  54.  
  55.     /* Remember current warning settings as our defaults */
  56.  
  57.     cmpErrorSave();
  58.  
  59.     /* Set a trap for any errors */
  60.  
  61.     setErrorTrap(this);
  62.     begErrorTrap
  63.     {
  64.         Scanner         scan;
  65.         HashTab         hash;
  66.         SymTab          stab;
  67.         SymDef          glob;
  68.         ArgDscRec       args;
  69.  
  70.         Parser          parser;
  71.  
  72.         /* Initialize the two global allocators */
  73.  
  74.         if  (cmpAllocPerm.nraInit(this))
  75.             cmpFatal(ERRnoMemory);
  76.         if  (cmpAllocCGen.nraInit(this))
  77.             cmpFatal(ERRnoMemory);
  78.         if  (cmpAllocTemp. baInit(this))
  79.             cmpFatal(ERRnoMemory);
  80.  
  81.         /* Initialize a bunch of stuff */
  82.  
  83.         cmpUniConvInit();
  84.         cmpMDsigInit();
  85.  
  86.         /* Create and initialize the global hash table */
  87.  
  88. #if MGDDATA
  89.         hash = new HashTab;
  90. #else
  91.         hash =    (HashTab)cmpAllocPerm.nraAlloc(sizeof(*hash));
  92. #endif
  93.         if  (!hash)
  94.             cmpFatal(ERRnoMemory);
  95.         if  (hash->hashInit(this, 16*1024, 0, &cmpAllocPerm))
  96.             cmpFatal(ERRnoMemory);
  97.  
  98.         cmpGlobalHT = hash;
  99.  
  100.         /* Create and initialize the scanner we will use */
  101.  
  102. #if MGDDATA
  103.         scan = new Scanner;
  104. #else
  105.         scan =    (Scanner)cmpAllocPerm.nraAlloc(sizeof(*scan));
  106. #endif
  107.         if  (scan->scanInit(this, hash))
  108.             cmpFatal(ERRnoMemory);
  109.  
  110.         cmpScanner  = scan;
  111.  
  112.         /* If we're debugging, make some instances available globally */
  113.  
  114. #ifdef  DEBUG
  115.         TheCompiler = this;
  116.         TheScanner  = scan;
  117. #endif
  118.  
  119.         /* Create and initialize the global symbol table */
  120.  
  121. #if MGDDATA
  122.         stab = new SymTab;
  123. #else
  124.         stab =    (SymTab)cmpAllocPerm.nraAlloc(sizeof(*stab));
  125. #endif
  126.         cmpGlobalST = stab;
  127.         if  (!stab)
  128.             cmpFatal(ERRnoMemory);
  129.  
  130.         stab->stInit(this, &cmpAllocPerm, hash);
  131.  
  132.         /* Create a few standard types */
  133.  
  134.         cmpTypeInt        = stab->stIntrinsicType(TYP_INT);
  135.         cmpTypeUint       = stab->stIntrinsicType(TYP_UINT);
  136.         cmpTypeBool       = stab->stIntrinsicType(TYP_BOOL);
  137.         cmpTypeChar       = stab->stIntrinsicType(TYP_CHAR);
  138.         cmpTypeVoid       = stab->stIntrinsicType(TYP_VOID);
  139.  
  140.         cmpTypeNatInt     = stab->stIntrinsicType(TYP_NATINT);
  141.         cmpTypeNatUint    = stab->stIntrinsicType(TYP_NATUINT);
  142.  
  143.         cmpTypeCharPtr    = stab->stNewRefType(TYP_PTR, cmpTypeChar);
  144.         cmpTypeWchrPtr    = stab->stNewRefType(TYP_PTR, stab->stIntrinsicType(TYP_WCHAR));
  145.         cmpTypeVoidPtr    = stab->stNewRefType(TYP_PTR, cmpTypeVoid);
  146.  
  147. #if MGDDATA
  148.         args = new ArgDscRec;
  149. #else
  150.         memset(&args, 0, sizeof(args));
  151. #endif
  152.  
  153.         cmpTypeVoidFnc    = stab->stNewFncType(args,    cmpTypeVoid);
  154.  
  155.         /* Create the temp tree nodes used for overloaded operator binding */
  156.  
  157.         cmpConvOperExpr   = cmpCreateExprNode(NULL, TN_NONE   , cmpTypeVoid);
  158.  
  159.         cmpCompOperArg1   = cmpCreateExprNode(NULL, TN_LIST   , cmpTypeVoid);
  160.         cmpCompOperArg2   = cmpCreateExprNode(NULL, TN_LIST   , cmpTypeVoid);
  161.         cmpCompOperFnc1   = cmpCreateExprNode(NULL, TN_FNC_SYM, cmpTypeVoid);
  162.         cmpCompOperFnc2   = cmpCreateExprNode(NULL, TN_FNC_SYM, cmpTypeVoid);
  163.         cmpCompOperFunc   = cmpCreateExprNode(NULL, TN_LIST   , cmpTypeVoid);
  164.         cmpCompOperCall   = cmpCreateExprNode(NULL, TN_LIST   , cmpTypeVoid);
  165.  
  166.         /* Create the global namespace symbol */
  167.  
  168.         glob = stab->stDeclareSym(hash->hashString("<global>"),
  169.                                   SYM_NAMESPACE,
  170.                                   NS_NORM,
  171.                                   NULL);
  172.  
  173.         glob->sdNS.sdnSymtab = stab;
  174.  
  175.         /* Record the global namespace symbol */
  176.  
  177.         cmpGlobalNS       = glob;
  178.  
  179.         /* Hash some strings so we can easily detect certain symbols */
  180.  
  181.         cmpIdentSystem    = declBuiltinName(hash, "System");
  182.         cmpIdentRuntime   = declBuiltinName(hash, "Runtime");
  183.         cmpIdentObject    = declBuiltinName(hash, "Object");
  184.         cmpIdentString    = declBuiltinName(hash, "String");
  185.         cmpIdentArray     = declBuiltinName(hash, "Array");
  186.         cmpIdentType      = declBuiltinName(hash, "Type");
  187.         cmpIdentInvoke    = declBuiltinName(hash, "Invoke");
  188.         cmpIdentInvokeBeg = declBuiltinName(hash, "BeginInvoke");
  189.         cmpIdentInvokeEnd = declBuiltinName(hash, "EndInvoke");
  190.         cmpIdentDeleg     = declBuiltinName(hash, "Delegate");
  191.         cmpIdentMulti     = declBuiltinName(hash, "MulticastDelegate");
  192.         cmpIdentExcept    = declBuiltinName(hash, "Exception");
  193.         cmpIdentRTexcp    = declBuiltinName(hash, "SystemException");
  194.         cmpIdentArgIter   = declBuiltinName(hash, "ArgIterator");
  195.  
  196.         cmpIdentEnum      = declBuiltinName(hash, "Enum");
  197.         cmpIdentValType   = declBuiltinName(hash, "ValueType");
  198.  
  199.         cmpIdentGetNArg   = declBuiltinName(hash, "GetNextArg");
  200.  
  201.         cmpIdentAssertAbt = declBuiltinName(hash, "__AssertAbort");
  202.         cmpIdentEnter     = declBuiltinName(hash, "Enter");
  203.         cmpIdentExit      = declBuiltinName(hash, "Exit");
  204.         cmpIdentGet       = declBuiltinName(hash, "get");
  205.         cmpIdentSet       = declBuiltinName(hash, "set");
  206.  
  207.         cmpIdentDbgBreak  = declBuiltinName(hash, "DebugBreak");
  208.  
  209.         cmpIdentXcptCode  = declBuiltinName(hash, "_exception_code");
  210.         cmpIdentXcptInfo  = declBuiltinName(hash, "_exception_info");
  211.         cmpIdentAbnmTerm  = declBuiltinName(hash, "_abnormal_termination");
  212.  
  213.         // UNDONE: All of the following method symbols should be
  214.         // UNDONE: cached after they are seen for the first time.
  215.  
  216.         cmpIdentMain      = hash->hashString("main");
  217.         cmpIdentToString  = hash->hashString("ToString");
  218.         cmpIdentGetType   = hash->hashString("GetType");
  219.         cmpIdentGetTpHnd  = hash->hashString("GetTypeFromHandle");
  220.         cmpIdentVariant   = hash->hashString("Variant");
  221.  
  222.         cmpIdentVAbeg     = hash->hashString("va_start");
  223.         cmpIdentVAget     = hash->hashString("va_arg");
  224.  
  225.         cmpIdentCompare   = hash->hashString("$compare");
  226.         cmpIdentEquals    = hash->hashString("$equals");
  227.         cmpIdentNarrow    = hash->hashString("$narrow");
  228.         cmpIdentWiden     = hash->hashString("$widen");
  229.  
  230.         /* Declare the "System" and "Runtime" namespaces */
  231.  
  232.         cmpNmSpcSystem    = stab->stDeclareSym(cmpIdentSystem,
  233.                                                SYM_NAMESPACE,
  234.                                                NS_NORM,
  235.                                                cmpGlobalNS);
  236.  
  237.         cmpNmSpcSystem ->sdNS.sdnSymtab = stab;
  238.  
  239.         cmpNmSpcRuntime   = stab->stDeclareSym(cmpIdentRuntime,
  240.                                                SYM_NAMESPACE,
  241.                                                NS_NORM,
  242.                                                cmpNmSpcSystem);
  243.  
  244.         cmpNmSpcRuntime->sdNS.sdnSymtab = stab;
  245.  
  246.         /* Hash the names of the standard value types */
  247.  
  248.         cmpInitStdValTypes();
  249.  
  250.         /* Create and initialize the parser */
  251.  
  252. #if MGDDATA
  253.         parser = new Parser;
  254. #else
  255.         parser =    (Parser)SMCgetMem(this, sizeof(*parser));
  256. #endif
  257.         cmpParser = parser;
  258.  
  259.         if  (cmpParser->parserInit(this))
  260.             cmpFatal(ERRnoMemory);
  261.         cmpParserInit = true;
  262.  
  263.         /* Define any built-in macros */
  264.  
  265.         scan->scanDefMac("__SMC__"    , "1");
  266.         scan->scanDefMac("__IL__"     , "1");
  267.         scan->scanDefMac("__COMRT__"  , "1");
  268.  
  269.         if  (cmpConfig.ccTgt64bit)
  270.             scan->scanDefMac("__64BIT__", "1");
  271.  
  272.         /* Do we have any macro definitions? */
  273.  
  274.         if  (cmpConfig.ccMacList)
  275.         {
  276.             StrList         macDsc;
  277.  
  278.             for (macDsc = cmpConfig.ccMacList;
  279.                  macDsc;
  280.                  macDsc = macDsc->slNext)
  281.             {
  282.                 char    *       macStr  = macDsc->slString;
  283.                 char    *       macName;
  284.                 bool            undef;
  285.  
  286.                 /* First see if this is a definition or undefinition */
  287.  
  288.                 undef = false;
  289.  
  290.                 if  (*macStr == '-')
  291.                 {
  292.                     macStr++;
  293.                     undef = true;
  294.                 }
  295.  
  296.                 /* Now extract the macro name */
  297.  
  298.                 macName = macStr;
  299.                 if  (!isalpha(*macStr) && *macStr != '_')
  300.                     goto MAC_ERR;
  301.  
  302.                 macStr++;
  303.  
  304.                 while (*macStr && *macStr != '=')
  305.                 {
  306.                     if  (!isalnum(*macStr) && *macStr != '_')
  307.                         goto MAC_ERR;
  308.  
  309.                     macStr++;
  310.                 }
  311.  
  312.                 if  (undef)
  313.                 {
  314.                     if  (*macStr)
  315.                         goto MAC_ERR;
  316.  
  317.                     if  (scan->scanUndMac(macName))
  318.                         goto MAC_ERR;
  319.                 }
  320.                 else
  321.                 {
  322.                     if  (*macStr)
  323.                     {
  324.                         *macStr++ = 0;
  325.                     }
  326.                     else
  327.                         macStr = "";
  328.  
  329.                     if  (!scan->scanDefMac(macName, macStr))
  330.                         goto MAC_ERR;
  331.                 }
  332.  
  333.                 continue;
  334.  
  335.             MAC_ERR:
  336.  
  337.                 cmpGenError(ERRbadMacDef, macDsc->slString);
  338.             }
  339.         }
  340.  
  341. #ifdef  CORIMP
  342.  
  343.         cmpInitMDimp();
  344.  
  345.         if  (cmpConfig.ccBaseLibs)
  346.             cmpImportMDfile(cmpConfig.ccBaseLibs, false, true);
  347.  
  348.         for (StrList xMD = cmpConfig.ccSuckList; xMD; xMD = xMD->slNext)
  349.             cmpImportMDfile(xMD->slString);
  350.  
  351. #endif
  352.  
  353.         /* Initialize the "using" logic */
  354.  
  355.         parser->parseUsingInit();
  356.  
  357.         /* The initialization is finished */
  358.  
  359.         result = false;
  360.  
  361.         /* End of the error trap's "normal" block */
  362.  
  363.         endErrorTrap(this);
  364.     }
  365.     chkErrorTrap(fltErrorTrap(this, _exception_code(), NULL)) // _exception_info()))
  366.     {
  367.         /* Begin the error trap's cleanup block */
  368.  
  369.         hndErrorTrap(this);
  370.  
  371.         /* An error occurred; free up any resources we've allocated */
  372.  
  373.         if  (cmpParser)
  374.         {
  375.             if  (cmpParserInit)
  376.                 cmpParser->parserDone();
  377.  
  378. #if!MGDDATA
  379.             SMCrlsMem(this, cmpParser);
  380. #endif
  381.             cmpParser = NULL;
  382.         }
  383.  
  384.         result = true;
  385.     }
  386.  
  387.     return  result;
  388. }
  389.  
  390. /*****************************************************************************
  391.  *
  392.  *  Initialize and shutdown metadata logic.
  393.  */
  394.  
  395. void                compiler::cmpInitMD()
  396. {
  397.     if  (!cmpWmdd)
  398.     {
  399.         cmpWmdd = initializeIMD();
  400.         if  (!cmpWmdd)
  401.             cmpFatal(ERRopenCOR);
  402.     }
  403. }
  404.  
  405. /*****************************************************************************
  406.  *
  407.  *  Initialize and shutdown metadata emission logic.
  408.  */
  409.  
  410. void                compiler::cmpInitMDemit()
  411. {
  412.     cmpInitMD();
  413.  
  414.     if  (cmpWmdd->DefineScope(getIID_CorMetaDataRuntime(),
  415.                               0,
  416.                               getIID_IMetaDataEmit(),
  417.                               &cmpWmde))
  418.     {
  419.         cmpFatal(ERRopenCOR);
  420.     }
  421.  
  422.     /* Create the remapper and tell the metadata engine about it */
  423.  
  424. #if MD_TOKEN_REMAP
  425.  
  426.     TokenMapper     remapper = new tokenMap;
  427.  
  428.     // UNDONE: Need to delete remapper when done, right?
  429.  
  430.     if  (cmpWmde->SetHandler(remapper))
  431.         cmpFatal(ERRopenCOR);
  432.  
  433. #endif
  434.  
  435.     cmpPEwriter->WPEinitMDemit(cmpWmdd, cmpWmde);
  436. }
  437.  
  438. void                compiler::cmpDoneMDemit()
  439. {
  440.     if (cmpWmde) { cmpWmde->Release(); cmpWmde = NULL; }
  441.     if (cmpWase) { cmpWase->Release(); cmpWase = NULL; }
  442.     if (cmpWmdd) { cmpWmdd->Release(); cmpWmdd = NULL; }
  443. }
  444.  
  445. /*****************************************************************************
  446.  *
  447.  *  Prepare the output logic for IL/metadata generation.
  448.  */
  449.  
  450. void                compiler::cmpPrepOutput()
  451. {
  452.     WritePE         writer;
  453.     GenILref        gen_IL;
  454.  
  455. #ifdef  OLD_IL
  456.  
  457.     if  (cmpConfig.ccOILgen)
  458.     {
  459.         GenOILref       genOIL;
  460.  
  461. #if MGDDATA
  462.         genOIL = new GenOILref;
  463. #else
  464.         genOIL =    (GenOILref)cmpAllocPerm.nraAlloc(sizeof(*genOIL));
  465. #endif
  466.  
  467.         cmpOIgen = genOIL;
  468.         return;
  469.     }
  470.  
  471. #endif
  472.  
  473. #if MGDDATA
  474.     writer = new WritePE;
  475.     gen_IL = new GenILref;
  476. #else
  477.     writer =    (WritePE )cmpAllocPerm.nraAlloc(sizeof(*writer));
  478.     gen_IL =    (GenILref)cmpAllocPerm.nraAlloc(sizeof(*gen_IL));
  479. #endif
  480.  
  481.     if  (!writer->WPEinit(this, &cmpAllocPerm))
  482.         cmpPEwriter = writer;
  483.  
  484.     if  (!gen_IL->genInit(this, writer, &cmpAllocCGen))
  485.         cmpILgen    = gen_IL;
  486.  
  487.     /* Initialize COM+ metadata emission stuff */
  488.  
  489.     cmpInitMDemit();
  490.  
  491.     /* If we were given either a name or GUID for the image, tell metadata */
  492.  
  493.     if  (cmpConfig.ccOutGUID.Data1|
  494.          cmpConfig.ccOutGUID.Data2|
  495.          cmpConfig.ccOutGUID.Data3)
  496.     {
  497.         printf("UNDONE: Need to create custom attribute for module GUID\n");
  498.     }
  499.  
  500.     if  (cmpConfig.ccOutName)
  501.     {
  502.         const   char *  name = cmpConfig.ccOutName;
  503.  
  504.         if  (cmpWmde->SetModuleProps(cmpUniConv(name, strlen(name)+1)))
  505.             cmpFatal(ERRmetadata);
  506.     }
  507. }
  508.  
  509. /*****************************************************************************
  510.  *
  511.  *  Terminate the compiler: call once per session.
  512.  */
  513.  
  514. bool                compiler::cmpDone(bool errors)
  515. {
  516.     bool            result = true;
  517.  
  518.     setErrorTrap(this);
  519.     begErrorTrap
  520.     {
  521.         if  (cmpErrorCount)
  522.         {
  523.             errors = true;
  524.         }
  525.         else if (!errors)
  526.         {
  527.             /* If it's an EXE make sure it has an entry point */
  528.  
  529.             if  (!cmpFnSymMain && !cmpConfig.ccOutDLL)
  530.             {
  531.                 cmpError(ERRnoEntry);
  532.                 errors = true;
  533.             }
  534.         }
  535.  
  536. #ifdef  OLD_IL
  537.  
  538.         if  (cmpConfig.ccOILgen)
  539.         {
  540.             cmpOIgen->GOIterminate(errors); assert(cmpPEwriter == NULL);
  541.         }
  542.  
  543. #endif
  544.  
  545.         if  (cmpPEwriter)
  546.         {
  547.             StrList         mods;
  548.  
  549.             /* Finish IL code generation */
  550.  
  551.             if  (cmpILgen)
  552.             {
  553.                 cmpILgen->genDone(errors); cmpILgen = NULL;
  554.             }
  555.  
  556.             /* Add any modules the user wants in the manifest */
  557.  
  558.             for (mods = cmpConfig.ccModList; mods; mods = mods->slNext)
  559.             {
  560.                 if  (cmpConfig.ccAssembly)
  561.                     cmpImportMDfile(mods->slString, true);
  562.                 else
  563.                     printf("WARNING: Ignoring '-zm%s', -z not used\n", mods->slString);
  564.             }
  565.  
  566.             /* Add any resources the user wants in the manifest */
  567.  
  568.             for (mods = cmpConfig.ccMRIlist; mods; mods = mods->slNext)
  569.             {
  570.                 if  (cmpConfig.ccAssembly)
  571.                     cmpAssemblyAddRsrc(mods->slString, false);
  572.                 else
  573.                     printf("WARNING: Ignoring '-zr%s', -z not used\n", mods->slString);
  574.             }
  575.  
  576.             /* If we were given a resource file to suck in, do it now */
  577.  
  578.             if  (cmpConfig.ccRCfile)
  579.             {
  580. //              if  (cmpConfig.ccAssembly)
  581. //                  cmpAssemblyAddFile(cmpUniConv(cmpConfig.ccRCfile, strlen(cmpConfig.ccRCfile)));
  582.  
  583.                 result = cmpPEwriter->WPEaddRCfile(cmpConfig.ccRCfile);
  584.                 if  (result)
  585.                     errors = true;
  586.             }
  587.  
  588.             /* Are we supposed to mark our assembly as non-CLS ? */
  589.  
  590.             if  (cmpConfig.ccAsmNonCLS && cmpConfig.ccAssembly)
  591.                 cmpAssemblyNonCLS();
  592.  
  593.             /* Close out the symbol store (must do before closing the PE) */
  594.  
  595.             if  (cmpSymWriter)
  596.             {
  597.                 /* Grab the necessary debug info from the symbol store */
  598.  
  599.                 if (cmpPEwriter->WPEinitDebugDirEmit(cmpSymWriter))
  600.                     cmpGenFatal(ERRdebugInfo);
  601.  
  602.                 if  (cmpSymWriter->Close())
  603.                     cmpGenFatal(ERRdebugInfo);
  604.  
  605.                 cmpSymWriter->Release();
  606.                 cmpSymWriter = NULL;
  607.             }
  608.  
  609.             /* Flush/write the output file */
  610.  
  611.             result = cmpPEwriter->WPEdone(cmpTokenMain, errors);
  612.  
  613.             /* Get rid of any metadata interfaces we've acquired */
  614.  
  615.             cmpDoneMDemit();
  616.  
  617.             /* Throw away the PE writer */
  618.  
  619.             cmpPEwriter = NULL;
  620.         }
  621.  
  622.         /* End of the error trap's "normal" block */
  623.  
  624.         endErrorTrap(this);
  625.     }
  626.     chkErrorTrap(fltErrorTrap(this, _exception_code(), NULL)) // _exception_info()))
  627.     {
  628.         /* Begin the error trap's cleanup block */
  629.  
  630.         hndErrorTrap(this);
  631.     }
  632.  
  633. #ifdef  CORIMP
  634.     cmpDoneMDimp();
  635. #endif
  636.  
  637. #ifdef  DEBUG
  638.     TheCompiler = NULL;
  639.     TheScanner  = NULL;
  640. #endif
  641.  
  642.     if  (!cmpConfig.ccQuiet)
  643.     {
  644. //      if  (cmpFncCntSeen || cmpFncCntComp)
  645. //      {
  646. //          printf("\n");
  647. //
  648. //          if  (cmpFncCntSeen) printf("A total of %6u function/method decl's processed\n", cmpFncCntSeen);
  649. //          if  (cmpFncCntComp) printf("A total of %6u function/method bodies  compiled\n", cmpFncCntComp);
  650. //      }
  651.  
  652.         if  (cmpLineCnt)
  653.             printf("%6u lines of source processed.\n", cmpLineCnt);
  654.     }
  655.  
  656.     return  result;
  657. }
  658.  
  659. /*****************************************************************************
  660.  *
  661.  *  Compile one source file.
  662.  */
  663.  
  664. bool                compiler::cmpPrepSrc(genericRef cookie, stringBuff file,
  665.                                                             QueuedFile buff,
  666.                                                             stringBuff srcText)
  667. {
  668.     SymDef          cmpUnit;
  669.  
  670.     bool            result = false;
  671.     Compiler        comp   = (Compiler)cookie;
  672.  
  673. #ifndef FAST
  674. //  printf("Reading source file '%s'\n", file);
  675. #endif
  676.  
  677.     /* Determine default management mode */
  678.  
  679.     comp->cmpManagedMode = !comp->cmpConfig.ccOldStyle;
  680.  
  681.     /* Convert the source string to a parse tree */
  682.  
  683.     cmpUnit = comp->cmpParser->parsePrepSrc(file, buff, srcText, comp->cmpGlobalST);
  684.  
  685.     comp->cmpLineCnt += comp->cmpScanner->scanGetTokenLno() - 1;
  686.  
  687.     return  !cmpUnit;
  688. }
  689.  
  690. /*****************************************************************************
  691.  *
  692.  *  Allocate a block outside of any allocator - this is to be used for very
  693.  *  large blocks with long lifetimes.
  694.  */
  695.  
  696. genericRef          compiler::cmpAllocBlock(size_t sz)
  697. {
  698. #if MGDDATA
  699.  
  700.     return  new managed char [sz];
  701.  
  702. #else
  703.  
  704.     BlkList         list  = (BlkList)cmpAllocTemp.baAlloc(sizeof(*list));
  705.     void        *   block = LowLevelAlloc(sz);
  706.  
  707.     if  (!block)
  708.         cmpFatal(ERRnoMemory);
  709.  
  710.     list->blAddr = block;
  711.     list->blNext = cmpAllocList;
  712.                    cmpAllocList = list;
  713.  
  714.     return  block;
  715.  
  716. #endif
  717. }
  718.  
  719. /*****************************************************************************
  720.  *
  721.  *  Display the contens of the global symbol table.
  722.  */
  723.  
  724. #ifdef  DEBUG
  725.  
  726. void                compiler::cmpDumpSymbolTable()
  727. {
  728.     assert(cmpGlobalNS);
  729.     assert(cmpGlobalNS->sdSymKind == SYM_NAMESPACE);
  730.  
  731.     cmpGlobalST->stDumpSymbol(cmpGlobalNS, 0, true, true);
  732. }
  733.  
  734. #endif
  735.  
  736. /*****************************************************************************
  737.  *
  738.  *  Expand the generic vector.
  739.  */
  740.  
  741. void                compiler::cmpVecExpand()
  742. {
  743.     unsigned        newSize;
  744.  
  745.     // CONSIDER: reuse deleted entries
  746.  
  747.     /* Start with a reasonable size and then keep doubling */
  748.  
  749.     newSize = cmpVecAlloc ? 2 * cmpVecAlloc
  750.                           : 64;
  751.  
  752.     /* Allocate the new vector */
  753.  
  754. #if MGDDATA
  755.     VecEntryDsc []  newTable = new VecEntryDsc[newSize];
  756. #else
  757.     VecEntryDsc *   newTable = (VecEntryDsc*)LowLevelAlloc(newSize * sizeof(*newTable));
  758. #endif
  759.  
  760.     /* If the vector is non-empty, copy it to the new location */
  761.  
  762.     if  (cmpVecAlloc)
  763.     {
  764.  
  765. #if MGDDATA
  766.         UNIMPL(!"need to copy managed array value");
  767. #else
  768.         memcpy(newTable, cmpVecTable, cmpVecAlloc * sizeof(*newTable));
  769.         LowLevelFree(cmpVecTable);
  770. #endif
  771.     }
  772.  
  773.     /* Remember the new size and address */
  774.  
  775.     cmpVecTable = newTable;
  776.     cmpVecAlloc = newSize;
  777. }
  778.  
  779. /*****************************************************************************
  780.  *
  781.  *  The pre-defined "String"/"Object"/"Class"/.... type is needed but it has
  782.  *  not been defined yet, try to locate it somehow and blow up if we can't
  783.  *  find it.
  784.  */
  785.  
  786. TypDef              compiler::cmpFindStringType()
  787. {
  788.     if  (!cmpClassString)
  789.         cmpGenFatal(ERRbltinTp, "String");
  790.  
  791.     cmpRefTpString = cmpClassString->sdType->tdClass.tdcRefTyp;
  792.  
  793.     return  cmpRefTpString;
  794. }
  795.  
  796. TypDef              compiler::cmpFindObjectType()
  797. {
  798.     if  (!cmpClassObject)
  799.         cmpGenFatal(ERRbltinTp, "Object");
  800.  
  801.     cmpRefTpObject = cmpClassObject->sdType->tdClass.tdcRefTyp;
  802.     cmpRefTpObject->tdIsObjRef = true;
  803.  
  804.     return  cmpRefTpObject;
  805. }
  806.  
  807. TypDef              compiler::cmpFindTypeType()
  808. {
  809.     if  (!cmpClassType)
  810.         cmpGenFatal(ERRbltinTp, "Type");
  811.  
  812.     cmpRefTpType = cmpClassType->sdType->tdClass.tdcRefTyp;
  813.  
  814.     return  cmpRefTpType;
  815. }
  816.  
  817. TypDef              compiler::cmpFindArrayType()
  818. {
  819.     if  (!cmpClassArray)
  820.         cmpGenFatal(ERRbltinTp, "Array");
  821.  
  822.     cmpRefTpArray= cmpClassArray->sdType->tdClass.tdcRefTyp;
  823.  
  824.     return  cmpRefTpArray;
  825. }
  826.  
  827. TypDef              compiler::cmpFindDelegType()
  828. {
  829.     if  (!cmpClassDeleg)
  830.         cmpGenFatal(ERRbltinTp, "Delegate");
  831.  
  832.     cmpRefTpDeleg = cmpClassDeleg->sdType->tdClass.tdcRefTyp;
  833.  
  834.     return  cmpRefTpDeleg;
  835. }
  836.  
  837. TypDef              compiler::cmpFindMultiType()
  838. {
  839.     if  (!cmpClassMulti)
  840.         cmpGenFatal(ERRbltinTp, "MulticastDelegate");
  841.  
  842.     cmpRefTpMulti = cmpClassMulti->sdType->tdClass.tdcRefTyp;
  843.  
  844.     return  cmpRefTpMulti;
  845. }
  846.  
  847. TypDef              compiler::cmpFindExceptType()
  848. {
  849.     if  (!cmpClassExcept)
  850.         cmpGenFatal(ERRbltinTp, "Exception");
  851.  
  852.     cmpRefTpExcept = cmpClassExcept->sdType->tdClass.tdcRefTyp;
  853.  
  854.     return  cmpRefTpExcept;
  855. }
  856.  
  857. TypDef              compiler::cmpFindRTexcpType()
  858. {
  859.     if  (!cmpClassRTexcp)
  860.         cmpGenFatal(ERRbltinTp, "SystemException");
  861.  
  862.     cmpRefTpRTexcp = cmpClassRTexcp->sdType->tdClass.tdcRefTyp;
  863.  
  864.     return  cmpRefTpRTexcp;
  865. }
  866.  
  867. TypDef              compiler::cmpFindArgIterType()
  868. {
  869.     if  (!cmpClassArgIter)
  870.         cmpGenFatal(ERRbltinTp, "ArgIterator");
  871.  
  872.     cmpRefTpArgIter = cmpClassArgIter->sdType->tdClass.tdcRefTyp;
  873.  
  874.     return  cmpRefTpArgIter;
  875. }
  876.  
  877. TypDef              compiler::cmpFindMonitorType()
  878. {
  879.     SymDef          temp;
  880.  
  881.     temp = cmpGlobalST->stLookupNspSym(cmpGlobalHT->hashString("Threading"),
  882.                                        NS_NORM,
  883.                                        cmpNmSpcSystem);
  884.  
  885.     if  (!temp || temp->sdSymKind != SYM_NAMESPACE)
  886.         cmpGenFatal(ERRbltinNS, "System::Threading");
  887.  
  888.     temp = cmpGlobalST->stLookupNspSym(cmpGlobalHT->hashString("Monitor"),
  889.                                        NS_NORM,
  890.                                        temp);
  891.  
  892.     if  (!temp || temp->sdSymKind != SYM_CLASS)
  893.         cmpGenFatal(ERRbltinTp, "System::Threading::Monitor");
  894.  
  895.     cmpClassMonitor = temp;
  896.     cmpRefTpMonitor = temp->sdType->tdClass.tdcRefTyp;
  897.  
  898.     return  cmpRefTpMonitor;
  899. }
  900.  
  901. void                compiler::cmpRThandleClsDcl()
  902. {
  903.     if  (!cmpRThandleCls)
  904.     {
  905.         SymDef          rthCls;
  906.  
  907.         rthCls = cmpGlobalST->stLookupNspSym(cmpGlobalHT->hashString("RuntimeTypeHandle"),
  908.                                              NS_NORM,
  909.                                              cmpNmSpcSystem);
  910.  
  911.         if  (rthCls && rthCls->sdSymKind         == SYM_CLASS
  912.                     && rthCls->sdClass.sdcFlavor == STF_STRUCT)
  913.         {
  914.             cmpRThandleCls = rthCls;
  915.         }
  916.         else
  917.             cmpGenFatal(ERRbltinTp, "System::RuntimeTypeHandle");
  918.     }
  919. }
  920.  
  921. void                compiler::cmpInteropFind()
  922. {
  923.     SymDef          temp;
  924.  
  925.     temp = cmpGlobalST->stLookupNspSym(cmpGlobalHT->hashString("InteropServices"),
  926.                                        NS_NORM,
  927.                                        cmpNmSpcRuntime);
  928.  
  929.     if  (temp && temp->sdSymKind == SYM_NAMESPACE)
  930.     {
  931.         cmpInteropSym = temp;
  932.     }
  933.     else
  934.         cmpGenFatal(ERRbltinNS, "System::Runtime::InteropServices");
  935. }
  936.  
  937. void                compiler::cmpFNsymGetTPHdcl()
  938. {
  939.     if  (!cmpFNsymGetTpHnd)
  940.     {
  941.         SymDef          ovlFnc;
  942.  
  943.         /* Look for the "Type::GetTypeFromHandle" method (it may be overloaded) */
  944.  
  945.         ovlFnc = cmpGlobalST->stLookupClsSym(cmpIdentGetTpHnd, cmpClassType);
  946.  
  947.         if  (ovlFnc)
  948.         {
  949.             SymDef          rthCls = cmpRThandleClsGet();
  950.  
  951.             if  (rthCls)
  952.             {
  953.                 TypDef          rthTyp = rthCls->sdType;
  954.  
  955.                 for (;;)
  956.                 {
  957.                     ArgDscRec       argDsc = ovlFnc->sdType->tdFnc.tdfArgs;
  958.  
  959.                     if  (argDsc.adCount == 1)
  960.                     {
  961.                         assert(argDsc.adArgs);
  962.  
  963.                         if  (symTab::stMatchTypes(argDsc.adArgs->adType, rthTyp))
  964.                             break;
  965.                     }
  966.  
  967.                     ovlFnc = ovlFnc->sdFnc.sdfNextOvl;
  968.                     if  (!ovlFnc)
  969.                         break;
  970.                 }
  971.  
  972.                 cmpFNsymGetTpHnd = ovlFnc;
  973.             }
  974.         }
  975.  
  976.         if  (cmpFNsymGetTpHnd == NULL)
  977.             cmpGenFatal(ERRbltinMeth, "Type::GetTypeFromHandle(RuntimeTypeHandle)");
  978.     }
  979. }
  980.  
  981. void                compiler::cmpNatTypeFind()
  982. {
  983.     if  (!cmpNatTypeSym)
  984.     {
  985.         SymDef          temp;
  986.  
  987.         /* Look for the enum within the "Interop" package */
  988.  
  989.         temp = cmpGlobalST->stLookupNspSym(cmpGlobalHT->hashString("NativeType"),
  990.                                            NS_NORM,
  991.                                            cmpInteropGet());
  992.  
  993.         if  (temp && temp->sdSymKind == SYM_ENUM)
  994.             cmpNatTypeSym = temp;
  995.  
  996.         if  (!cmpNatTypeSym)
  997.             cmpGenFatal(ERRbltinTp, "System::Interop::NativeType");
  998.     }
  999. }
  1000.  
  1001. void                compiler::cmpCharSetFind()
  1002. {
  1003.     if  (!cmpCharSetSym)
  1004.     {
  1005.         SymDef          temp;
  1006.  
  1007.         /* Look for the enum within the "Interop" package */
  1008.  
  1009.         temp = cmpGlobalST->stLookupNspSym(cmpGlobalHT->hashString("CharacterSet"),
  1010.                                            NS_NORM,
  1011.                                            cmpInteropGet());
  1012.  
  1013.         if  (temp && temp->sdSymKind == SYM_ENUM)
  1014.             cmpCharSetSym = temp;
  1015.  
  1016.         if  (!cmpCharSetSym)
  1017.             cmpGenFatal(ERRbltinTp, "System::Interop::CharacterSet");
  1018.     }
  1019. }
  1020.  
  1021. /*****************************************************************************
  1022.  *
  1023.  *  Declare a symbol for "operator new / delete".
  1024.  */
  1025.  
  1026. SymDef              compiler::cmpDeclUmgOper(tokens tokName, const char *extName)
  1027. {
  1028.     ArgDscRec       args;
  1029.     TypDef          type;
  1030.     SymDef          fsym;
  1031.     SymXinfoLnk     desc = NULL;
  1032.  
  1033.     assert(tokName == tkNEW || tokName == tkDELETE);
  1034.  
  1035.     if  (tokName == tkNEW)
  1036.     {
  1037.         cmpParser->parseArgListNew(args,
  1038.                                    1,
  1039.                                    false, cmpTypeUint   , NULL);
  1040.  
  1041. //      type = cmpGlobalST->stNewFncType(args, cmpTypeVoidPtr);
  1042.         type = cmpGlobalST->stNewFncType(args, cmpTypeInt);
  1043.     }
  1044.     else
  1045.     {
  1046.         cmpParser->parseArgListNew(args,
  1047.                                    1,
  1048. //                                 false, cmpTypeVoidPtr, NULL);
  1049.                                    false, cmpTypeInt    , NULL);
  1050.  
  1051.         type = cmpGlobalST->stNewFncType(args, cmpTypeVoid);
  1052.     }
  1053.  
  1054.     fsym = cmpGlobalST->stDeclareSym(cmpGlobalHT->tokenToIdent(tokName),
  1055.                                      SYM_FNC,
  1056.                                      NS_HIDE,
  1057.                                      cmpGlobalNS);
  1058.  
  1059.     /* Allocate a linkage descriptor and fill it in */
  1060.  
  1061. #if MGDDATA
  1062.     desc = new SymXinfoLnk;
  1063. #else
  1064.     desc =    (SymXinfoLnk)cmpAllocPerm.nraAlloc(sizeof(*desc));
  1065. #endif
  1066.  
  1067.     desc->xiKind             = XI_LINKAGE;
  1068.     desc->xiNext             = NULL;
  1069.  
  1070.     desc->xiLink.ldDLLname   = "msvcrt.dll";
  1071.     desc->xiLink.ldSYMname   = extName;
  1072.     desc->xiLink.ldStrings   = 0;
  1073.     desc->xiLink.ldLastErr   = false;
  1074.  
  1075.     /* Store the type and linkage info in the function symbol */
  1076.  
  1077.     fsym->sdType             = type;
  1078.     fsym->sdFnc.sdfExtraInfo = cmpAddXtraInfo(fsym->sdFnc.sdfExtraInfo, desc);
  1079.  
  1080.     return  fsym;
  1081. }
  1082.  
  1083. /*****************************************************************************
  1084.  *
  1085.  *  The given function has been mentioned twice, and we need to check that
  1086.  *  the second declaration/definition doesn't redefine any default argument
  1087.  *  values, and we also transfer any defaults from the old function type.
  1088.  *
  1089.  *  The type that represents the merged function type is returned.
  1090.  *
  1091.  *  WARNING: Since this is here to support a dubious feature (i.e. declaring
  1092.  *           functions in more than one place), we don't bother doing this
  1093.  *           completely clean - when merging, rather than create a new copy
  1094.  *           of the argument list we simply bash the old one.
  1095.  */
  1096.  
  1097. TypDef              compiler::cmpMergeFncType(SymDef fncSym, TypDef newType)
  1098. {
  1099.     ArgDef          params1;
  1100.     ArgDef          params2;
  1101.  
  1102.     TypDef          oldType = fncSym->sdType;
  1103.  
  1104.     /* Both types should be matching function types */
  1105.  
  1106.     assert(oldType->tdTypeKind == TYP_FNC);
  1107.     assert(newType->tdTypeKind == TYP_FNC);
  1108.  
  1109.     /* Make sure the return type agree */
  1110.  
  1111.     if  (!symTab::stMatchTypes(oldType->tdFnc.tdfRett, newType->tdFnc.tdfRett))
  1112.     {
  1113.         fncSym->sdType = newType;
  1114.  
  1115.         cmpErrorQSS(ERRdiffMethRet, fncSym, oldType->tdFnc.tdfRett);
  1116.  
  1117.         return  newType;
  1118.     }
  1119.  
  1120. #ifdef  DEBUG
  1121.  
  1122.     if  (!symTab::stMatchTypes(oldType, newType))
  1123.     {
  1124.         printf("Old method type: '%s'\n", cmpGlobalST->stTypeName(oldType, fncSym, NULL, NULL, false));
  1125.         printf("New method type: '%s'\n", cmpGlobalST->stTypeName(newType, fncSym, NULL, NULL, false));
  1126.     }
  1127.  
  1128.     assert(symTab::stMatchTypes(oldType, newType));
  1129.  
  1130. #endif
  1131.  
  1132.     /* If the old type didn't have any argument defaults, we're done */
  1133.  
  1134.     if  (!oldType->tdFnc.tdfArgs.adDefs)
  1135.         return  newType;
  1136.  
  1137.     /* Get hold of the argument lists */
  1138.  
  1139.     params1 = oldType->tdFnc.tdfArgs.adArgs;
  1140.     params2 = newType->tdFnc.tdfArgs.adArgs;
  1141.  
  1142.     while (params1)
  1143.     {
  1144.         assert(params2);
  1145.  
  1146.         /* GROSS HACK: Simply copy the new parameter name to the old type */
  1147.  
  1148.         params1->adName = params2->adName;
  1149.  
  1150.         /* Continue with the next parameter */
  1151.  
  1152.         params1 = params1->adNext;
  1153.         params2 = params2->adNext;
  1154.     }
  1155.  
  1156.     assert(params1 == NULL);
  1157.     assert(params2 == NULL);
  1158.  
  1159.     return  oldType;
  1160. }
  1161.  
  1162. /*****************************************************************************
  1163.  *
  1164.  *  Invent a new name for an anonymous symbol.
  1165.  */
  1166.  
  1167. Ident               compiler::cmpNewAnonymousName()
  1168. {
  1169.     char            buff[16];
  1170.     Ident           name;
  1171.  
  1172.     sprintf(buff, "$%u", cmpCntAnonymousNames++);
  1173.  
  1174.     name = cmpGlobalHT->hashString(buff);
  1175.     cmpGlobalHT->hashMarkHidden(name);
  1176.  
  1177.     return  name;
  1178. }
  1179.  
  1180. /*****************************************************************************
  1181.  *
  1182.  *  Evaluate a pre-processing constant expression.
  1183.  */
  1184.  
  1185. bool                compiler::cmpEvalPreprocCond()
  1186. {
  1187.     Scanner         ourScanner = cmpScanner;
  1188.  
  1189.     constVal        cval;
  1190.  
  1191.     /* Get the scanner started */
  1192.  
  1193.     ourScanner->scan();
  1194.  
  1195.     /* Parse and evaluate the constant value */
  1196.  
  1197.     if  (cmpParser->parseConstExpr(cval))
  1198.     {
  1199.         if  (ourScanner->scanTok.tok == tkEOL)
  1200.         {
  1201.             /* We have an expression value, check it for 0 */
  1202.  
  1203.             switch (cval.cvVtyp)
  1204.             {
  1205.             default:        return (cval.cvValue.cvIval != 0);
  1206.             case tkLONGINT:
  1207.             case tkULONGINT:return (cval.cvValue.cvLval != 0);
  1208.             case tkFLOAT:   return (cval.cvValue.cvFval != 0);
  1209.             case tkDOUBLE:  return (cval.cvValue.cvDval != 0);
  1210.             }
  1211.         }
  1212.     }
  1213.  
  1214.     /* There has been an error, swallow the rest of the line */
  1215.  
  1216.     while (ourScanner->scanTok.tok != tkEOL)
  1217.         ourScanner->scan();
  1218.  
  1219.     return  false;
  1220. }
  1221.  
  1222. /*****************************************************************************
  1223.  *
  1224.  *  Fetch a constant value and return the corresponding expression.
  1225.  */
  1226.  
  1227. Tree                compiler::cmpFetchConstVal(ConstVal cval, Tree expr)
  1228. {
  1229.     /* What's the type of the constant? */
  1230.  
  1231.     switch (cval->cvVtyp)
  1232.     {
  1233.         __int32         ival;
  1234.  
  1235.     case TYP_BOOL:   ival =             1 & cval->cvValue.cvIval; goto IV;
  1236.     case TYP_CHAR:   ival = (  signed char )cval->cvValue.cvIval; goto IV;
  1237.     case TYP_UCHAR:  ival = (unsigned char )cval->cvValue.cvIval; goto IV;
  1238.     case TYP_SHORT:  ival = (  signed short)cval->cvValue.cvIval; goto IV;
  1239.     case TYP_WCHAR:
  1240.     case TYP_USHORT: ival = (unsigned short)cval->cvValue.cvIval; goto IV;
  1241.     case TYP_INT:
  1242.     case TYP_UINT:   ival =                 cval->cvValue.cvIval; goto IV;
  1243.  
  1244.     IV:
  1245.         expr = cmpCreateIconNode(expr,                 ival, (var_types)cval->cvVtyp);
  1246.         break;
  1247.  
  1248.     case TYP_LONG:
  1249.     case TYP_ULONG:
  1250.         expr = cmpCreateLconNode(expr, cval->cvValue.cvLval, (var_types)cval->cvVtyp);
  1251.         break;
  1252.  
  1253.     case TYP_FLOAT:
  1254.         expr = cmpCreateFconNode(expr, cval->cvValue.cvFval);
  1255.         break;
  1256.  
  1257.     case TYP_DOUBLE:
  1258.         expr = cmpCreateDconNode(expr, cval->cvValue.cvDval);
  1259.         break;
  1260.  
  1261.     case TYP_ENUM:
  1262.  
  1263.         if  (cval->cvType->tdEnum.tdeIntType->tdTypeKind >= TYP_LONG)
  1264.         {
  1265.             UNIMPL(!"fetch long enum value");
  1266.         }
  1267.         else
  1268.         {
  1269.             expr = cmpCreateIconNode(expr, cval->cvValue.cvIval, TYP_VOID);
  1270.  
  1271.             expr->tnOper = TN_CNS_INT;
  1272.             expr->tnVtyp = TYP_ENUM;
  1273.             expr->tnType = cval->cvType;
  1274.         }
  1275.         break;
  1276.  
  1277.     case TYP_PTR:
  1278.     case TYP_REF:
  1279.  
  1280.         /* Must be either a string or "null" or icon cast to pointer */
  1281.  
  1282.         if  (cval->cvIsStr)
  1283.         {
  1284.             assert(cval->cvType == cmpTypeCharPtr ||
  1285.                    cval->cvType == cmpTypeWchrPtr || cval->cvType == cmpFindStringType());
  1286.  
  1287.             expr = cmpCreateSconNode(cval->cvValue.cvSval->csStr,
  1288.                                      cval->cvValue.cvSval->csLen,
  1289.                                      cval->cvHasLC,
  1290.                                      cval->cvType);
  1291.         }
  1292.         else
  1293.         {
  1294.             /* This could be NULL or a constant cast to a pointer */
  1295.  
  1296.             expr = cmpCreateExprNode(expr, TN_NULL, cval->cvType);
  1297.  
  1298.             if  (cval->cvType == cmpFindObjectType() && !cval->cvValue.cvIval)
  1299.                 return  expr;
  1300.  
  1301.             /* It's an integer constant cast to a pointer */
  1302.  
  1303.             expr->tnOper             = TN_CNS_INT;
  1304.             expr->tnIntCon.tnIconVal = cval->cvValue.cvIval;
  1305.         }
  1306.         break;
  1307.  
  1308.     case TYP_UNDEF:
  1309.         return cmpCreateErrNode();
  1310.  
  1311.     default:
  1312. #ifdef  DEBUG
  1313.         printf("\nConstant type: '%s'\n", cmpGlobalST->stTypeName(cval->cvType, NULL, NULL, NULL, false));
  1314. #endif
  1315.         UNIMPL(!"unexpected const type");
  1316.     }
  1317.  
  1318.     /* The type of the value is "fixed" */
  1319.  
  1320.     expr->tnFlags |= TNF_BEEN_CAST;
  1321.  
  1322.     return  expr;
  1323. }
  1324.  
  1325. /*****************************************************************************
  1326.  *
  1327.  *  Return the class/namespace that contains the given symbol. This is made
  1328.  *  a bit tricky by anonymous unions.
  1329.  */
  1330.  
  1331. SymDef              compiler::cmpSymbolOwner(SymDef sym)
  1332. {
  1333.     for (;;)
  1334.     {
  1335.         sym = sym->sdParent;
  1336.  
  1337.         if  (sym->sdSymKind == SYM_CLASS && sym->sdClass.sdcAnonUnion)
  1338.             continue;
  1339.  
  1340.         assert(sym->sdSymKind == SYM_CLASS ||
  1341.                sym->sdSymKind == SYM_NAMESPACE);
  1342.  
  1343.         return  sym;
  1344.     }
  1345. }
  1346.  
  1347. /*****************************************************************************
  1348.  *
  1349.  *  Fold any constant sub-expression in the given bound expression tree.
  1350.  */
  1351.  
  1352. Tree                compiler::cmpFoldExpression(Tree expr)
  1353. {
  1354.     // UNDONE: fold expr
  1355.  
  1356.     return  expr;
  1357. }
  1358.  
  1359. /*****************************************************************************
  1360.  *
  1361.  *  Returns true if the given type is an acceptable exception type.
  1362.  */
  1363.  
  1364. bool                compiler::cmpCheckException(TypDef type)
  1365. {
  1366.     switch (type->tdTypeKind)
  1367.     {
  1368.     case TYP_REF:
  1369.  
  1370.         assert(cmpClassExcept);
  1371.         assert(cmpClassRTexcp);
  1372.  
  1373.         if  (cmpIsBaseClass(cmpClassExcept->sdType, type->tdRef.tdrBase))
  1374.             return  true;
  1375.         if  (cmpIsBaseClass(cmpClassRTexcp->sdType, type->tdRef.tdrBase))
  1376.             return  true;
  1377.  
  1378.         return  false;
  1379.  
  1380.     default:
  1381.         return  false;
  1382.  
  1383.     case TYP_TYPEDEF:
  1384.         return cmpCheckException(cmpActualType(type));
  1385.     }
  1386. }
  1387.  
  1388. /*****************************************************************************
  1389.  *
  1390.  *  Convert a string to Unicode.
  1391.  *
  1392.  *  WARNING: This routine usually reuses the same buffer so don't call it
  1393.  *           while hanging on to any results from previous calls.
  1394.  */
  1395.  
  1396. #if MGDDATA
  1397.  
  1398. wideString          compiler::cmpUniConv(char managed [] str, size_t len)
  1399. {
  1400.     UNIMPL(!"");
  1401.     return  "hi";
  1402. }
  1403.  
  1404. wideString          compiler::cmpUniConv(const char *    str, size_t len)
  1405. {
  1406.     UNIMPL(!"");
  1407.     return  "hi";
  1408. }
  1409.  
  1410. #else
  1411.  
  1412. wideString          compiler::cmpUniConv(const char *    str, size_t len)
  1413. {
  1414.     /* If there are embedded nulls, we can't use mbstowcs() */
  1415.  
  1416.     if  (strlen(str)+1 < len)
  1417.         return cmpUniCnvW(str, &len);
  1418.  
  1419.     if  (len > cmpUniConvSize)
  1420.     {
  1421.         size_t          newsz;
  1422.  
  1423.         /* The buffer is apparently too small, so grab a bigger one */
  1424.  
  1425.         cmpUniConvSize = newsz = max(cmpUniConvSize*2, len + len/2);
  1426.         cmpUniConvAddr = (wchar *)cmpAllocTemp.baAlloc(roundUp(2*newsz));
  1427.     }
  1428.  
  1429.     mbstowcs(cmpUniConvAddr, str, cmpUniConvSize);
  1430.  
  1431.     return   cmpUniConvAddr;
  1432. }
  1433.  
  1434. wideString          compiler::cmpUniCnvW(const char *    str, size_t*lenPtr)
  1435. {
  1436.     size_t          len = *lenPtr;
  1437.  
  1438.     wchar       *   dst;
  1439.     const BYTE  *   src;
  1440.     const BYTE  *   end;
  1441.  
  1442.     bool            nch = false;
  1443.  
  1444.     if  (len > cmpUniConvSize)
  1445.     {
  1446.         size_t          newsz;
  1447.  
  1448.         /* The buffer is apparently too small, so grab a bigger one */
  1449.  
  1450.         cmpUniConvSize = newsz = max(cmpUniConvSize*2, len + len/2);
  1451.         cmpUniConvAddr = (wchar *)cmpAllocTemp.baAlloc(roundUp(2*newsz));
  1452.     }
  1453.  
  1454.     /* This is not entirely right, but it's good enough for now */
  1455.  
  1456.     dst = cmpUniConvAddr;
  1457.     src = (const BYTE *)str;
  1458.     end = src + len;
  1459.  
  1460.     do
  1461.     {
  1462.         unsigned        ch = *src++;
  1463.  
  1464.         if  (ch != 0xFF)
  1465.         {
  1466.             *dst++ = ch;
  1467.         }
  1468.         else
  1469.         {
  1470.             ch = *src++;
  1471.  
  1472.             *dst++ = ch | (*src++ << 8);
  1473.         }
  1474.     }
  1475.     while (src < end);
  1476.  
  1477.     *lenPtr = dst - cmpUniConvAddr; assert(*lenPtr <= len);
  1478.  
  1479. //  printf("Wide string = '%ls', len = %u\n", cmpUniConvAddr, *lenPtr);
  1480.  
  1481.     return   cmpUniConvAddr;
  1482. }
  1483.  
  1484. #endif
  1485.  
  1486. /*****************************************************************************
  1487.  *
  1488.  *  The following maps a type kind to its built-in value type name equivalent.
  1489.  */
  1490.  
  1491. static
  1492. const   char *      cmpStdValTpNames[] =
  1493. {
  1494.     NULL,           // UNDEF
  1495.     "Void",         // VOID
  1496.     "Boolean",      // BOOL
  1497.     "Char",         // WCHAR
  1498.     "SByte",        // CHAR
  1499.     "Byte",         // UCHAR
  1500.     "Int16",        // SHORT
  1501.     "UInt16",       // USHORT
  1502.     "Int32",        // INT
  1503.     "UInt32",       // UINT
  1504.     "Integer" ,     // NATINT
  1505.     "Uinteger",     // NATUINT
  1506.     "Int64",        // LONG
  1507.     "UInt64",       // ULONG
  1508.     "Single",       // FLOAT
  1509.     "Double",       // DOUBLE
  1510.     "Extended",     // LONGDBL
  1511. };
  1512.  
  1513. /*****************************************************************************
  1514.  *
  1515.  *  Hash all the standard value type names and mark them as such.
  1516.  */
  1517.  
  1518. void                compiler::cmpInitStdValTypes()
  1519. {
  1520.     HashTab         hash = cmpGlobalHT;
  1521.     unsigned        type;
  1522.  
  1523.     for (type = 0; type < arraylen(cmpStdValTpNames); type++)
  1524.     {
  1525.         if  (cmpStdValTpNames[type])
  1526.         {
  1527.             Ident       name = hash->hashString(cmpStdValTpNames[type]);
  1528.  
  1529.             hashTab::setIdentFlags(name, IDF_STDVTP|IDF_PREDEF);
  1530.  
  1531.             cmpStdValueIdens[type] = name;
  1532.         }
  1533.     }
  1534. }
  1535.  
  1536. /*****************************************************************************
  1537.  *
  1538.  *  Given a value type, return the corresponding intrinsic type (or TYP_UNDEF
  1539.  *  if the argument doesn't represent a "built-in" value type).
  1540.  */
  1541.  
  1542. var_types           compiler::cmpFindStdValType(TypDef type)
  1543. {
  1544.     assert(type->tdTypeKind == TYP_CLASS);
  1545.     assert(type->tdIsIntrinsic);
  1546.  
  1547.     if  (type->tdClass.tdcIntrType == TYP_UNDEF)
  1548.     {
  1549.         Ident           name = type->tdClass.tdcSymbol->sdName;
  1550.  
  1551.         if  (hashTab::getIdentFlags(name) & IDF_STDVTP)
  1552.         {
  1553.             unsigned        vtyp;
  1554.  
  1555.             for (vtyp = 0; vtyp < arraylen(cmpStdValTpNames); vtyp++)
  1556.             {
  1557.                 if  (cmpStdValueIdens[vtyp] == name)
  1558.                 {
  1559.                     type->tdClass.tdcIntrType = vtyp;
  1560.                     break;
  1561.                 }
  1562.             }
  1563.         }
  1564.     }
  1565.  
  1566.     return  (var_types)type->tdClass.tdcIntrType;
  1567. }
  1568.  
  1569. /*****************************************************************************
  1570.  *
  1571.  *  Given an intrinsic type, return the corresponding value type.
  1572.  */
  1573.  
  1574. TypDef              compiler::cmpFindStdValType(var_types vtp)
  1575. {
  1576.     Ident           nam;
  1577.     TypDef          typ;
  1578.     SymDef          sym;
  1579.  
  1580.     if  (vtp == TYP_UNDEF)
  1581.         return  NULL;
  1582.  
  1583.     assert(vtp < TYP_lastIntrins);
  1584.     assert(vtp < arraylen(cmpStdValueTypes));
  1585.     assert(vtp < arraylen(cmpStdValTpNames));
  1586.  
  1587.     /* If we've already created the type, return it */
  1588.  
  1589.     typ = cmpStdValueTypes[vtp];
  1590.     if  (typ)
  1591.         return  typ;
  1592.  
  1593.     /* Do we have "System" loaded? */
  1594.  
  1595.     if  (!cmpNmSpcSystem)
  1596.         return  NULL;
  1597.  
  1598.     /* Get hold of the type's name and look it up */
  1599.  
  1600.     nam = cmpStdValueIdens[vtp]; assert(nam);
  1601.     sym = cmpGlobalST->stLookupNspSym(nam, NS_NORM, cmpNmSpcSystem);
  1602.  
  1603.     if  (sym && sym->sdSymKind == SYM_CLASS)
  1604.     {
  1605.         cmpStdValueTypes[vtp] = sym->sdType;
  1606.         return  sym->sdType;
  1607.     }
  1608.  
  1609.     return  NULL;
  1610. }
  1611.  
  1612. /*****************************************************************************
  1613.  *
  1614.  *  Report the use of a symbol marked as obsolete (deprecated).
  1615.  */
  1616.  
  1617. void                compiler::cmpObsoleteUse(SymDef sym, unsigned wrn)
  1618. {
  1619.     assert(sym && sym->sdIsDeprecated);
  1620.  
  1621.     if  (sym->sdIsImport)
  1622.     {
  1623.         SymDef          clsSym;
  1624.         mdToken         token;
  1625.  
  1626.         const   void *  blobAddr;
  1627.         ULONG           blobSize;
  1628.  
  1629.         /* Try to get hold of the string attached to the attribute */
  1630.  
  1631.         switch (sym->sdSymKind)
  1632.         {
  1633.         case SYM_CLASS:
  1634.             token  = sym->sdClass.sdcMDtypedef;
  1635.             clsSym = sym;
  1636.             break;
  1637.  
  1638.         case SYM_FNC:
  1639.             token  = sym->sdFnc.sdfMDtoken;
  1640.             clsSym = sym->sdParent;
  1641.             break;
  1642.  
  1643.         default:
  1644.             goto NOSTR;
  1645.         }
  1646.  
  1647.         assert(clsSym && clsSym->sdSymKind == SYM_CLASS && clsSym->sdIsImport);
  1648.  
  1649.         if      (!clsSym->sdClass.sdcMDimporter->MDfindAttr(token,                   L"Deprecated", &blobAddr, &blobSize))
  1650.         {
  1651.         }
  1652.         else if (!clsSym->sdClass.sdcMDimporter->MDfindAttr(token, L"System.Attributes.Deprecated", &blobAddr, &blobSize))
  1653.         {
  1654.         }
  1655.         else if (!clsSym->sdClass.sdcMDimporter->MDfindAttr(token,     L"System.ObsoleteAttribute", &blobAddr, &blobSize))
  1656.         {
  1657.         }
  1658.         else
  1659.             goto NOSTR;
  1660.  
  1661.         if  (!blobAddr || !blobSize)
  1662.             goto NOSTR;
  1663.  
  1664. //      printf("Blob [%2u bytes] = '%s'\n", blobSize, (BYTE*)blobAddr+3);
  1665.  
  1666.         cmpWarnQns(WRNobsoleteStr, sym, (char*)blobAddr+3);
  1667.  
  1668.     NOSTR:
  1669.  
  1670.         cmpWarnQnm(wrn, sym);
  1671.     }
  1672.  
  1673.     sym->sdIsDeprecated = false;
  1674. }
  1675.  
  1676. /*****************************************************************************
  1677.  *
  1678.  *  Make sure space has been allocated for the given variable in the data
  1679.  *  section of the output file. Returns the address of the data section
  1680.  *  where its initial value is located,
  1681.  */
  1682.  
  1683. memBuffPtr          compiler::cmpAllocGlobVar(SymDef varSym)
  1684. {
  1685.     memBuffPtr      addr;
  1686.  
  1687.     assert(varSym);
  1688.     assert(varSym->sdSymKind == SYM_VAR);
  1689.     assert(varSym->sdParent->sdSymKind   != SYM_CLASS ||
  1690.            varSym->sdParent->sdIsManaged == false);
  1691.  
  1692.     if  (!varSym->sdVar.sdvAllocated)
  1693.     {
  1694.         TypDef          tp = cmpActualType(varSym->sdType);
  1695.  
  1696.         size_t          sz;
  1697.         size_t          al;
  1698.  
  1699.         /* The variable better not be an undimensioned array */
  1700.  
  1701.         assert(tp->tdTypeKind != TYP_ARRAY || !tp->tdIsUndimmed);
  1702.  
  1703.         /* Get hold of the size and alignment of the variable */
  1704.  
  1705.         if  (varSym->sdVar.sdvIsVtable)
  1706.         {
  1707.             assert(varSym->sdParent);
  1708.             assert(varSym->sdParent->sdSymKind == SYM_CLASS);
  1709.             assert(varSym->sdParent->sdIsManaged == false);
  1710.  
  1711.             sz = sizeof(void*) * varSym->sdParent->sdClass.sdcVirtCnt;
  1712.             al = sizeof(void*);
  1713.         }
  1714.         else
  1715.             sz = cmpGetTypeSize(tp, &al);
  1716.  
  1717.         /* Now reserve space in the data section */
  1718.  
  1719.         varSym->sdVar.sdvOffset = cmpPEwriter->WPEsecRsvData(PE_SECT_data,
  1720.                                                              sz,
  1721.                                                              al,
  1722.                                                              addr);
  1723.  
  1724.         /* Remember that we've allocated space for the variable */
  1725.  
  1726.         varSym->sdVar.sdvAllocated = true;
  1727.     }
  1728.     else
  1729.     {
  1730.         addr = cmpPEwriter->WPEsecAdrData(PE_SECT_data, varSym->sdVar.sdvOffset);
  1731.     }
  1732.  
  1733.     return  addr;
  1734. }
  1735.  
  1736. /*****************************************************************************
  1737.  *
  1738.  *  Tables used by cmpDecodeAlign() and cmpEncodeAlign().
  1739.  */
  1740.  
  1741. BYTE                cmpAlignDecodes[] =
  1742. {
  1743.     0,  //  0
  1744.     1,  //  1
  1745.     2,  //  2
  1746.     4,  //  3
  1747.     8,  //  4
  1748.     16  //  5
  1749. };
  1750.  
  1751. BYTE                cmpAlignEncodes[] =
  1752. {
  1753.     0,  //  0
  1754.     1,  //  1
  1755.     2,  //  2
  1756.     0,  //  3
  1757.     3,  //  4
  1758.     0,  //  5
  1759.     0,  //  6
  1760.     0,  //  7
  1761.     4,  //  8
  1762.     0,  //  9
  1763.     0,  // 10
  1764.     0,  // 11
  1765.     0,  // 12
  1766.     0,  // 13
  1767.     0,  // 14
  1768.     0,  // 15
  1769.     5,  // 16
  1770. };
  1771.  
  1772. /*****************************************************************************
  1773.  *
  1774.  *  Return the size and alignment of the type.
  1775.  */
  1776.  
  1777. size_t              compiler::cmpGetTypeSize(TypDef type, size_t *alignPtr)
  1778. {
  1779.     var_types       vtp;
  1780.  
  1781.     size_t          sz;
  1782.     size_t          al;
  1783.  
  1784. AGAIN:
  1785.  
  1786.     vtp = type->tdTypeKindGet();
  1787.  
  1788.     if  (vtp <= TYP_lastIntrins)
  1789.     {
  1790.         al = symTab::stIntrTypeAlign(vtp);
  1791.         sz = symTab::stIntrTypeSize (vtp);
  1792.     }
  1793.     else
  1794.     {
  1795.         switch (vtp)
  1796.         {
  1797.         case TYP_ENUM:
  1798.             cmpDeclSym(type->tdEnum.tdeSymbol);
  1799.             type = type->tdEnum.tdeIntType;
  1800.             goto AGAIN;
  1801.  
  1802.         case TYP_TYPEDEF:
  1803.             cmpDeclSym(type->tdTypedef.tdtSym);
  1804.             type = type->tdTypedef.tdtType;
  1805.             goto AGAIN;
  1806.  
  1807.         case TYP_CLASS:
  1808.  
  1809.             /* Make sure the class is declared */
  1810.  
  1811.             cmpDeclSym(type->tdClass.tdcSymbol);
  1812.  
  1813.             // UNDONE: Make sure the class is not managed
  1814.  
  1815.             al = cmpDecodeAlign(type->tdClass.tdcAlignment);
  1816.             sz =                type->tdClass.tdcSize;
  1817.             break;
  1818.  
  1819.         case TYP_REF:
  1820.         case TYP_PTR:
  1821.             al =
  1822.             sz = cmpConfig.ccTgt64bit ? 8 : 4;
  1823.             break;
  1824.  
  1825.         case TYP_ARRAY:
  1826.  
  1827.             /* Is this a managed array? */
  1828.  
  1829.             if  (type->tdIsManaged)
  1830.             {
  1831.                 /* A managed array is really just a GC ref */
  1832.  
  1833.                 al =
  1834.                 sz = cmpConfig.ccTgt64bit ? 8 : 4;
  1835.             }
  1836.             else
  1837.             {
  1838.                 /* Unmanaged array: use the element's alignment */
  1839.  
  1840.                 sz = cmpGetTypeSize(type->tdArr.tdaElem, &al);
  1841.  
  1842.                 if  (type->tdIsUndimmed)
  1843.                 {
  1844.                     /* Unmanaged array without a dimension - set size to 0 */
  1845.  
  1846.                     sz = 0;
  1847.                 }
  1848.                 else
  1849.                 {
  1850.                     DimDef          dims = type->tdArr.tdaDims;
  1851.  
  1852.                     assert(dims);
  1853.                     assert(dims->ddNext == NULL);
  1854.                     assert(dims->ddIsConst);
  1855.  
  1856.                     if  (!dims->ddSize)
  1857.                     {
  1858.                         cmpError(ERRemptyArray);
  1859.                         dims->ddSize = 1;
  1860.                     }
  1861.  
  1862.                     sz *= dims->ddSize;
  1863.                 }
  1864.             }
  1865.             break;
  1866.  
  1867.         case TYP_FNC:
  1868.         case TYP_VOID:
  1869.  
  1870.             al = sz = 0;
  1871.             break;
  1872.  
  1873.         default:
  1874. #ifdef  DEBUG
  1875.             printf("%s: ", cmpGlobalST->stTypeName(type, NULL, NULL, NULL, false));
  1876. #endif
  1877.             NO_WAY(!"unexpected type");
  1878.         }
  1879.     }
  1880.  
  1881.     if  (alignPtr)
  1882.         *alignPtr = al;
  1883.  
  1884.     return sz;
  1885. }
  1886.  
  1887. /*****************************************************************************
  1888.  *
  1889.  *  Given an unmanaged (early-bound) class/struct/union, assign offsets to
  1890.  *  its members and compute its total size.
  1891.  */
  1892.  
  1893. void                compiler::cmpLayoutClass(SymDef clsSym)
  1894. {
  1895.     TypDef          clsTyp  = clsSym->sdType;
  1896.     bool            virtFns = clsSym->sdClass.sdcHasVptr;
  1897.     bool            isUnion = (clsTyp->tdClass.tdcFlavor == STF_UNION);
  1898.  
  1899.     unsigned        maxAl;
  1900.     unsigned        align;
  1901.     unsigned        offset;
  1902.     unsigned        totSiz;
  1903.  
  1904.     unsigned        curBFoffs;
  1905.     unsigned        curBFbpos;
  1906.     unsigned        curBFmore;
  1907.     var_types       curBFtype;
  1908.  
  1909.     bool            hadMem;
  1910.     SymDef          memSym;
  1911.  
  1912.     assert(clsSym->sdSymKind == SYM_CLASS);
  1913.     assert(clsSym->sdIsManaged == false);
  1914.     assert(clsSym->sdCompileState >= CS_DECLARED);
  1915.  
  1916. //  printf("Layout [%u,%u] '%s'\n", clsTyp->tdClass.tdcLayoutDoing, clsTyp->tdClass.tdcLayoutDone, clsSym->sdSpelling());
  1917.  
  1918.     if  (clsTyp->tdClass.tdcLayoutDone)
  1919.         return;
  1920.  
  1921.     /* Check for the case where a class embeds itself (or a derived copy) */
  1922.  
  1923.     if  (clsTyp->tdClass.tdcLayoutDoing)
  1924.     {
  1925.         cmpErrorQnm(ERRrecClass, clsSym);
  1926.  
  1927.         /* One error message for this is enough */
  1928.  
  1929.         clsTyp->tdClass.tdcLayoutDone = true;
  1930.         return;
  1931.     }
  1932.  
  1933.     maxAl  = cmpDecodeAlign(clsSym->sdClass.sdcDefAlign);
  1934.     align  = 1;
  1935.     offset = 0;
  1936.     totSiz = 0;
  1937.     hadMem = false;
  1938.  
  1939. //  printf("Max. alignment is %2u for '%s'\n", maxAl, clsSym->sdSpelling());
  1940.  
  1941.     clsTyp->tdClass.tdcLayoutDoing = true;
  1942.  
  1943.     /* Reserve space for the base class, if any */
  1944.  
  1945.     if  (clsTyp->tdClass.tdcBase)
  1946.     {
  1947.         TypDef          baseTyp =  clsTyp->tdClass.tdcBase;
  1948.         SymDef          baseSym = baseTyp->tdClass.tdcSymbol;
  1949.  
  1950.         assert(baseSym->sdSymKind == SYM_CLASS);
  1951.  
  1952.         if  (baseSym->sdIsManaged)
  1953.         {
  1954.             /* This can only happen after egregious errors, right? */
  1955.  
  1956.             assert(cmpErrorCount);
  1957.             return;
  1958.         }
  1959.  
  1960.         /* Make sure we've laid out the base and reserve space for it */
  1961.  
  1962.         cmpLayoutClass(baseSym); totSiz = offset = baseTyp->tdClass.tdcSize;
  1963.  
  1964.         /*
  1965.             If this class has any virtual functions and the base class
  1966.             doesn't, we'll have to add a vtable pointer in front of
  1967.             the base class.
  1968.          */
  1969.  
  1970.         if  (virtFns && !baseSym->sdClass.sdcHasVptr)
  1971.         {
  1972.             /* Remember that we're adding a vtable pointer */
  1973.  
  1974.             clsSym->sdClass.sdc1stVptr = true;
  1975.  
  1976.             /* Make room for the vtable pointer in the class */
  1977.  
  1978.             offset += sizeof(void*);
  1979.         }
  1980.     }
  1981.     else
  1982.     {
  1983.         /* Reserve space for the vtable, if any virtuals are present */
  1984.  
  1985.         if  (virtFns)
  1986.             offset += sizeof(void*);
  1987.     }
  1988.  
  1989.     /* Now assign offsets to all members */
  1990.  
  1991.     curBFoffs = 0;
  1992.     curBFbpos = 0;
  1993.     curBFmore = 0;
  1994.     curBFtype = TYP_UNDEF;
  1995.  
  1996.     for (memSym = clsSym->sdScope.sdScope.sdsChildList;
  1997.          memSym;
  1998.          memSym = memSym->sdNextInScope)
  1999.     {
  2000.         TypDef          memType;
  2001.         size_t          memSize;
  2002.         size_t          memAlign;
  2003.  
  2004.         if  (memSym->sdSymKind != SYM_VAR)
  2005.             continue;
  2006.         if  (memSym->sdIsStatic)
  2007.             continue;
  2008.  
  2009.         /* We have an instance member, get its size/alignment */
  2010.  
  2011.         hadMem  = true;
  2012.  
  2013.         /* Special case: undimensioned array in unmanaged class */
  2014.  
  2015.         memType = cmpActualType(memSym->sdType); assert(memType);
  2016.  
  2017.         if  (memType->tdIsManaged)
  2018.         {
  2019.             /* Assume that this has already been flagged as an error */
  2020.  
  2021.             assert(cmpErrorCount);
  2022.  
  2023.             /* Supply reasonable value just so that we can continue */
  2024.  
  2025.             memSize = memAlign = sizeof(void*);
  2026.         }
  2027.         else
  2028.         {
  2029.             TypDef          chkType = memType;
  2030.             TypDef          sizType = memType;
  2031.  
  2032.             if  (memType->tdTypeKind == TYP_ARRAY)
  2033.             {
  2034.                 chkType = memType->tdArr.tdaElem;
  2035.  
  2036.                 if  (memType->tdIsUndimmed && !isUnion)
  2037.                 {
  2038.                     SymDef      nxtMem;
  2039.  
  2040.                 UNDIM_ARR:
  2041.  
  2042.                     /* Make sure that no other non-static members follow */
  2043.  
  2044.                     nxtMem = memSym;
  2045.                     for (;;)
  2046.                     {
  2047.                         nxtMem = nxtMem->sdNextInScope;
  2048.                         if  (!nxtMem)
  2049.                             break;
  2050.  
  2051.                         if  (memSym->sdSymKind  == SYM_VAR &&
  2052.                              memSym->sdIsStatic == false)
  2053.                         {
  2054.                             cmpError(ERRbadUndimMem);
  2055.                         }
  2056.                     }
  2057.  
  2058.                     sizType = chkType;
  2059.                 }
  2060.                 else if (memType->tdArr.tdaDcnt == 1)
  2061.                 {
  2062.                     DimDef          dims = memType->tdArr.tdaDims;
  2063.  
  2064.                     /* Make a zero-length array into an undimmed one */
  2065.  
  2066.                     assert(dims);
  2067.                     assert(dims->ddNext == NULL);
  2068.  
  2069.                     if  (dims->ddIsConst && dims->ddSize == 0 && !isUnion)
  2070.                     {
  2071.                         memType->tdIsUndimmed = true;
  2072.                         goto UNDIM_ARR;
  2073.                     }
  2074.                 }
  2075.             }
  2076.  
  2077.             if  (chkType == clsTyp)
  2078.             {
  2079.                 cmpError(ERRrecFld);
  2080.                 memSize = memAlign = sizeof(void*);
  2081.             }
  2082.             else
  2083.                 memSize = cmpGetTypeSize(sizType, &memAlign);
  2084.         }
  2085.  
  2086.         /* Honor the requested packing */
  2087.  
  2088.         if  (memAlign > maxAl)
  2089.              memAlign = maxAl;
  2090.  
  2091.         /* Keep track of the max. alignment */
  2092.  
  2093.         if  (align < memAlign)
  2094.              align = memAlign;
  2095.  
  2096.         /* Is the member a bitfield? */
  2097.  
  2098.         if  (memSym->sdVar.sdvBitfield)
  2099.         {
  2100.             unsigned        cnt = memSym->sdVar.sdvBfldInfo.bfWidth;
  2101.             var_types       vtp = cmpActualVtyp(memType);
  2102.  
  2103.             /* Is there enough room for the member in the current cell? */
  2104.  
  2105.             if  (symTab::stIntrTypeSize(vtp) !=
  2106.                  symTab::stIntrTypeSize(curBFtype) || cnt > curBFmore)
  2107.             {
  2108.                 /* Special case: byte bitfields can straddle boundaries */
  2109.  
  2110.                 if  (memSize == 1 && curBFmore)
  2111.                 {
  2112.                     /* Add more room by stealing the next byte */
  2113.  
  2114.                     offset   += 1;
  2115.                     curBFmore = 8;
  2116.  
  2117.                     /* Keep the bit offset below 8 */
  2118.  
  2119.                     if  (curBFbpos >= 8)
  2120.                     {
  2121.                         curBFoffs += curBFbpos / 8;
  2122.                         curBFbpos  = curBFbpos % 8;
  2123.                     }
  2124.                 }
  2125.                 else
  2126.                 {
  2127.                     /* We need to start a new storage cell for the bitfield */
  2128.  
  2129.                     offset +=  (memAlign - 1);
  2130.                     offset &= ~(memAlign - 1);
  2131.  
  2132.                     /* Remember where the bitfield starts */
  2133.  
  2134.                     curBFoffs = offset;
  2135.                                 offset += memSize;
  2136.  
  2137.                     /* The memory cell is completely free */
  2138.  
  2139.                     curBFbpos = 0;
  2140.                     curBFmore = 8 * memSize;
  2141.                     curBFtype = vtp;
  2142.                 }
  2143.  
  2144.                 /* We better have enough room for the new bitfield */
  2145.  
  2146.                 assert(cnt <= curBFmore);
  2147.             }
  2148.  
  2149.             /* Fit the member in the next available bit section */
  2150.  
  2151.             memSym->sdVar.sdvOffset            = curBFoffs;
  2152.             memSym->sdVar.sdvBfldInfo.bfOffset = curBFbpos;
  2153.  
  2154. //          printf("Member [bf=%2u;%2u] at offset %04X: '%s'\n", curBFbpos, cnt, curBFoffs, memSym->sdSpelling());
  2155.  
  2156.             /* Update the bit position/count and we're done with this one */
  2157.  
  2158.             curBFbpos += cnt;
  2159.             curBFmore -= cnt;
  2160.         }
  2161.         else
  2162.         {
  2163.             /* Make sure the member is properly aligned */
  2164.  
  2165.             offset +=  (memAlign - 1);
  2166.             offset &= ~(memAlign - 1);
  2167.  
  2168.             /* Record the offset of this member */
  2169.  
  2170.             memSym->sdVar.sdvOffset = offset;
  2171.  
  2172. //          printf("Member [size =%3u] at offset %04X: %s.%s\n", memSize, offset, clsSym->sdSpelling(), memSym->sdSpelling());
  2173.  
  2174. #if 0
  2175.  
  2176.             /* Is this an anonymous union? */
  2177.  
  2178.             if  (memType->tdTypeKind == TYP_CLASS &&
  2179.                  memType->tdClass.tdcAnonUnion)
  2180.             {
  2181.                 SymDef          tmpSym;
  2182.                 SymDef          aunSym = memType->tdClass.tdcSymbol;
  2183.  
  2184.                 if  (!memType->tdClass.tdcLayoutDone)
  2185.                     cmpLayoutClass(aunSym);
  2186.  
  2187.                 for (tmpSym = aunSym->sdScope.sdScope.sdsChildList;
  2188.                      tmpSym;
  2189.                      tmpSym = tmpSym->sdNextInScope)
  2190.                 {
  2191.                     printf("Anon union member '%s'\n", tmpSym->sdSpelling());
  2192.                 }
  2193.             }
  2194.  
  2195. #endif
  2196.  
  2197.             /* Bump the offset for the next member */
  2198.  
  2199.             offset += memSize;
  2200.         }
  2201.  
  2202.         /* For unions, keep track of the largest member size */
  2203.  
  2204.         if  (isUnion)
  2205.         {
  2206.             if  (totSiz < memSize)
  2207.                  totSiz = memSize;
  2208.  
  2209.             offset = 0;
  2210.         }
  2211.     }
  2212.  
  2213.     /* Did we have any members at all? */
  2214.  
  2215.     if  (hadMem)
  2216.     {
  2217.         /* Unless it's a union, use the final member offset as size */
  2218.  
  2219.         if  (!isUnion)
  2220.             totSiz = offset;
  2221.     }
  2222.     else
  2223.     {
  2224.         // ISSUE: Do we need to do anything special for empty classes?
  2225.     }
  2226.  
  2227.     /* Better round up the total size for proper alignment */
  2228.  
  2229.     totSiz = roundUp(totSiz, align);
  2230.  
  2231.     /* Record the total size and max. alignment of the type */
  2232.  
  2233. //  printf("Class  [align=%3u] totalsize %04X: %s\n", align, totSiz, clsSym->sdSpelling());
  2234.  
  2235.     clsTyp->tdClass.tdcSize        = totSiz;
  2236.     clsTyp->tdClass.tdcAlignment   = cmpEncodeAlign(align);
  2237.  
  2238.     clsTyp->tdClass.tdcLayoutDone  = true;
  2239.     clsTyp->tdClass.tdcLayoutDoing = false;
  2240. }
  2241.  
  2242. /*****************************************************************************
  2243.  *
  2244.  *  Switch to the given variable's data area so that we can output its
  2245.  *  initial value. The caller promises to hang on to the return value,
  2246.  *  and pass it on to the various cmpWritexxxInit() functions so that
  2247.  *  the value ends up in the right place.
  2248.  *
  2249.  *  Special case: when 'undim' is true, the variable being initialized
  2250.  *  is an array of unknown size. In that case we'll simply prepare the
  2251.  *  data section for output but won't reserve any space in it, since
  2252.  *  the amount of space won't be known until the entire initializer is
  2253.  *  processed.
  2254.  */
  2255.  
  2256. memBuffPtr          compiler::cmpInitVarBeg(SymDef varSym, bool undim)
  2257. {
  2258.     /* Prevent re-entering this logic for more than one variable at once */
  2259.  
  2260. #ifdef  DEBUG
  2261.     assert(cmpInitVarCur == NULL); cmpInitVarCur = varSym;
  2262. #endif
  2263.  
  2264.     /* Has space for the variable been allocated? */
  2265.  
  2266.     if  (varSym->sdVar.sdvAllocated)
  2267.     {
  2268.         if  (undim)
  2269.         {
  2270.             UNIMPL("space already allocated for undim'd array - I don't think so!");
  2271.         }
  2272.  
  2273. #ifdef  DEBUG
  2274.         cmpInitVarOfs = varSym->sdVar.sdvOffset;
  2275. #endif
  2276.  
  2277.         /* Locate the data area of the variable and return it */
  2278.  
  2279.         return  cmpPEwriter->WPEsecAdrData(PE_SECT_data, varSym->sdVar.sdvOffset);
  2280.     }
  2281.     else
  2282.     {
  2283.         size_t          al;
  2284.         memBuffPtr      ignore;
  2285.  
  2286.         /* We don't expect vtables to ever appear here */
  2287.  
  2288.         assert(varSym->sdVar.sdvIsVtable == false);
  2289.  
  2290.         /* The space has not been allocated, get the required alignment */
  2291.  
  2292.         cmpGetTypeSize(varSym->sdType, &al);
  2293.  
  2294.         /* Prepare to append the variable's value to the data section */
  2295.  
  2296.         varSym->sdVar.sdvOffset = cmpPEwriter->WPEsecRsvData(PE_SECT_data,
  2297.                                                              0,
  2298.                                                              al,
  2299.                                                              ignore);
  2300.  
  2301.         /* Remember that we've allocated space for the variable */
  2302.  
  2303.         varSym->sdVar.sdvAllocated = true;
  2304.  
  2305. #ifdef  DEBUG
  2306.         cmpInitVarOfs = varSym->sdVar.sdvOffset;
  2307. #endif
  2308.  
  2309.         return  memBuffMkNull();
  2310.     }
  2311. }
  2312.  
  2313. /*****************************************************************************
  2314.  *
  2315.  *  This function is only used in debug mode, where it helps make sure that
  2316.  *  we don't try to append more than one variable's initial value to the
  2317.  *  data section at once.
  2318.  */
  2319.  
  2320. #ifdef  DEBUG
  2321.  
  2322. void                compiler::cmpInitVarEnd(SymDef varSym)
  2323. {
  2324.     size_t          sz;
  2325.  
  2326.     assert(cmpInitVarCur);
  2327.  
  2328.     if  (varSym->sdVar.sdvIsVtable)
  2329.     {
  2330.         assert(varSym->sdParent);
  2331.         assert(varSym->sdParent->sdSymKind == SYM_CLASS);
  2332.         assert(varSym->sdParent->sdIsManaged == false);
  2333.  
  2334.         sz = sizeof(void*) * varSym->sdParent->sdClass.sdcVirtCnt;
  2335.     }
  2336.     else
  2337.         sz = cmpGetTypeSize(varSym->sdType);
  2338.  
  2339.     assert(cmpInitVarOfs == varSym->sdVar.sdvOffset + sz || cmpErrorCount);
  2340.  
  2341.     cmpInitVarCur = NULL;
  2342. }
  2343.  
  2344. #endif
  2345.  
  2346. /*****************************************************************************
  2347.  *
  2348.  *  Append the given blob of bits to the data section of the variable being
  2349.  *  initialized.
  2350.  */
  2351.  
  2352. memBuffPtr          compiler::cmpWriteVarData(memBuffPtr dest, genericBuff str,
  2353.                                                                size_t      len)
  2354. {
  2355.     if  (!memBuffIsNull(dest))
  2356.     {
  2357.         memBuffCopy(dest, str, len);
  2358.     }
  2359.     else
  2360.     {
  2361.         unsigned        offs;
  2362.  
  2363.         offs = cmpPEwriter->WPEsecAddData(PE_SECT_data, str, len);
  2364.  
  2365.         /* Make sure we are where we think we ought to be */
  2366.  
  2367.         assert(offs == cmpInitVarOfs);
  2368.     }
  2369.  
  2370. #ifdef  DEBUG
  2371.     cmpInitVarOfs += len;
  2372. #endif
  2373.  
  2374.     return dest;
  2375. }
  2376.  
  2377. /*****************************************************************************
  2378.  *
  2379.  *  Write the given constant value to the next position in the current
  2380.  *  variable's data area. The 'dest' argument points at where the data
  2381.  *  is to be writtem, and an updated address is returned. If 'dest' is
  2382.  *  NULL, we're simply appending to the data section (in which case a
  2383.  *  NULL value is returned back).
  2384.  */
  2385.  
  2386. memBuffPtr          compiler::cmpWriteOneInit(memBuffPtr dest, Tree expr)
  2387. {
  2388.     BYTE        *   addr;
  2389.     size_t          size;
  2390.  
  2391.     __int32         ival;
  2392.     __int64         lval;
  2393.     float           fval;
  2394.     double          dval;
  2395.  
  2396.     switch (expr->tnOper)
  2397.     {
  2398.         unsigned        offs;
  2399.  
  2400.     case TN_CNS_INT: ival = expr->tnIntCon.tnIconVal; addr = (BYTE*)&ival; break;
  2401.     case TN_CNS_LNG: lval = expr->tnLngCon.tnLconVal; addr = (BYTE*)&lval; break;
  2402.     case TN_CNS_FLT: fval = expr->tnFltCon.tnFconVal; addr = (BYTE*)&fval; break;
  2403.     case TN_CNS_DBL: dval = expr->tnDblCon.tnDconVal; addr = (BYTE*)&dval; break;
  2404.     case TN_NULL:    ival =                        0; addr = (BYTE*)&ival; break;
  2405.  
  2406.     case TN_CNS_STR:
  2407.  
  2408.         /* Add the string to the string pool */
  2409.  
  2410.         ival = cmpILgen->genStrPoolAdd(expr->tnStrCon.tnSconVal,
  2411.                                        expr->tnStrCon.tnSconLen+1,
  2412.                                        expr->tnStrCon.tnSconLCH);
  2413.  
  2414.         /* We will output the relative offset of the string */
  2415.  
  2416.         addr = (BYTE*)&ival;
  2417.  
  2418.         /* We also need to add a fixup for the string reference */
  2419.  
  2420.         offs = memBuffIsNull(dest) ? cmpPEwriter->WPEsecNextOffs(PE_SECT_data)
  2421.                                    : cmpPEwriter->WPEsecAddrOffs(PE_SECT_data, dest);
  2422.  
  2423.         cmpPEwriter->WPEsecAddFixup(PE_SECT_data, PE_SECT_string, offs);
  2424.         break;
  2425.  
  2426.     default:
  2427.         NO_WAY(!"unexpected initializer type");
  2428.     }
  2429.  
  2430.     /* Get hold of the size of the value */
  2431.  
  2432.     size = cmpGetTypeSize(expr->tnType);
  2433.  
  2434.     /* Now output the initializer value */
  2435.  
  2436.     return  cmpWriteVarData(dest, makeGenBuff(addr, size), size);
  2437. }
  2438.  
  2439. /*****************************************************************************
  2440.  *
  2441.  *  Parse one initializer expression (which we expect to be of an arithmetic
  2442.  *  type or a pointer/ref), return the bound constant result or NULL if there
  2443.  *  is an error.
  2444.  */
  2445.  
  2446. Tree                compiler::cmpParseOneInit(TypDef type)
  2447. {
  2448.     Tree            expr;
  2449.  
  2450.     /* Parse the expression, coerce it, bind it, fold it, mutilate it, ... */
  2451.  
  2452.     expr = cmpParser->parseExprComma();
  2453.     expr = cmpCreateExprNode(NULL, TN_CAST, type, expr, NULL);
  2454.     expr = cmpBindExpr(expr);
  2455.     expr = cmpFoldExpression(expr);
  2456.  
  2457.     /* Now see what we've ended up with */
  2458.  
  2459.     if  (expr->tnOperKind() & TNK_CONST)
  2460.         return  expr;
  2461.  
  2462.     if  (expr->tnOper == TN_ERROR)
  2463.         return  NULL;
  2464.  
  2465.     return  cmpCreateErrNode(ERRinitNotCns);
  2466. }
  2467.  
  2468. /*****************************************************************************
  2469.  *
  2470.  *  Add the given amount of padding to the variable being initialized.
  2471.  */
  2472.  
  2473. memBuffPtr          compiler::cmpInitVarPad(memBuffPtr dest, size_t amount)
  2474. {
  2475.     memBuffPtr      ignore;
  2476.  
  2477.     if  (!memBuffIsNull(dest))
  2478.         memBuffMove(dest, amount);
  2479.     else
  2480.         cmpPEwriter->WPEsecRsvData(PE_SECT_data, amount, 1, ignore);
  2481.  
  2482. #ifdef  DEBUG
  2483.     cmpInitVarOfs += amount;
  2484. #endif
  2485.  
  2486.     return  dest;
  2487. }
  2488.  
  2489. /*****************************************************************************
  2490.  *
  2491.  *  Initialize a scalar value; returns true if an error was encountered.
  2492.  */
  2493.  
  2494. bool                compiler::cmpInitVarScl(INOUT memBuffPtr REF dest,
  2495.                                                   TypDef         type,
  2496.                                                   SymDef         varSym)
  2497. {
  2498.     Tree            init;
  2499.  
  2500.     /* If this is the top level, prepare to initialize the variable */
  2501.  
  2502.     if  (varSym)
  2503.     {
  2504.         assert(memBuffIsNull(dest)); dest = cmpInitVarBeg(varSym);
  2505.     }
  2506.  
  2507.     /* Make sure the initializer does not start with "{" */
  2508.  
  2509.     if  (cmpScanner->scanTok.tok == tkLCurly)
  2510.     {
  2511.         cmpError(ERRbadBrInit, type);
  2512.         return  true;
  2513.     }
  2514.  
  2515.     /* Parse the initializer and make sure it's a constant */
  2516.  
  2517.     init = cmpParseOneInit(type);
  2518.     if  (!init || init->tnOper == TN_ERROR)
  2519.         return  true;
  2520.  
  2521.     assert(symTab::stMatchTypes(type, init->tnType));
  2522.  
  2523.     /* Output the constant */
  2524.  
  2525.     dest = cmpWriteOneInit(dest, init);
  2526.  
  2527.     /* Everything went just dandy */
  2528.  
  2529.     return  false;
  2530. }
  2531.  
  2532. /*****************************************************************************
  2533.  *
  2534.  *  Initialize an array value; returns true if an error was encountered.
  2535.  */
  2536.  
  2537. bool                compiler::cmpInitVarArr(INOUT memBuffPtr REF dest,
  2538.                                                   TypDef         type,
  2539.                                                   SymDef         varSym)
  2540. {
  2541.     Scanner         ourScanner = cmpScanner;
  2542.  
  2543.     bool            undim;
  2544.  
  2545.     unsigned        fsize;
  2546.     unsigned        elems;
  2547.  
  2548.     TypDef          base;
  2549.     bool            curl;
  2550.  
  2551.     /* We expect to have an unmanaged array here */
  2552.  
  2553.     assert(type && type->tdTypeKind == TYP_ARRAY && !type->tdIsManaged);
  2554.     assert(varSym == NULL || symTab::stMatchTypes(varSym->sdType, type));
  2555.  
  2556.     /* Does the array have a fixed dimension? */
  2557.  
  2558.     if  (type->tdIsUndimmed)
  2559.     {
  2560.         fsize = 0;
  2561.         undim = true;
  2562.     }
  2563.     else
  2564.     {
  2565.         assert(type->tdArr.tdaDims);
  2566.         assert(type->tdArr.tdaDims->ddNext == NULL);
  2567.         assert(type->tdArr.tdaDims->ddIsConst);
  2568.  
  2569.         fsize = type->tdArr.tdaDims->ddSize;
  2570.         undim = false;
  2571.     }
  2572.  
  2573.     elems = 0;
  2574.  
  2575.     /* If this is the top level, prepare to initialize the variable */
  2576.  
  2577.     if  (varSym)
  2578.     {
  2579.         assert(memBuffIsNull(dest)); dest = cmpInitVarBeg(varSym, undim);
  2580.     }
  2581.  
  2582.     /* Get hold of the base type */
  2583.  
  2584.     base = cmpDirectType(type->tdArr.tdaElem);
  2585.  
  2586.     /* Make sure the initializer starts with "{" */
  2587.  
  2588.     if  (ourScanner->scanTok.tok != tkLCurly)
  2589.     {
  2590.         genericBuff     buff;
  2591.  
  2592.         /* Special case: "char []" initialized with string */
  2593.  
  2594.         if  (ourScanner->scanTok.tok != tkStrCon || base->tdTypeKind != TYP_CHAR &&
  2595.                                                     base->tdTypeKind != TYP_UCHAR)
  2596.         {
  2597. //          printf("Base type = '%s'\n", cmpGlobalST->stTypeName(base, NULL, NULL, NULL, true));
  2598.  
  2599.             cmpError(ERRbadInitSt, type);
  2600.             return  true;
  2601.         }
  2602.  
  2603.         /* Does the array have a fixed dimension? */
  2604.  
  2605.         elems = ourScanner->scanTok.strCon.tokStrLen + 1;
  2606.  
  2607.         if  (fsize)
  2608.         {
  2609.             /* Make sure the string isn't too long */
  2610.  
  2611.             if  (elems > fsize)
  2612.             {
  2613.                 if  (elems - 1 == fsize)
  2614.                 {
  2615.                     /* Simply chop off the terminating null */
  2616.  
  2617.                     elems--;
  2618.                 }
  2619.                 else
  2620.                 {
  2621.                     cmpGenError(ERRstrInitMany, fsize); elems = fsize;
  2622.                 }
  2623.             }
  2624.         }
  2625.  
  2626.         /* Output as many characters as makes sense */
  2627.  
  2628.         buff = makeGenBuff(ourScanner->scanTok.strCon.tokStrVal, elems);
  2629.         dest = cmpWriteVarData(dest, buff, elems);
  2630.  
  2631.         if  (ourScanner->scan() == tkStrCon)
  2632.         {
  2633.             UNIMPL(!"adjacent string literals NYI in initializers");
  2634.         }
  2635.  
  2636.         curl = false;
  2637.         goto DONE;
  2638.     }
  2639.  
  2640.     ourScanner->scan();
  2641.  
  2642.     /* Process all the element initializers that are present */
  2643.  
  2644.     for (;;)
  2645.     {
  2646.         /* Special case: byte array initialized with a string */
  2647.  
  2648.         if  (ourScanner->scanTok.tok == tkStrCon && (base->tdTypeKind == TYP_CHAR ||
  2649.                                                      base->tdTypeKind == TYP_UCHAR))
  2650.         {
  2651.             genericBuff     buff;
  2652.             unsigned        chars;
  2653.  
  2654.             do
  2655.             {
  2656.                 /* Does the array have a fixed dimension? */
  2657.  
  2658.                 chars = ourScanner->scanTok.strCon.tokStrLen + 1;
  2659.  
  2660.                 if  (fsize)
  2661.                 {
  2662.                     /* Make sure the string isn't too long */
  2663.  
  2664.                     if  (elems + chars > fsize)
  2665.                     {
  2666.                         if  (elems + chars - 1 == fsize)
  2667.                         {
  2668.                             /* Simply chop off the terminating null */
  2669.  
  2670.                             chars--;
  2671.                         }
  2672.                         else
  2673.                         {
  2674.                             cmpGenError(ERRstrInitMany, fsize); chars = fsize - elems;
  2675.                         }
  2676.                     }
  2677.                 }
  2678.  
  2679.                 /* Output as many characters as makes sense */
  2680.  
  2681.                 buff = makeGenBuff(ourScanner->scanTok.strCon.tokStrVal, chars);
  2682.                 dest   = cmpWriteVarData(dest, buff, chars);
  2683.                 elems += chars;
  2684.             }
  2685.             while (ourScanner->scan() == tkStrCon);
  2686.         }
  2687.         else
  2688.         {
  2689.             /* Make sure we don't have too many elements */
  2690.  
  2691.             if  (++elems > fsize && fsize)
  2692.             {
  2693.                 cmpGenError(ERRarrInitMany, fsize);
  2694.                 fsize = 0;
  2695.             }
  2696.  
  2697.             /* Process this particular element's initializer */
  2698.  
  2699.             if  (cmpInitVarAny(dest, base, NULL))
  2700.                 return  true;
  2701.         }
  2702.  
  2703.         /* Check for more initializers; we allow ", }" for convenience */
  2704.  
  2705.         if  (ourScanner->scanTok.tok != tkComma)
  2706.             break;
  2707.  
  2708.         if  (ourScanner->scan() == tkRCurly)
  2709.             break;
  2710.     }
  2711.  
  2712.     curl = true;
  2713.  
  2714.     if  (ourScanner->scanTok.tok != tkRCurly)
  2715.     {
  2716.         cmpError(ERRnoRcurly);
  2717.         return  true;
  2718.     }
  2719.  
  2720. DONE:
  2721.  
  2722.     /* Does the array have fixed dimension? */
  2723.  
  2724.     if  (fsize)
  2725.     {
  2726.         /* We might have to pad the array */
  2727.  
  2728.         if  (elems < fsize)
  2729.             dest = cmpInitVarPad(dest, (fsize - elems) * cmpGetTypeSize(base));
  2730.     }
  2731.     else
  2732.     {
  2733.         /* Store the dimension in the array type */
  2734.  
  2735.         if  (varSym)
  2736.         {
  2737.             DimDef          dims;
  2738.  
  2739. #if MGDDATA
  2740.             dims = new DimDef;
  2741. #else
  2742.             dims =    (DimDef)cmpAllocTemp.baAlloc(sizeof(*dims));
  2743. #endif
  2744.  
  2745.             dims->ddNext     = NULL;
  2746.             dims->ddNoDim    = false;
  2747.             dims->ddIsConst  = true;
  2748. #ifndef NDEBUG
  2749.             dims->ddDimBound = true;
  2750. #endif
  2751.             dims->ddSize     = elems;
  2752.  
  2753.             varSym->sdType   = cmpGlobalST->stNewArrType(dims,
  2754.                                                          false,
  2755.                                                          type->tdArr.tdaElem);
  2756.         }
  2757.         else
  2758.         {
  2759.             UNIMPL("can we just bash the array type elem count?");
  2760.         }
  2761.     }
  2762.  
  2763.     /* Swallow the closing "}" and we're done */
  2764.  
  2765.     if  (curl)
  2766.         ourScanner->scan();
  2767.  
  2768.     return  false;
  2769. }
  2770.  
  2771. /*****************************************************************************
  2772.  *
  2773.  *  Initialize an array value; returns true if an error was encountered.
  2774.  */
  2775.  
  2776. bool                compiler::cmpInitVarCls(INOUT memBuffPtr REF dest,
  2777.                                                   TypDef         type,
  2778.                                                   SymDef         varSym)
  2779. {
  2780.     Scanner         ourScanner = cmpScanner;
  2781.  
  2782.     unsigned        curOffs;
  2783.  
  2784.     __int64         curBFval;
  2785.     unsigned        curBFsiz;
  2786.  
  2787.     SymDef          memSym;
  2788.  
  2789.     size_t          size;
  2790.  
  2791.     /* We expect to have an unmanaged class here */
  2792.  
  2793.     assert(type && type->tdTypeKind == TYP_CLASS && !type->tdIsManaged);
  2794.     assert(varSym == NULL || symTab::stMatchTypes(varSym->sdType, type));
  2795.  
  2796.     /* If this is the top level, prepare to initialize the variable */
  2797.  
  2798.     if  (varSym)
  2799.     {
  2800.         assert(memBuffIsNull(dest)); dest = cmpInitVarBeg(varSym);
  2801.     }
  2802.  
  2803.     /* Disallow initialization if there is a base class or a ctor */
  2804.  
  2805.     if  (type->tdClass.tdcHasCtor || type->tdClass.tdcBase)
  2806.     {
  2807.         cmpError(ERRbadBrInit, type);
  2808.         return  true;
  2809.     }
  2810.  
  2811.     /* Make sure the initializer starts with "{" */
  2812.  
  2813.     if  (ourScanner->scanTok.tok != tkLCurly)
  2814.     {
  2815.         cmpError(ERRbadInitSt, type);
  2816.         return  true;
  2817.     }
  2818.  
  2819.     ourScanner->scan();
  2820.  
  2821.     /* Process all the member initializers that are present */
  2822.  
  2823.     curOffs  = 0;
  2824.     curBFsiz = 0;
  2825.     curBFval = 0;
  2826.  
  2827.     for (memSym = type->tdClass.tdcSymbol->sdScope.sdScope.sdsChildList;
  2828.          memSym;
  2829.          memSym = memSym->sdNextInScope)
  2830.     {
  2831.         TypDef          memTyp;
  2832.         size_t          memSiz;
  2833.  
  2834.         /* We only care about non-static instance variables */
  2835.  
  2836.         if  (memSym->sdSymKind != SYM_VAR)
  2837.             continue;
  2838.         if  (memSym->sdIsStatic)
  2839.             continue;
  2840.  
  2841.         /* Get hold of the member's type and size */
  2842.  
  2843.         memTyp = memSym->sdType;
  2844.         memSiz = cmpGetTypeSize(memTyp);
  2845.  
  2846.         /* Do we need to insert any padding? */
  2847.  
  2848.         if  (memSym->sdVar.sdvOffset != curOffs)
  2849.         {
  2850.             /* Is there a pending bitfield we need to flush? */
  2851.  
  2852.             if  (curBFsiz)
  2853.             {
  2854.                 genericBuff     buff;
  2855.  
  2856.                 /* Write out the bitfield cell we've collected */
  2857.  
  2858.                 buff     = makeGenBuff(&curBFval, curBFsiz);
  2859.                 dest     = cmpWriteVarData(dest, buff, curBFsiz);
  2860.  
  2861.                 /* Update the offset past the bitfield cell */
  2862.  
  2863.                 curOffs += curBFsiz;
  2864.  
  2865.                 /* We don't have an active bitfield cell any more */
  2866.  
  2867.                 curBFsiz = 0;
  2868.                 curBFval = 0;
  2869.             }
  2870.  
  2871.             if  (memSym->sdVar.sdvOffset != curOffs)
  2872.                 dest = cmpInitVarPad(dest, memSym->sdVar.sdvOffset - curOffs);
  2873.         }
  2874.  
  2875.         /* Is this a bitfield member? */
  2876.  
  2877.         if  (memSym->sdVar.sdvBitfield)
  2878.         {
  2879.             Tree            init;
  2880.             __int64         bval;
  2881.  
  2882.             /* Parse the initializer and make sure it's a constant */
  2883.  
  2884.             init = cmpParseOneInit(memTyp);
  2885.             if  (!init)
  2886.                 return  true;
  2887.  
  2888.             assert(symTab::stMatchTypes(memTyp, init->tnType));
  2889.  
  2890.             /* Get hold of the constant value */
  2891.  
  2892.             assert(init->tnOper == TN_CNS_INT ||
  2893.                    init->tnOper == TN_CNS_LNG);
  2894.  
  2895.             bval = (init->tnOper == TN_CNS_INT) ? init->tnIntCon.tnIconVal
  2896.                                                 : init->tnLngCon.tnLconVal;
  2897.  
  2898.             /* Are we in the middle of a bitfield cell already? */
  2899.  
  2900.             if  (!curBFsiz)
  2901.                 curBFsiz = memSiz;
  2902.  
  2903.             assert(curBFsiz == memSiz);
  2904.  
  2905.             /* Insert the bitfield in the current cell */
  2906.  
  2907.             bval  &= ((1 << memSym->sdVar.sdvBfldInfo.bfWidth) - 1);
  2908.             bval <<=        memSym->sdVar.sdvBfldInfo.bfOffset;
  2909.  
  2910.             /* Make sure we don't have any overlap */
  2911.  
  2912.             assert((curBFval & bval) == 0); curBFval |= bval;
  2913.         }
  2914.         else
  2915.         {
  2916.             /* Initialize this member */
  2917.  
  2918.             if  (cmpInitVarAny(dest, memTyp, NULL))
  2919.                 return  true;
  2920.  
  2921.             /* Update the current offset */
  2922.  
  2923.             curOffs = memSym->sdVar.sdvOffset + memSiz;
  2924.         }
  2925.  
  2926.         /* Check for more initializers; we allow ", }" for convenience */
  2927.  
  2928.         if  (ourScanner->scanTok.tok != tkComma)
  2929.             break;
  2930.  
  2931.         if  (ourScanner->scan() == tkRCurly)
  2932.             break;
  2933.  
  2934.         /* Only the first member of a union may be initialized */
  2935.  
  2936.         if  (type->tdClass.tdcFlavor == STF_UNION)
  2937.             break;
  2938.     }
  2939.  
  2940.     if  (ourScanner->scanTok.tok != tkRCurly)
  2941.     {
  2942.         cmpError(ERRnoRcurly);
  2943.         return  true;
  2944.     }
  2945.  
  2946.     /* Is there a pending bitfield we need to flush? */
  2947.  
  2948.     if  (curBFsiz)
  2949.     {
  2950.         dest = cmpWriteVarData(dest, makeGenBuff(&curBFval, curBFsiz), curBFsiz);
  2951.  
  2952.         curOffs += curBFsiz;
  2953.     }
  2954.  
  2955.     /* We might have to pad the class value */
  2956.  
  2957.     size = cmpGetTypeSize(type);
  2958.  
  2959.     if  (size > curOffs)
  2960.         dest = cmpInitVarPad(dest, size - curOffs);
  2961.  
  2962.     /* Swallow the closing "}" and we're done */
  2963.  
  2964.     ourScanner->scan();
  2965.  
  2966.     return  false;
  2967. }
  2968.  
  2969. /*****************************************************************************
  2970.  *
  2971.  *  Process an initializer of the give type (if 'varSym' is no-NULL we have
  2972.  *  the top-level initializer for the given variable).
  2973.  *
  2974.  *  Returns true if an error has been encountered.
  2975.  */
  2976.  
  2977. bool                compiler::cmpInitVarAny(INOUT memBuffPtr REF dest, TypDef type,
  2978.                                                                        SymDef varSym)
  2979. {
  2980.     assert(varSym == NULL || symTab::stMatchTypes(varSym->sdType, type));
  2981.  
  2982.     for (;;)
  2983.     {
  2984.         switch (type->tdTypeKind)
  2985.         {
  2986.         default:
  2987.             return  cmpInitVarScl(dest, type, varSym);
  2988.  
  2989.         case TYP_ARRAY:
  2990.  
  2991.             if  (type->tdIsManaged)
  2992.                 return  cmpInitVarScl(dest, type, varSym);
  2993.             else
  2994.                 return  cmpInitVarArr(dest, type, varSym);
  2995.  
  2996.         case TYP_CLASS:
  2997.  
  2998.             if  (type->tdIsManaged)
  2999.                 return  cmpInitVarScl(dest, type, varSym);
  3000.             else
  3001.                 return  cmpInitVarCls(dest, type, varSym);
  3002.  
  3003.         case TYP_TYPEDEF:
  3004.             type = cmpActualType(type);
  3005.             continue;
  3006.         }
  3007.     }
  3008. }
  3009.  
  3010. /*****************************************************************************
  3011.  *
  3012.  *  Recursively output a vtable contents.
  3013.  */
  3014.  
  3015. memBuffPtr          compiler::cmpGenVtableSection(SymDef     innerSym,
  3016.                                                   SymDef     outerSym,
  3017.                                                   memBuffPtr dest)
  3018. {
  3019.     SymDef          memSym;
  3020.  
  3021.     SymTab          ourStab = cmpGlobalST;
  3022.     TypDef          baseCls = innerSym->sdType->tdClass.tdcBase;
  3023.  
  3024.     if  (baseCls)
  3025.     {
  3026.         assert(baseCls->tdTypeKind == TYP_CLASS);
  3027.  
  3028.         dest = cmpGenVtableSection(baseCls->tdClass.tdcSymbol, outerSym, dest);
  3029.     }
  3030.  
  3031.     /* Look for any virtuals introduced at this level of the hierarchy */
  3032.  
  3033.     for (memSym = innerSym->sdScope.sdScope.sdsChildList;
  3034.          memSym;
  3035.          memSym = memSym->sdNextInScope)
  3036.     {
  3037.         SymDef          fncSym;
  3038.  
  3039.         if  (memSym->sdSymKind != SYM_FNC)
  3040.             continue;
  3041.  
  3042.         fncSym = memSym;
  3043.  
  3044.         do
  3045.         {
  3046.             /* Is the next method a virtual introduced in this class? */
  3047.  
  3048.             if  (fncSym->sdFnc.sdfVirtual && !fncSym->sdFnc.sdfOverride)
  3049.             {
  3050.                 SymDef          ovrSym = fncSym;
  3051.                 mdToken         mtok;
  3052.  
  3053.                 /* Find the most-derived override of this method */
  3054.  
  3055.                 if  (innerSym != outerSym)
  3056.                 {
  3057.                     SymDef          clsSym;
  3058.                     TypDef          fncType = fncSym->sdType;
  3059.                     Ident           fncName = fncSym->sdName;
  3060.  
  3061.                     clsSym = outerSym;
  3062.                     do
  3063.                     {
  3064.                         SymDef          tmpSym;
  3065.  
  3066.                         /* Look for a matching virtual in this class */
  3067.  
  3068.                         tmpSym = ourStab->stLookupScpSym(fncName, clsSym);
  3069.                         if  (tmpSym)
  3070.                         {
  3071.                             tmpSym = ourStab->stFindOvlFnc(tmpSym, fncType);
  3072.                             if  (tmpSym)
  3073.                             {
  3074.                                 ovrSym = tmpSym;
  3075.                                 goto FND_OVR;
  3076.                             }
  3077.                         }
  3078.  
  3079.                         /* Continue with the base class */
  3080.  
  3081.                         assert(clsSym->sdType->tdClass.tdcBase);
  3082.  
  3083.                         clsSym = clsSym->sdType->tdClass.tdcBase->tdClass.tdcSymbol;
  3084.                     }
  3085.                     while (clsSym != innerSym);
  3086.                 }
  3087.  
  3088.             FND_OVR:
  3089.  
  3090. #ifdef DEBUG
  3091.                 if  (cmpConfig.ccVerbose >= 2) printf("    [%02u] %s\n", ovrSym->sdFnc.sdfVtblx, cmpGlobalST->stTypeName(ovrSym->sdType, ovrSym, NULL, NULL, true));
  3092. #endif
  3093.  
  3094.                 /* Make sure the method has the expected position */
  3095.  
  3096. #ifdef  DEBUG
  3097.                 assert(ovrSym->sdFnc.sdfVtblx == ++cmpVtableIndex);
  3098. #endif
  3099.  
  3100.                 /* Get hold of the metadata token for the method */
  3101.  
  3102.                 mtok = cmpILgen->genMethodRef(ovrSym, false);
  3103.  
  3104.                 /* Output the value of the token */
  3105.  
  3106.                 dest = cmpWriteVarData(dest, (BYTE*)&mtok, sizeof(mtok));
  3107.             }
  3108.  
  3109.             /* Continue with the next overload, if any */
  3110.  
  3111.             fncSym = fncSym->sdFnc.sdfNextOvl;
  3112.         }
  3113.         while (fncSym);
  3114.     }
  3115.  
  3116.     return  dest;
  3117. }
  3118.  
  3119. /*****************************************************************************
  3120.  *
  3121.  *  Initialize the contents of the given vtable.
  3122.  */
  3123.  
  3124. void                compiler::cmpGenVtableContents(SymDef vtabSym)
  3125. {
  3126.     memBuffPtr      init;
  3127.  
  3128.     SymDef          clsSym = vtabSym->sdParent;
  3129.  
  3130.     assert(vtabSym);
  3131.     assert(vtabSym->sdSymKind == SYM_VAR);
  3132.     assert(vtabSym->sdVar.sdvIsVtable);
  3133.  
  3134.     assert( clsSym);
  3135.     assert( clsSym->sdSymKind == SYM_CLASS);
  3136.     assert( clsSym->sdClass.sdcVtableSym == vtabSym);
  3137.     assert(!clsSym->sdIsManaged);
  3138.     assert(!clsSym->sdType->tdClass.tdcIntf);
  3139.  
  3140. #ifdef DEBUG
  3141.     if  (cmpConfig.ccVerbose >= 2) printf("Generating vtable for class '%s':\n", cmpGlobalST->stTypeName(NULL, clsSym, NULL, NULL, false));
  3142. #endif
  3143.  
  3144. #ifdef  DEBUG
  3145.     cmpVtableIndex = 0;
  3146. #endif
  3147.  
  3148.     init = cmpInitVarBeg(vtabSym, false);
  3149.  
  3150.     /* Recursively add all the virtual method entries to the table */
  3151.  
  3152.     init = cmpGenVtableSection(clsSym, clsSym, init);
  3153.  
  3154. #ifdef  DEBUG
  3155.     assert(cmpVtableIndex == clsSym->sdClass.sdcVirtCnt);
  3156. #endif
  3157.  
  3158.     cmpInitVarEnd(vtabSym);
  3159. }
  3160.  
  3161. /*****************************************************************************
  3162.  *
  3163.  *  A class with a "pre-defined" name has just been declared, note whether
  3164.  *  it's one of the "well-known" class types, and record it if so.
  3165.  */
  3166.  
  3167. void                compiler::cmpMarkStdType(SymDef clsSym)
  3168. {
  3169.     Ident           clsName = clsSym->sdName;
  3170.  
  3171.     assert(clsSym->sdParent == cmpNmSpcSystem);
  3172.     assert(hashTab::getIdentFlags(clsName) & IDF_PREDEF);
  3173.  
  3174.     if  (clsName == cmpIdentType)
  3175.         cmpClassType    = clsSym;
  3176.  
  3177.     if  (clsName == cmpIdentObject)
  3178.         cmpClassObject  = clsSym;
  3179.  
  3180.     if  (clsName == cmpIdentString)
  3181.         cmpClassString  = clsSym;
  3182.  
  3183.     if  (clsName == cmpIdentArray)
  3184.         cmpClassArray   = clsSym;
  3185.  
  3186.     if  (clsName == cmpIdentExcept)
  3187.         cmpClassExcept  = clsSym;
  3188.  
  3189.     if  (clsName == cmpIdentRTexcp)
  3190.         cmpClassRTexcp  = clsSym;
  3191.  
  3192.     if  (clsName == cmpIdentArgIter)
  3193.         cmpClassArgIter = clsSym;
  3194.  
  3195.     if  (clsName == cmpIdentEnum)
  3196.         cmpClassEnum    = clsSym;
  3197.  
  3198.     if  (clsName == cmpIdentValType)
  3199.         cmpClassValType = clsSym;
  3200.  
  3201.     if  (clsName == cmpIdentDeleg ||
  3202.          clsName == cmpIdentMulti)
  3203.     {
  3204.         TypDef          clsTyp = clsSym->sdType;
  3205.  
  3206.         clsTyp->tdClass.tdcFnPtrWrap = true;
  3207.         clsTyp->tdClass.tdcFlavor    =
  3208.         clsSym->sdClass.sdcFlavor    = STF_DELEGATE;
  3209.         clsSym->sdClass.sdcBuiltin   = true;
  3210.  
  3211.         if  (clsName == cmpIdentDeleg)
  3212.             cmpClassDeleg  = clsSym;
  3213.         else
  3214.             cmpClassMulti = clsSym;
  3215.     }
  3216.  
  3217.     /* Is this one of the "intrinsic" value types? */
  3218.  
  3219.     if  (hashTab::getIdentFlags(clsName) & IDF_STDVTP)
  3220.     {
  3221.         TypDef          clsTyp = clsSym->sdType;
  3222.  
  3223.         clsTyp->tdIsIntrinsic       = true;
  3224.         clsTyp->tdClass.tdcIntrType = TYP_UNDEF;
  3225.  
  3226.         cmpFindStdValType(clsTyp);
  3227.     }
  3228. }
  3229.  
  3230. /*****************************************************************************
  3231.  *
  3232.  *  Try to display the location of any existing definition of the given symbol.
  3233.  */
  3234.  
  3235. void                compiler::cmpReportSymDef(SymDef sym)
  3236. {
  3237.     const   char *  file = NULL;
  3238.     unsigned        line;
  3239.  
  3240.     if  (sym->sdSrcDefList)
  3241.     {
  3242.         DefList         defs;
  3243.  
  3244.         for (defs = sym->sdSrcDefList; defs; defs = defs->dlNext)
  3245.         {
  3246.             if  (defs->dlHasDef)
  3247.             {
  3248.                 file = defs->dlComp->sdComp.sdcSrcFile;
  3249.                 line = defs->dlDef.dsdSrcLno;
  3250.                 break;
  3251.             }
  3252.         }
  3253.     }
  3254.     else
  3255.     {
  3256.         // UNDONE: Need to look for a member definition in its class
  3257.     }
  3258.  
  3259.     if  (file)
  3260.         cmpGenError(ERRerrPos, file, line);
  3261. }
  3262.  
  3263. /*****************************************************************************
  3264.  *
  3265.  *  Report a redefinition error of the given symbol.
  3266.  */
  3267.  
  3268. void                compiler::cmpRedefSymErr(SymDef oldSym, unsigned err)
  3269. {
  3270.     if  (err)
  3271.         cmpErrorQnm(err, oldSym);
  3272.  
  3273.     cmpReportSymDef(oldSym);
  3274. }
  3275.  
  3276. /*****************************************************************************
  3277.  *
  3278.  *  Make a permanent copy of the given string value.
  3279.  */
  3280.  
  3281. ConstStr            compiler::cmpSaveStringCns(const char *str, size_t len)
  3282. {
  3283.     ConstStr        cnss;
  3284.     char    *       buff;
  3285.  
  3286. #if MGDDATA
  3287.  
  3288.     UNIMPL(!"save string");
  3289.  
  3290. #else
  3291.  
  3292.     cnss = (ConstStr)cmpAllocPerm.nraAlloc(sizeof(*cnss));
  3293.     buff = (char   *)cmpAllocPerm.nraAlloc(roundUp(len+1));
  3294.  
  3295.     memcpy(buff, str, len+1);
  3296.  
  3297. #endif
  3298.  
  3299.     cnss->csLen = len;
  3300.     cnss->csStr = buff;
  3301.  
  3302.     return  cnss;
  3303. }
  3304.  
  3305. ConstStr            compiler::cmpSaveStringCns(const wchar *str, size_t len)
  3306. {
  3307.     ConstStr        cnss;
  3308.     char    *       buff;
  3309.  
  3310. #if MGDDATA
  3311.  
  3312.     UNIMPL(!"save string");
  3313.  
  3314. #else
  3315.  
  3316.     cnss = (ConstStr)cmpAllocPerm.nraAlloc(sizeof(*cnss));
  3317.     buff = (char   *)cmpAllocPerm.nraAlloc(roundUp(len+1));
  3318.  
  3319.     wcstombs(buff, str, len+1);
  3320.  
  3321. #endif
  3322.  
  3323.     cnss->csLen = len;
  3324.     cnss->csStr = buff;
  3325.  
  3326.     return  cnss;
  3327. }
  3328.  
  3329. /*****************************************************************************
  3330.  *
  3331.  *  Process a constant declaration: the caller supplies the variable symbol,
  3332.  *  and optionally the initialization expression (if 'init' is NULL, the
  3333.  *  initializer will be read from the input).
  3334.  */
  3335.  
  3336. bool                compiler::cmpParseConstDecl(SymDef  varSym,
  3337.                                                 Tree    init,
  3338.                                                 Tree  * nonCnsPtr)
  3339. {
  3340.     bool            OK;
  3341.     constVal        cval;
  3342.     ConstVal        cptr;
  3343.  
  3344.     assert(varSym && varSym->sdSymKind == SYM_VAR);
  3345.  
  3346.     assert(varSym->sdCompileState == CS_DECLARED);
  3347.  
  3348.     /* Remember that we've found an initializer */
  3349.  
  3350.     varSym->sdVar.sdvHadInit = true;
  3351.  
  3352.     /* With managed data we don't have to worry about memory leaks */
  3353.  
  3354. #if MGDDATA
  3355.     cptr = new constVal;
  3356. #endif
  3357.  
  3358.     /* Evaluate the constant value (making sure to detect recursion) */
  3359.  
  3360.     varSym->sdVar.sdvInEval = true;
  3361.     OK = cmpParser->parseConstExpr(cval, init, varSym->sdType, nonCnsPtr);
  3362.     varSym->sdVar.sdvInEval = false;
  3363.  
  3364.     if  (OK)
  3365.     {
  3366.  
  3367. #if!MGDDATA
  3368.  
  3369.         /* Create a permanent home for the constant value */
  3370.  
  3371.         cptr = (constVal*)cmpAllocPerm.nraAlloc(sizeof(cval)); *cptr = cval;
  3372.  
  3373.         /* If the constant is a string, find a permanent home for it */
  3374.  
  3375.         if  (cval.cvIsStr)
  3376.         {
  3377.             ConstStr        cnss = cval.cvValue.cvSval;
  3378.  
  3379.             cptr->cvValue.cvSval = cmpSaveStringCns(cnss->csStr, cnss->csLen);
  3380.         }
  3381.  
  3382. #endif
  3383.  
  3384.         varSym->sdCompileState  = CS_CNSEVALD;
  3385.  
  3386.         /* Remember the fact that this is a constant variable */
  3387.  
  3388.         varSym->sdVar.sdvConst  = true;
  3389.         varSym->sdVar.sdvCnsVal = cptr;
  3390.     }
  3391.  
  3392.     return  OK;
  3393. }
  3394.  
  3395. /*****************************************************************************
  3396.  *
  3397.  *  See if the specified function is the program's entry point (the caller
  3398.  *  has already checked its name).
  3399.  */
  3400.  
  3401. void                compiler::cmpChk4entryPt(SymDef sym)
  3402. {
  3403.     SymDef          scope = sym->sdParent;
  3404.     TypDef          type  = sym->sdType;
  3405.  
  3406. #ifdef  OLD_IL
  3407.     if  (cmpConfig.ccOILgen && scope != cmpGlobalNS) return;
  3408. #endif
  3409.  
  3410.     /* Don't bother looking for an entry point in DLL's */
  3411.  
  3412.     if  (cmpConfig.ccOutDLL)
  3413.         return;
  3414.  
  3415.     assert(scope == cmpGlobalNS);
  3416.  
  3417.     /* Make sure the signature is correct for main() */
  3418.  
  3419.     if  (type->tdFnc.tdfRett->tdTypeKind != TYP_INT &&
  3420.          type->tdFnc.tdfRett->tdTypeKind != TYP_VOID)
  3421.         goto BAD_MAIN;
  3422.  
  3423.     if  (type->tdFnc.tdfArgs.adVarArgs)
  3424.         goto BAD_MAIN;
  3425.     if  (type->tdFnc.tdfArgs.adCount != 1)
  3426.         goto BAD_MAIN;
  3427.  
  3428.     assert(type->tdFnc.tdfArgs.adArgs);
  3429.     assert(type->tdFnc.tdfArgs.adArgs->adNext == NULL);
  3430.  
  3431.     type = type->tdFnc.tdfArgs.adArgs->adType;
  3432.  
  3433.     cmpFindStringType();
  3434.  
  3435.     if  (type->tdTypeKind != TYP_ARRAY)
  3436.         goto BAD_MAIN;
  3437.     if  (type->tdArr.tdaElem != cmpRefTpString)
  3438.         goto BAD_MAIN;
  3439.     if  (type->tdIsUndimmed == false)
  3440.         goto BAD_MAIN;
  3441.     if  (type->tdArr.tdaDcnt != 1)
  3442.         goto BAD_MAIN;
  3443.  
  3444.     /* The function must not be static */
  3445.  
  3446.     if  (sym->sdIsStatic)
  3447.         goto BAD_MAIN;
  3448.  
  3449.     /* This function will be the main entry point */
  3450.  
  3451.     cmpEntryPointCls      = sym->sdParent;
  3452.     sym->sdFnc.sdfEntryPt = true;
  3453.     return;
  3454.  
  3455. BAD_MAIN:
  3456.  
  3457.     /* In file scope this is not allowed */
  3458.  
  3459.     if  (scope == cmpGlobalNS)
  3460.         cmpError(ERRbadMain);
  3461. }
  3462.  
  3463. /*****************************************************************************
  3464.  *
  3465.  *  Bring the given file scope symbol to "declared" state.
  3466.  */
  3467.  
  3468. void                compiler::cmpDeclFileSym(ExtList decl, bool fullDecl)
  3469. {
  3470.     SymTab          ourSymTab  = cmpGlobalST;
  3471.     Parser          ourParser  = cmpParser;
  3472.     Scanner         ourScanner = cmpScanner;
  3473.  
  3474.     parserState     save;
  3475.     TypDef          base;
  3476.     SymDef          scope;
  3477.     declMods        memMod;
  3478.  
  3479.     SymXinfo        xtraList   = NULL;
  3480.  
  3481. #ifdef DEBUG
  3482.  
  3483.     if  (cmpConfig.ccVerbose >= 2)
  3484.     {
  3485.         printf("%s file-scope symbol: '", fullDecl ? "Defining " : "Declaring");
  3486.  
  3487.         if  (decl->dlQualified)
  3488.             cmpGlobalST->stDumpQualName(decl->mlQual);
  3489.         else
  3490.             printf("%s", hashTab::identSpelling(decl->mlName));
  3491.  
  3492.         printf("'\n");
  3493.     }
  3494.  
  3495. #endif
  3496.  
  3497.     /* Prepare scoping state for the symbol */
  3498.  
  3499.     cmpCurScp = NULL;
  3500.     cmpCurCls = NULL;
  3501.     scope     =
  3502.     cmpCurNS  = cmpGlobalNS;
  3503.     cmpCurST  = cmpGlobalST;
  3504.  
  3505.     cmpBindUseList(decl->dlUses);
  3506.  
  3507.     /* Is this a qualified (member) symbol declaration? */
  3508.  
  3509.     if  (decl->dlQualified)
  3510.     {
  3511.         /* Bind the qualified name */
  3512.  
  3513.         scope = cmpBindQualName(decl->mlQual, true);
  3514.  
  3515.         if  (scope)
  3516.         {
  3517.             switch (scope->sdSymKind)
  3518.             {
  3519.             case SYM_CLASS:
  3520.                 cmpCurCls = scope;
  3521.                 cmpCurNS  = cmpSymbolNS(scope);
  3522.                 break;
  3523.  
  3524.             case SYM_NAMESPACE:
  3525.                 cmpCurNS  = scope;
  3526.                 break;
  3527.  
  3528.             default:
  3529.                 // This sure looks bogus, it will be flagged below
  3530.                 break;
  3531.             }
  3532.  
  3533.             /* We may need to insert some "using" entries */
  3534.  
  3535.             if  (cmpCurNS != cmpGlobalNS)
  3536.                 cmpCurUses = cmpParser->parseInsertUses(cmpCurUses, cmpCurNS);
  3537.         }
  3538.     }
  3539.  
  3540.     /* Start reading source text from the definition */
  3541.  
  3542.     cmpParser->parsePrepText(&decl->dlDef, decl->dlComp, save);
  3543.  
  3544.     /* Check for a linkage specifier, custom attribute, and all the other prefix stuff */
  3545.  
  3546.     if  (decl->dlPrefixMods)
  3547.     {
  3548.         for (;;)
  3549.         {
  3550.             switch (ourScanner->scanTok.tok)
  3551.             {
  3552.                 SymXinfo        linkDesc;
  3553.  
  3554.                 unsigned        attrMask;
  3555.                 genericBuff     attrAddr;
  3556.                 size_t          attrSize;
  3557.                 SymDef          attrCtor;
  3558.  
  3559.             case tkLBrack:
  3560.             case tkEXTERN:
  3561.                 linkDesc = ourParser->parseBrackAttr(true, ATTR_MASK_SYS_IMPORT, &memMod);
  3562.                 xtraList = cmpAddXtraInfo(xtraList, linkDesc);
  3563.                 continue;
  3564.  
  3565.             case tkATTRIBUTE:
  3566.                 attrCtor = cmpParser->parseAttribute(ATGT_Methods|ATGT_Fields|ATGT_Constructors|ATGT_Properties,
  3567.                                                      attrMask,
  3568.                                                      attrAddr,
  3569.                                                      attrSize);
  3570.                 if  (attrSize)
  3571.                 {
  3572.                     xtraList = cmpAddXtraInfo(xtraList, attrCtor,
  3573.                                                         attrMask,
  3574.                                                         attrSize,
  3575.                                                         attrAddr);
  3576.                 }
  3577.                 continue;
  3578.             }
  3579.  
  3580.             break;
  3581.         }
  3582.     }
  3583.     else
  3584.     {
  3585.         /* Parse any leading modifiers */
  3586.  
  3587.         ourParser->parseDeclMods((accessLevels)decl->dlDefAcc, &memMod);
  3588.     }
  3589.  
  3590.     /* Is this a constructor body? */
  3591.  
  3592.     if  (decl->dlIsCtor)
  3593.     {
  3594.         base = cmpTypeVoid;
  3595.     }
  3596.     else
  3597.     {
  3598.         /* Parse the type specification */
  3599.  
  3600.         base = ourParser->parseTypeSpec(&memMod, true);
  3601.     }
  3602.  
  3603.     /* We have the type, now parse any declarators that follow */
  3604.  
  3605.     for (;;)
  3606.     {
  3607.         Ident           name;
  3608.         QualName        qual;
  3609.         TypDef          type;
  3610.         SymDef          newSym;
  3611.  
  3612.         /* Parse the next declarator */
  3613.  
  3614.         name = ourParser->parseDeclarator(&memMod,
  3615.                                           base,
  3616.                                           (dclrtrName)(DN_REQUIRED|DN_QUALOK),
  3617.                                           &type,
  3618.                                           &qual,
  3619.                                           true);
  3620.  
  3621.         if  ((name || qual) && type)
  3622.         {
  3623.             SymDef          oldSym;
  3624.  
  3625. //          if  (name && !strcmp(name->idSpelling(), "printf")) forceDebugBreak();
  3626.  
  3627.             /* Make sure we bind the type */
  3628.  
  3629.             cmpBindType(type, false, false);
  3630.  
  3631.             /* Is the name qualified? */
  3632.  
  3633.             scope = cmpGlobalNS;
  3634.  
  3635.             if  (qual)
  3636.             {
  3637.                 /* We don't expect member constants to be pre-declared */
  3638.  
  3639.                 assert(fullDecl);
  3640.  
  3641.                 scope = cmpBindQualName(qual, true);
  3642.                 if  (!scope)
  3643.                 {
  3644.                     /* Here if we have a disastrous error */
  3645.  
  3646.                 ERR:
  3647.  
  3648.                     if  (ourScanner->scanTok.tok == tkComma)
  3649.                         goto NEXT_DECL;
  3650.                     else
  3651.                         goto DONE_DECL;
  3652.                 }
  3653.  
  3654.                 /* Get hold of the last name in the sequence */
  3655.  
  3656.                 name = qual->qnTable[qual->qnCount - 1];
  3657.  
  3658.                 /* Do we have a definition of a class member? */
  3659.  
  3660.                 if  (scope->sdSymKind == SYM_CLASS)
  3661.                 {
  3662.                     /* Make sure the class has been declared */
  3663.  
  3664.                     cmpDeclSym(scope);
  3665.  
  3666.                     /* Look for the member in the class */
  3667.  
  3668.                     if  (type->tdTypeKind == TYP_FNC)
  3669.                     {
  3670.                         ovlOpFlavors    ovlOper = OVOP_NONE;
  3671.  
  3672.                         if  (name == scope->sdName)
  3673.                         {
  3674.                             ovlOper = (memMod.dmMod & DM_STATIC) ? OVOP_CTOR_STAT
  3675.                                                                  : OVOP_CTOR_INST;
  3676.                         }
  3677.  
  3678.                         newSym = (ovlOper == OVOP_NONE) ? ourSymTab->stLookupClsSym(   name, scope)
  3679.                                                         : ourSymTab->stLookupOperND(ovlOper, scope);
  3680.                         if  (newSym)
  3681.                         {
  3682.                             if  (newSym->sdSymKind != SYM_FNC)
  3683.                             {
  3684.                                 UNIMPL(!"fncs and vars can't overload, right?");
  3685.                             }
  3686.  
  3687.                             /* Make sure we find the proper overloaded function */
  3688.  
  3689.                             newSym = ourSymTab->stFindOvlFnc(newSym, type);
  3690.                         }
  3691.                     }
  3692.                     else
  3693.                     {
  3694.                         newSym = ourSymTab->stLookupClsSym(name, scope);
  3695.  
  3696.                         if  (newSym && newSym->sdSymKind != SYM_VAR)
  3697.                         {
  3698.                             UNIMPL(!"fncs and vars can't overload, right?");
  3699.                         }
  3700.                     }
  3701.  
  3702.                     /* Was the member found in the class? */
  3703.  
  3704.                     if  (newSym)
  3705.                     {
  3706.                         assert(newSym->sdCompileState >= CS_DECLARED);
  3707.  
  3708.                         /* Mark the method (and its class) as having a definition */
  3709.  
  3710.                         newSym->sdIsDefined         = true;
  3711.                         scope->sdClass.sdcHasBodies = true;
  3712.  
  3713.                         /* Record the member symbol in the declaration descriptor */
  3714.  
  3715.                         decl->mlSym = newSym;
  3716.  
  3717.                         /* Transfer the definition record to the class symbol */
  3718.  
  3719.                         cmpRecordMemDef(scope, decl);
  3720.  
  3721.                         /* Do we have a function or data member ? */
  3722.  
  3723.                         if  (newSym->sdSymKind == SYM_FNC)
  3724.                         {
  3725.                             /* Copy the type to capture argument names etc. */
  3726.  
  3727.                             newSym->sdType = cmpMergeFncType(newSym, type);
  3728.                         }
  3729.                         else
  3730.                         {
  3731.                             /* Remember that the member has an initializer */
  3732.  
  3733.                             if  (ourScanner->scanTok.tok == tkAsg)
  3734.                                 newSym->sdVar.sdvHadInit = true;
  3735.                         }
  3736.                     }
  3737.                     else
  3738.                     {
  3739.                         cmpError(ERRnoSuchMem, scope, qual, type);
  3740.                     }
  3741.  
  3742.                     goto DONE_DECL;
  3743.                 }
  3744.  
  3745.                 /* The name better belong to a namespace */
  3746.  
  3747.                 if  (scope->sdSymKind != SYM_NAMESPACE)
  3748.                 {
  3749.                     cmpError(ERRbadQualName, qual);
  3750.                     goto ERR;
  3751.                 }
  3752.             }
  3753.  
  3754.             /* Have we already pre-declared the symbol? */
  3755.  
  3756.             if  (decl->mlSym)
  3757.             {
  3758.                 /* This is the second pass for this constant symbol */
  3759.  
  3760.                 assert(fullDecl);
  3761.  
  3762.                 /* Get hold of the symbol (and make sure we didn't mess up) */
  3763.  
  3764.                 assert(memMod.dmMod & DM_CONST);
  3765.                 newSym = decl->mlSym;
  3766. //              printf("Revisit symbol [%08X->%08X] '%s' (declname = '%s')\n", decl, newSym, newSym->sdSpelling(), name->idSpelling());
  3767.                 assert(newSym->sdName == name);
  3768.                 assert(symTab::stMatchTypes(newSym->sdType, type));
  3769.                 newSym->sdCompileState = CS_DECLARED;
  3770.  
  3771.                 /* Now go evaluate the constant value */
  3772.  
  3773.                 assert(ourScanner->scanTok.tok == tkAsg);
  3774.  
  3775.                 goto EVAL_CONST;
  3776.             }
  3777.  
  3778.             /* Declare a symbol for the name */
  3779.  
  3780.             oldSym = ourSymTab->stLookupNspSym(name, NS_NORM, scope);
  3781.  
  3782.             if  (memMod.dmMod & DM_TYPEDEF)
  3783.             {
  3784.                 assert(fullDecl);
  3785.  
  3786.                 /* typedefs never overload, of course */
  3787.  
  3788.                 if  (oldSym)
  3789.                 {
  3790.                 REDEF:
  3791.  
  3792.                     cmpRedefSymErr(oldSym, (scope == cmpGlobalNS) ? ERRredefName
  3793.                                                                   : ERRredefMem);
  3794.                 }
  3795.                 else
  3796.                 {
  3797.                     TypDef      ttyp;
  3798.  
  3799.                     /* Declare the typedef symbol */
  3800.  
  3801.                     newSym = ourSymTab->stDeclareSym(name,
  3802.                                                      SYM_TYPEDEF,
  3803.                                                      NS_NORM,
  3804.                                                      scope);
  3805.  
  3806.                     /* Force the typedef type to be created */
  3807.  
  3808.                     ttyp = newSym->sdTypeGet();
  3809.  
  3810.                     /* Store the actual type in the typedef */
  3811.  
  3812.                     ttyp->tdTypedef.tdtType = cmpDirectType(type);
  3813.  
  3814.                     /* This symbol has been declared */
  3815.  
  3816.                     newSym->sdCompileState = CS_DECLARED;
  3817.                 }
  3818.             }
  3819.             else
  3820.             {
  3821.                 switch (type->tdTypeKind)
  3822.                 {
  3823.                 case TYP_FNC:
  3824.  
  3825.                     assert(fullDecl);
  3826.  
  3827.                     /* Might this be an overloaded function? */
  3828.  
  3829.                     if  (oldSym)
  3830.                     {
  3831.                         SymDef          tmpSym;
  3832.  
  3833.                         /* Can't overload global variables and functions */
  3834.  
  3835.                         if  (oldSym->sdSymKind != SYM_FNC)
  3836.                             goto REDEF;
  3837.  
  3838.                         /* Look for a function with a matching arglist */
  3839.  
  3840.                         tmpSym = ourSymTab->stFindOvlFnc(oldSym, type);
  3841.                         if  (tmpSym)
  3842.                         {
  3843.                             /* Is this the same exact function? */
  3844.  
  3845.                             if  (symTab::stMatchTypes(tmpSym->sdType, type))
  3846.                             {
  3847.                                 /*
  3848.                                     Transfer the new type to the symbol if
  3849.                                     there is a definition so that the names
  3850.                                     of arguments are right for the body.
  3851.                                  */
  3852.  
  3853.                                 if  (ourScanner->scanTok.tok == tkLCurly)
  3854.                                     tmpSym->sdType = type;
  3855.  
  3856.                                 // UNDONE: check that function attributes agree (and transfer them), etc.
  3857.                                 // UNDONE: check that default argument values aren't redefined
  3858.  
  3859.                                 if  (tmpSym->sdIsDefined && ourScanner->scanTok.tok == tkLCurly)
  3860.                                 {
  3861.                                     cmpError(ERRredefBody, tmpSym);
  3862.                                     newSym = tmpSym;
  3863.                                     goto CHK_INIT;
  3864.                                 }
  3865.  
  3866.                                 newSym = tmpSym;
  3867.                                 type   = cmpMergeFncType(newSym, type);
  3868.  
  3869.                                 /* Do we have any security/linkage info? */
  3870.  
  3871.                                 if  (xtraList)
  3872.                                 {
  3873.                                     /* Record the linkage/security specification(s) */
  3874.  
  3875.                                     newSym->sdFnc.sdfExtraInfo = xtraList;
  3876.  
  3877.                                     /* We can't import this sucker any more */
  3878.  
  3879.                                     newSym->sdIsImport         = false;
  3880.                                     newSym->sdFnc.sdfMDtoken   = 0;
  3881.                                 }
  3882.                             }
  3883.                             else
  3884.                             {
  3885.                                 /* Presumably the return types don't agree */
  3886.  
  3887.                                 cmpError(ERRbadOvl, tmpSym, name, type);
  3888.                             }
  3889.  
  3890.                             goto CHK_INIT;
  3891.                         }
  3892.                         else
  3893.                         {
  3894.                             /* It's a new overload, declare a symbol for it */
  3895.  
  3896.                             newSym = cmpCurST->stDeclareOvl(oldSym);
  3897.                         }
  3898.                     }
  3899.                     else
  3900.                     {
  3901.                         /* This is a brand new function */
  3902.  
  3903.                         newSym = ourSymTab->stDeclareSym(name,
  3904.                                                          SYM_FNC,
  3905.                                                          NS_NORM,
  3906.                                                          scope);
  3907.  
  3908.                     }
  3909.  
  3910.                     /* Is the function marked as "unsafe" ? */
  3911.  
  3912.                     if  (memMod.dmMod & DM_UNSAFE)
  3913.                         newSym->sdFnc.sdfUnsafe = true;
  3914.  
  3915.                     /* Remember the type of the function */
  3916.  
  3917.                     newSym->sdType = type;
  3918.  
  3919.                     /* Record the access level */
  3920.  
  3921.                     newSym->sdAccessLevel = (accessLevels)memMod.dmAcc;
  3922.  
  3923.                     /* Record any linkage/security/custom attribute info */
  3924.  
  3925.                     newSym->sdFnc.sdfExtraInfo = xtraList;
  3926.  
  3927.                     /* This symbol has been declared */
  3928.  
  3929.                     newSym->sdCompileState = CS_DECLARED;
  3930.  
  3931.                     /* Is the function named 'main' ? */
  3932.  
  3933.                     if  (name == cmpIdentMain)
  3934.                         cmpChk4entryPt(newSym);
  3935.  
  3936.                     break;
  3937.  
  3938.                 case TYP_VOID:
  3939.                     cmpError(ERRbadVoid, name);
  3940.                     break;
  3941.  
  3942.                 default:
  3943.  
  3944.                     /* File-scope variables never overload */
  3945.  
  3946.                     if  (oldSym)
  3947.                         goto REDEF;
  3948.  
  3949.                     if  ((memMod.dmMod & (DM_CONST|DM_EXTERN)) == (DM_CONST|DM_EXTERN))
  3950.                     {
  3951.                         cmpError(ERRextCns);
  3952.                         memMod.dmMod &= ~DM_CONST;
  3953.                     }
  3954.  
  3955.                     /* Declare the variable symbol */
  3956.  
  3957.                     newSym = ourSymTab->stDeclareSym(name,
  3958.                                                      SYM_VAR,
  3959.                                                      NS_NORM,
  3960.                                                      scope);
  3961.                     newSym->sdType         = type;
  3962.                     newSym->sdAccessLevel  = (accessLevels)memMod.dmAcc;
  3963.  
  3964.                     /* Global variables may not have a managed type for now */
  3965.  
  3966.                     if  (type->tdIsManaged && !qual)
  3967.                     {
  3968.                         cmpError(ERRmgdGlobVar);
  3969.                         break;
  3970.                     }
  3971.  
  3972.                     /* Are we fully declaring this symbol at this point? */
  3973.  
  3974.                     if  (!fullDecl)
  3975.                     {
  3976.                         DefList         memDef;
  3977.                         ExtList         extDef;
  3978.  
  3979.                         /* No, we've done enough at this stage */
  3980.  
  3981.                         assert(decl->dlHasDef);
  3982.                         assert(ourScanner->scanTok.tok == tkAsg);
  3983.  
  3984.                         /* Transfer the definition info to the method symbol */
  3985.  
  3986.                         memDef = ourSymTab->stRecordSymSrcDef(newSym,
  3987.                                                               decl->dlComp,
  3988.                                                               decl->dlUses,
  3989.                                                               decl->dlDef.dsdBegPos,
  3990. //                                                            decl->dlDef.dsdEndPos,
  3991.                                                               decl->dlDef.dsdSrcLno,
  3992. //                                                            decl->dlDef.dsdSrcCol,
  3993.                                                               true);
  3994.                         memDef->dlHasDef   = true;
  3995.                         memDef->dlDeclSkip = decl->dlDeclSkip;
  3996.  
  3997.                         /* Record the symbol so that we don't try to redeclare it */
  3998.  
  3999.                         assert(decl  ->dlExtended);
  4000.                         assert(memDef->dlExtended); extDef = (ExtList)memDef;
  4001.  
  4002. //                      printf("Defer   symbol [%08X->%08X] '%s'\n",   decl, newSym, newSym->sdSpelling());
  4003. //                      printf("Defer   symbol [%08X->%08X] '%s'\n", extDef, newSym, newSym->sdSpelling());
  4004.  
  4005.                         extDef->mlSym = decl->mlSym = newSym;
  4006.  
  4007.                         newSym->sdVar.sdvDeferCns = (ourScanner->scanTok.tok == tkAsg);
  4008.                         goto DONE_DECL;
  4009.                     }
  4010.  
  4011.                     /* This symbol has been declared */
  4012.  
  4013.                     newSym->sdCompileState = CS_DECLARED;
  4014.  
  4015.                     /* Remember whether assignment is allowed */
  4016.  
  4017.                     if  (memMod.dmMod & DM_SEALED)
  4018.                         newSym->sdIsSealed = true;
  4019.  
  4020.                     /* Is there an explicit initialization? */
  4021.  
  4022.                     if  (decl->dlHasDef)
  4023.                     {
  4024.                         DefList         memDef;
  4025.  
  4026.                         /* Transfer the definition info to the variable symbol */
  4027.  
  4028.                         memDef = ourSymTab->stRecordSymSrcDef(newSym,
  4029.                                                               decl->dlComp,
  4030.                                                               decl->dlUses,
  4031.                                                               decl->dlDef.dsdBegPos,
  4032. //                                                            decl->dlDef.dsdEndPos,
  4033.                                                               decl->dlDef.dsdSrcLno);
  4034.                         memDef->dlHasDef   = true;
  4035.                         memDef->dlDeclSkip = decl->dlDeclSkip;
  4036.                     }
  4037.                     else
  4038.                     {
  4039.                         if  (!(memMod.dmMod & DM_EXTERN))
  4040.                             newSym->sdIsDefined = true;
  4041.                     }
  4042.  
  4043.                     break;
  4044.                 }
  4045.             }
  4046.         }
  4047.  
  4048.     CHK_INIT:
  4049.  
  4050.         /* Is there an initializer or method body? */
  4051.  
  4052.         switch (ourScanner->scanTok.tok)
  4053.         {
  4054.         case tkAsg:
  4055.  
  4056.             /* Remember that we've found an initializer */
  4057.  
  4058.             if  (newSym && newSym->sdSymKind == SYM_VAR)
  4059.             {
  4060.                 newSym->sdVar.sdvHadInit = true;
  4061.             }
  4062.             else
  4063.             {
  4064.                 /* Make sure we don't have a typedef or function */
  4065.  
  4066.                 if  ((memMod.dmMod & DM_TYPEDEF) || type->tdTypeKind == TYP_FNC)
  4067.                     cmpError(ERRbadInit);
  4068.             }
  4069.  
  4070.             /* Process the initializer */
  4071.  
  4072.             if  (memMod.dmMod & DM_CONST)
  4073.             {
  4074.             EVAL_CONST:
  4075.  
  4076.                 /* Presumably the initial value of the symbol follows */
  4077.  
  4078.                 if  (ourScanner->scan() == tkLCurly)
  4079.                 {
  4080.                     /* This better be a struct or array */
  4081.  
  4082.                     switch (type->tdTypeKind)
  4083.                     {
  4084.                     case TYP_CLASS:
  4085.                     case TYP_ARRAY:
  4086.                         ourScanner->scanSkipText(tkLCurly, tkRCurly);
  4087.                         if  (ourScanner->scanTok.tok == tkRCurly)
  4088.                              ourScanner->scan();
  4089.                         break;
  4090.  
  4091.                     default:
  4092.                         cmpError(ERRbadBrInit, type);
  4093.                         break;
  4094.                     }
  4095.  
  4096.                     newSym->sdCompileState = CS_DECLARED;
  4097.                     break;
  4098.                 }
  4099.  
  4100.                 /* Parse and evaluate the constant value */
  4101.  
  4102.                 cmpParseConstDecl(newSym);
  4103.             }
  4104.             else
  4105.             {
  4106.                 type = cmpActualType(type);
  4107.  
  4108.                 /* For now, we simply skip non-constant initializers */
  4109.  
  4110.                 ourScanner->scanSkipText(tkNone, tkNone, tkComma);
  4111.  
  4112.                 /* Special case: is the variable an undimensioned array? */
  4113.  
  4114.                 if  (type->tdTypeKind == TYP_ARRAY && type->tdIsManaged == false
  4115.                                                    && type->tdIsUndimmed)
  4116.                 {
  4117.                     SymList         list;
  4118.  
  4119.                     /* Add this variable to the appropriate list */
  4120.  
  4121. #if MGDDATA
  4122.                     list = new SymList;
  4123. #else
  4124.                     list =    (SymList)cmpAllocTemp.baAlloc(sizeof(*list));
  4125. #endif
  4126.  
  4127.                     list->slSym  = newSym;
  4128.                     list->slNext = cmpNoDimArrVars;
  4129.                                    cmpNoDimArrVars = list;
  4130.                 }
  4131.             }
  4132.  
  4133.             break;
  4134.  
  4135.         case tkLCurly:
  4136.  
  4137.             if  (type->tdTypeKind != TYP_FNC)
  4138.                 cmpError(ERRbadLcurly);
  4139.  
  4140.             /* Record the position of the function body */
  4141.  
  4142.             if  (newSym)
  4143.             {
  4144.                 SymDef          clsSym;
  4145.                 DefList         memDef;
  4146.  
  4147.                 /* Mark the method as having a body now */
  4148.  
  4149.                 newSym->sdIsDefined = true;
  4150.  
  4151.                 /* If this is a class member, mark the class */
  4152.  
  4153.                 clsSym = newSym->sdParent;
  4154.                 if  (clsSym->sdSymKind == SYM_CLASS)
  4155.                     clsSym->sdClass.sdcHasBodies = true;
  4156.  
  4157.                 /* Transfer the definition info to the method symbol */
  4158.  
  4159.                 memDef = ourSymTab->stRecordSymSrcDef(newSym,
  4160.                                                       decl->dlComp,
  4161.                                                       decl->dlUses,
  4162.                                                       decl->dlDef.dsdBegPos,
  4163. //                                                    decl->dlDef.dsdEndPos,
  4164.                                                       decl->dlDef.dsdSrcLno);
  4165.                 memDef->dlHasDef   = true;
  4166.                 memDef->dlDeclSkip = decl->dlDeclSkip;
  4167.             }
  4168.  
  4169.             decl->dlHasDef = true;
  4170.             goto DONE_DECL;
  4171.  
  4172.         default:
  4173.  
  4174.             if  (memMod.dmMod & DM_CONST)
  4175.                 cmpError(ERRnoCnsInit);
  4176.  
  4177.             break;
  4178.         }
  4179.  
  4180.     NEXT_DECL:
  4181.  
  4182.         /* Are there any more declarators? */
  4183.  
  4184.         if  (ourScanner->scanTok.tok != tkComma)
  4185.             break;
  4186.  
  4187.         /* Swallow the "," and go get the next declarator */
  4188.  
  4189.         ourScanner->scan();
  4190.     }
  4191.  
  4192.     /* Make sure we've consumed the expected amount of text */
  4193.  
  4194.     if  (ourScanner->scanTok.tok != tkSColon)
  4195.         cmpError(ERRnoSemic);
  4196.  
  4197. DONE_DECL:
  4198.  
  4199.     /* We're done reading source text from the definition */
  4200.  
  4201.     cmpParser->parseDoneText(save);
  4202. }
  4203.  
  4204. /*****************************************************************************/
  4205. /*****************************************************************************
  4206.  *
  4207.  *  Report any modifiers in the given mask as errors.
  4208.  */
  4209.  
  4210. void                compiler::cmpModifierError(unsigned err, unsigned mods)
  4211. {
  4212.     HashTab         hash = cmpGlobalHT;
  4213.  
  4214.     if  (mods & DM_CONST    ) cmpError(err, hash->tokenToIdent(tkCONST    ));
  4215.     if  (mods & DM_STATIC   ) cmpError(err, hash->tokenToIdent(tkSTATIC   ));
  4216.     if  (mods & DM_EXTERN   ) cmpError(err, hash->tokenToIdent(tkEXTERN   ));
  4217.     if  (mods & DM_INLINE   ) cmpError(err, hash->tokenToIdent(tkINLINE   ));
  4218.     if  (mods & DM_EXCLUDE  ) cmpError(err, hash->tokenToIdent(tkEXCLUSIVE));
  4219.     if  (mods & DM_VIRTUAL  ) cmpError(err, hash->tokenToIdent(tkVIRTUAL  ));
  4220.     if  (mods & DM_ABSTRACT ) cmpError(err, hash->tokenToIdent(tkABSTRACT ));
  4221.     if  (mods & DM_OVERRIDE ) cmpError(err, hash->tokenToIdent(tkOVERRIDE ));
  4222.     if  (mods & DM_VOLATILE ) cmpError(err, hash->tokenToIdent(tkVOLATILE ));
  4223.     if  (mods & DM_MANAGED  ) cmpError(err, hash->tokenToIdent(tkMANAGED  ));
  4224.     if  (mods & DM_UNMANAGED) cmpError(err, hash->tokenToIdent(tkUNMANAGED));
  4225. }
  4226.  
  4227. void                compiler::cmpMemFmod2Error(tokens tok1, tokens tok2)
  4228. {
  4229.     HashTab         hash = cmpGlobalHT;
  4230.  
  4231.     cmpGenError(ERRfmModifier2, hash->tokenToIdent(tok1)->idSpelling(),
  4232.                                 hash->tokenToIdent(tok2)->idSpelling());
  4233. }
  4234.  
  4235. /*****************************************************************************
  4236.  *
  4237.  *  Add a data member to the specified class.
  4238.  */
  4239.  
  4240. SymDef              compiler::cmpDeclDataMem(SymDef     clsSym,
  4241.                                              declMods   memMod,
  4242.                                              TypDef     type,
  4243.                                              Ident      name)
  4244. {
  4245.     SymDef          memSym;
  4246.     unsigned        badMod;
  4247.     name_space      nameSP;
  4248.  
  4249.     /* Make sure the modifiers look OK */
  4250.  
  4251.     badMod = memMod.dmMod & ~(DM_STATIC|DM_CONST|DM_SEALED|DM_MANAGED|DM_UNMANAGED);
  4252.     if  (badMod)
  4253.         cmpModifierError(ERRdmModifier, badMod);
  4254.  
  4255.     /* Is this an interface member? */
  4256.  
  4257.     if  (clsSym->sdClass.sdcFlavor == STF_INTF)
  4258.     {
  4259.         cmpError(ERRintfDM);
  4260.     }
  4261.  
  4262.     /* See if the class already has a data member with a matching name */
  4263.  
  4264.     memSym = cmpCurST->stLookupClsSym(name, clsSym);
  4265.     if  (memSym)
  4266.     {
  4267.         cmpRedefSymErr(memSym, ERRredefMem);
  4268.         return  NULL;
  4269.     }
  4270.  
  4271.     /* Create a member symbol and add it to the class */
  4272.  
  4273.     nameSP = NS_NORM;
  4274.  
  4275.     memSym = cmpCurST->stDeclareSym(name, SYM_VAR, nameSP, clsSym);
  4276.  
  4277.     /* Remember the type, access level and other attributes of the member */
  4278.  
  4279.     memSym->sdType = type;
  4280.  
  4281.     assert((memMod.dmMod & DM_TYPEDEF) == 0);
  4282.  
  4283.     if  (memMod.dmMod & DM_STATIC)
  4284.         memSym->sdIsStatic = true;
  4285.  
  4286.     if  (memMod.dmMod & DM_SEALED)
  4287.         memSym->sdIsSealed = true;
  4288.  
  4289.     memSym->sdAccessLevel  = (accessLevels)memMod.dmAcc;
  4290.     memSym->sdIsMember     = true;
  4291.  
  4292.     /* Remember whether this is a member of a managed class */
  4293.  
  4294.     memSym->sdIsManaged    = clsSym->sdIsManaged;
  4295.  
  4296.     /* The member has been declared */
  4297.  
  4298.     memSym->sdCompileState = CS_DECLARED;
  4299.  
  4300.     return  memSym;
  4301. }
  4302.  
  4303. /*****************************************************************************
  4304.  *
  4305.  *  Add a function member (i.e. a method) to the specified class.
  4306.  */
  4307.  
  4308. SymDef              compiler::cmpDeclFuncMem(SymDef     clsSym,
  4309.                                              declMods   memMod,
  4310.                                              TypDef     type,
  4311.                                              Ident      name)
  4312. {
  4313.     ovlOpFlavors    ovlOper;
  4314.  
  4315.     SymDef          oldSym;
  4316.     SymDef          memSym;
  4317.  
  4318. //  printf("Declare method '%s'\n", cmpGlobalST->stTypeName(type, NULL, name, NULL, false));
  4319.  
  4320.     /* "extern" is never allowed on a method except for sysimport's */
  4321.  
  4322.     if  (memMod.dmMod & DM_EXTERN)
  4323.         cmpModifierError(ERRfmModifier, DM_EXTERN);
  4324.  
  4325.     /* Check for any other illegal modifier combinations */
  4326.  
  4327. #if 0
  4328.     if  ((memMod.dmMod & (DM_STATIC|DM_SEALED)) == (DM_STATIC|DM_SEALED))
  4329.         cmpMemFmod2Error(tkSTATIC, tkSEALED);
  4330. #endif
  4331.  
  4332.     /* This an overloaded operator / ctor if the name is a token */
  4333.  
  4334.     ovlOper = OVOP_NONE;
  4335.  
  4336.     if  (hashTab::tokenOfIdent(name) != tkNone)
  4337.     {
  4338.         unsigned        argc = 0;
  4339.         ArgDef          args = type->tdFnc.tdfArgs.adArgs;
  4340.  
  4341.         if  (args)
  4342.         {
  4343.             argc++;
  4344.  
  4345.             args = args->adNext;
  4346.             if  (args)
  4347.             {
  4348.                 argc++;
  4349.  
  4350.                 if  (args->adNext)
  4351.                     argc++;
  4352.             }
  4353.         }
  4354.  
  4355.         ovlOper = cmpGlobalST->stOvlOperIndex(hashTab::tokenOfIdent(name), argc);
  4356.  
  4357.         if  (ovlOper == OVOP_PROP_GET || ovlOper == OVOP_PROP_SET)
  4358.         {
  4359.             memSym = cmpCurST->stDeclareSym(NULL, SYM_FNC, NS_NORM, clsSym);
  4360.             goto FILL;
  4361.         }
  4362.     }
  4363.     else if (name == clsSym->sdName && type->tdTypeKind == TYP_FNC)
  4364.     {
  4365.         ovlOper = (memMod.dmMod & DM_STATIC) ? OVOP_CTOR_STAT : OVOP_CTOR_INST;
  4366.     }
  4367.  
  4368.     /* See if the class already has a method with a matching name */
  4369.  
  4370.     oldSym = (ovlOper == OVOP_NONE) ? cmpCurST->stLookupClsSym(   name, clsSym)
  4371.                                     : cmpCurST->stLookupOperND(ovlOper, clsSym);
  4372.  
  4373.     if  (oldSym)
  4374.     {
  4375.         SymDef          tmpSym;
  4376.  
  4377.         if  (oldSym->sdSymKind != SYM_FNC)
  4378.         {
  4379.             cmpRedefSymErr(oldSym, ERRredefMem);
  4380.             return  NULL;
  4381.         }
  4382.  
  4383.         /* Look for an existing method with an identical signature */
  4384.  
  4385.         tmpSym = cmpCurST->stFindOvlFnc(oldSym, type);
  4386.         if  (tmpSym)
  4387.         {
  4388.             cmpRedefSymErr(tmpSym, ERRredefMem);
  4389.             return  NULL;
  4390.         }
  4391.  
  4392.         /* The new method is a new overload */
  4393.  
  4394.         memSym = cmpCurST->stDeclareOvl(oldSym);
  4395.  
  4396.         /* Copy over some info from the existing method */
  4397.  
  4398.         memSym->sdFnc.sdfOverload = oldSym->sdFnc.sdfOverload;
  4399.     }
  4400.     else
  4401.     {
  4402.         // UNDONE: Need to check the base class!
  4403.  
  4404.         /* Create a member symbol and add it to the class */
  4405.  
  4406.         if  (ovlOper == OVOP_NONE)
  4407.             memSym = cmpCurST->stDeclareSym (name, SYM_FNC, NS_NORM, clsSym);
  4408.         else
  4409.             memSym = cmpCurST->stDeclareOper(ovlOper               , clsSym);
  4410.     }
  4411.  
  4412. FILL:
  4413.  
  4414.     /* Remember the type, access level and other attributes of the member */
  4415.  
  4416.     memSym->sdType = type;
  4417.  
  4418.     assert((memMod.dmMod & DM_TYPEDEF) == 0);
  4419.  
  4420.     if  (memMod.dmMod & DM_STATIC  ) memSym->sdIsStatic         = true;
  4421.     if  (memMod.dmMod & DM_SEALED  ) memSym->sdIsSealed         = true;
  4422.     if  (memMod.dmMod & DM_EXCLUDE ) memSym->sdFnc.sdfExclusive = true;
  4423.     if  (memMod.dmMod & DM_ABSTRACT) memSym->sdIsAbstract       = true;
  4424.     if  (memMod.dmMod & DM_NATIVE  ) memSym->sdFnc.sdfNative    = true;
  4425.  
  4426.     memSym->sdAccessLevel  = (accessLevels)memMod.dmAcc;
  4427.  
  4428.     memSym->sdIsMember     = true;
  4429.  
  4430.     /* Remember whether this is a member of a managed class */
  4431.  
  4432.     memSym->sdIsManaged    = clsSym->sdIsManaged;
  4433.  
  4434.     /* The member is now in "declared" state */
  4435.  
  4436.     memSym->sdCompileState = CS_DECLARED;
  4437.  
  4438.     /* Is the method marked as "unsafe" ? */
  4439.  
  4440.     if  (memMod.dmMod & DM_UNSAFE)
  4441.         memSym->sdFnc.sdfUnsafe = true;
  4442.  
  4443.     /* Record the fact that the class has some method bodies */
  4444.  
  4445.     clsSym->sdClass.sdcHasMeths = true;
  4446.  
  4447.     return  memSym;
  4448. }
  4449.  
  4450. /*****************************************************************************
  4451.  *
  4452.  *  Add a property member to the specified class.
  4453.  */
  4454.  
  4455. SymDef              compiler::cmpDeclPropMem(SymDef     clsSym,
  4456.                                              TypDef     type,
  4457.                                              Ident      name)
  4458. {
  4459.     SymDef          propSym;
  4460.  
  4461.     SymTab          ourStab = cmpGlobalST;
  4462.  
  4463. //  if  (!strcmp(name->idSpelling(), "<name>")) printf("Declare property '%s'\n", name->idSpelling());
  4464.  
  4465.     propSym = ourStab->stLookupProp(name, clsSym);
  4466.  
  4467.     if  (propSym)
  4468.     {
  4469.         SymDef          tsym;
  4470.  
  4471.         /* Check for a redefinition of an earlier property */
  4472.  
  4473.         tsym = (propSym->sdSymKind == SYM_PROP) ? ourStab->stFindSameProp(propSym, type)
  4474.                                                 : propSym;
  4475.  
  4476.         if  (tsym)
  4477.         {
  4478.             cmpRedefSymErr(tsym, ERRredefMem);
  4479.             return  NULL;
  4480.         }
  4481.  
  4482.         /* The new property is a new overload */
  4483.  
  4484.         propSym = ourStab->stDeclareOvl(propSym);
  4485.     }
  4486.     else
  4487.     {
  4488.         propSym = ourStab->stDeclareSym(name, SYM_PROP, NS_NORM, clsSym);
  4489.     }
  4490.  
  4491.     propSym->sdIsMember    = true;
  4492.     propSym->sdIsManaged   = true;
  4493.     propSym->sdType        = type;
  4494.  
  4495.     return  propSym;
  4496. }
  4497.  
  4498. /*****************************************************************************
  4499.  *
  4500.  *  Save a record for the given symbol and source position, for some unknown
  4501.  *  but limited amount of time.
  4502.  */
  4503.  
  4504. ExtList             compiler::cmpTempMLappend(ExtList       list,
  4505.                                               ExtList     * lastPtr,
  4506.                                               SymDef        sym,
  4507.                                               SymDef        comp,
  4508.                                               UseList       uses,
  4509.                                               scanPosTP     dclFpos,
  4510.                                               unsigned      dclLine)
  4511. {
  4512.     ExtList         entry;
  4513.  
  4514.     if  (cmpTempMLfree)
  4515.     {
  4516.         entry = cmpTempMLfree;
  4517.                 cmpTempMLfree = (ExtList)entry->dlNext;
  4518.     }
  4519.     else
  4520.     {
  4521. #if MGDDATA
  4522.         entry = new ExtList;
  4523. #else
  4524.         entry =    (ExtList)cmpAllocPerm.nraAlloc(sizeof(*entry));
  4525. #endif
  4526.     }
  4527.  
  4528.     entry->dlNext          = NULL;
  4529.  
  4530.     entry->dlDef.dsdBegPos = dclFpos;
  4531. //  entry->dlDef.dsdEndPos = dclEpos;
  4532.     entry->dlDef.dsdSrcLno = dclLine; assert(dclLine < 0xFFFF);
  4533. //  entry->dlDef.dsdSrcCol = dclCol;  assert(dclCol  < 0xFFFF);
  4534.  
  4535.     entry->dlHasDef        = true;
  4536.     entry->dlComp          = comp;
  4537.     entry->dlUses          = uses;
  4538.     entry->mlSym           = sym;
  4539.  
  4540.     /* Now add the entry to the caller's list */
  4541.  
  4542.     if  (list)
  4543.         (*lastPtr)->dlNext = entry;
  4544.     else
  4545.         list               = entry;
  4546.  
  4547.     *lastPtr = entry;
  4548.  
  4549.     /* Record the entry in the member symbol */
  4550.  
  4551.     assert(sym->sdSrcDefList == NULL); sym->sdSrcDefList = entry;
  4552.  
  4553.     return  list;
  4554. }
  4555.  
  4556. inline
  4557. void                compiler::cmpTempMLrelease(ExtList entry)
  4558. {
  4559.     entry->dlNext = cmpTempMLfree;
  4560.                     cmpTempMLfree = entry;
  4561. }
  4562.  
  4563. /*****************************************************************************
  4564.  *
  4565.  *  Bring the given delegate to "declared" state.
  4566.  */
  4567.  
  4568. void                compiler::cmpDeclDelegate(DefList decl,
  4569.                                               SymDef  dlgSym, accessLevels acc)
  4570. {
  4571.     Parser          ourParser = cmpParser;
  4572.  
  4573.     TypDef          dlgTyp;
  4574.     unsigned        badMod;
  4575.     parserState     save;
  4576.  
  4577.     declMods        mods;
  4578.     Ident           name;
  4579.     TypDef          type;
  4580.  
  4581.     /* Get hold of the class type */
  4582.  
  4583.     dlgTyp = dlgSym->sdTypeGet(); assert(dlgTyp && dlgTyp->tdClass.tdcSymbol == dlgSym);
  4584.  
  4585.     /* Set the base class to "Delegate"/"MultiDelegate" and fix other things as well */
  4586.  
  4587.     if  (dlgSym->sdClass.sdcMultiCast)
  4588.     {
  4589.         cmpMultiRef();  dlgTyp->tdClass.tdcBase = cmpClassMulti->sdType;
  4590.     }
  4591.     else
  4592.     {
  4593.         cmpDelegRef();  dlgTyp->tdClass.tdcBase = cmpClassDeleg->sdType;
  4594.     }
  4595.  
  4596.     dlgSym->sdCompileState  = CS_DECLARED;
  4597.  
  4598.     /* Start reading from the delegate declaration source text */
  4599.  
  4600.     ourParser->parsePrepText(&decl->dlDef, decl->dlComp, save);
  4601.  
  4602.     /* Parse the declaration - it looks like any other, really */
  4603.  
  4604.     ourParser->parseDeclMods(acc, &mods);
  4605.  
  4606.     /* Make sure the modifiers look OK */
  4607.  
  4608.     badMod = mods.dmMod & ~(DM_MANAGED|DM_UNMANAGED);
  4609.     if  (badMod)
  4610.         cmpModifierError(ERRdmModifier, badMod);
  4611.  
  4612.     /* Swallow "asynch" if present */
  4613.  
  4614.     if  (cmpScanner->scanTok.tok == tkASYNCH)
  4615.         cmpScanner->scan();
  4616.  
  4617.     /* Now parse the type spec and a single declarator */
  4618.  
  4619.     type = ourParser->parseTypeSpec(&mods, true);
  4620.  
  4621.     name = ourParser->parseDeclarator(&mods,
  4622.                                       type,
  4623.                                       DN_REQUIRED,
  4624.                                       &type,
  4625.                                       NULL,
  4626.                                       true);
  4627.  
  4628.     if  (name && type)
  4629.     {
  4630.         SymDef          msym;
  4631.         ArgDscRec       args;
  4632.         ArgDef          last;
  4633.         TypDef          tmpt;
  4634.  
  4635.         cmpBindType(type, false, false);
  4636.  
  4637.         /* Delegates must be declared as functions */
  4638.  
  4639.         if  (type->tdTypeKind != TYP_FNC)
  4640.         {
  4641.             cmpError(ERRdlgNonFn);
  4642.             goto DONE_DLG;
  4643.         }
  4644.  
  4645.         if  (cmpScanner->scanTok.tok != tkSColon)
  4646.             cmpError(ERRnoCmSc);
  4647.  
  4648.         /* Multicast delegates must not return a non-void value */
  4649.  
  4650.         if  (dlgSym->sdClass.sdcMultiCast)
  4651.         {
  4652.             if  (cmpDirectType(type->tdFnc.tdfRett)->tdTypeKind != TYP_VOID)
  4653.                 cmpError(ERRmulDlgRet);
  4654.         }
  4655.  
  4656.         /* Declare a "Invoke" method with the delegate's type */
  4657.  
  4658.         mods.dmAcc = ACL_PUBLIC;
  4659.         mods.dmMod = 0;
  4660.  
  4661.         /* First see if the user himself has supplied an "Invoke" method */
  4662.  
  4663.         msym = cmpCurST->stLookupClsSym(cmpIdentInvoke, dlgSym);
  4664.         if  (msym && msym->sdSymKind == SYM_FNC)
  4665.         {
  4666.             if  (cmpCurST->stFindOvlFnc(msym, type))
  4667.                 goto DONE_INVK;
  4668.         }
  4669.  
  4670.         msym = cmpDeclFuncMem(dlgSym, mods, type, cmpIdentInvoke); assert(msym);
  4671.         msym->sdIsSealed        = true;
  4672.         msym->sdIsDefined       = true;
  4673.         msym->sdIsImplicit      = true;
  4674.         msym->sdFnc.sdfVirtual  = true;
  4675.         msym->sdFnc.sdfRThasDef = true;
  4676.         msym->sdFnc.sdfOverride = true;
  4677.  
  4678.     DONE_INVK:
  4679.  
  4680.         /* Are we supposed to do the "asynch" thing? */
  4681.  
  4682.         if  (!dlgSym->sdClass.sdcAsyncDlg)
  4683.             goto DONE_ASYNC;
  4684.  
  4685.         /* Make sure we have the various hard-wired types we'll need */
  4686.  
  4687.         if  (!cmpAsyncDlgRefTp)
  4688.         {
  4689.             SymDef          asym;
  4690.             Ident           aname;
  4691.  
  4692.             aname = cmpGlobalHT->hashString("AsyncCallback");
  4693.             asym  = cmpGlobalST->stLookupNspSym(aname, NS_NORM, cmpNmSpcSystem);
  4694.  
  4695.             if  (!asym || asym->sdSymKind         != SYM_CLASS
  4696.                        || asym->sdClass.sdcFlavor != STF_DELEGATE)
  4697.             {
  4698.                 UNIMPL(!"didn't find class 'System.AsyncCallbackDelegate', now what?");
  4699.             }
  4700.  
  4701.             cmpAsyncDlgRefTp = asym->sdTypeGet()->tdClass.tdcRefTyp;
  4702.         }
  4703.  
  4704.         if  (!cmpIAsyncRsRefTp)
  4705.         {
  4706.             SymDef          asym;
  4707.             Ident           aname;
  4708.  
  4709.             aname = cmpGlobalHT->hashString("IAsyncResult");
  4710.             asym  = cmpGlobalST->stLookupNspSym(aname, NS_NORM, cmpNmSpcSystem);
  4711.  
  4712.             if  (!asym || asym->sdSymKind         != SYM_CLASS
  4713.                        || asym->sdClass.sdcFlavor != STF_INTF)
  4714.             {
  4715.                 UNIMPL(!"didn't find interface 'System.IAsyncResult', now what?");
  4716.             }
  4717.  
  4718.             cmpIAsyncRsRefTp = asym->sdTypeGet()->tdClass.tdcRefTyp;
  4719.         }
  4720.  
  4721.         /* Declare the "BeginInvoke" method */
  4722.  
  4723.         cmpGlobalST->stExtArgsBeg(args, last, type->tdFnc.tdfArgs);
  4724.         cmpGlobalST->stExtArgsAdd(args, last, cmpAsyncDlgRefTp, NULL);
  4725.         cmpGlobalST->stExtArgsAdd(args, last, cmpObjectRef()  , NULL);
  4726.         cmpGlobalST->stExtArgsEnd(args);
  4727.  
  4728.         tmpt = cmpGlobalST->stNewFncType(args, cmpIAsyncRsRefTp);
  4729.  
  4730.         msym = cmpDeclFuncMem(dlgSym, mods, tmpt, cmpIdentInvokeBeg); assert(msym);
  4731.         msym->sdIsSealed        = true;
  4732.         msym->sdIsDefined       = true;
  4733.         msym->sdIsImplicit      = true;
  4734.         msym->sdFnc.sdfVirtual  = true;
  4735.         msym->sdFnc.sdfRThasDef = true;
  4736.         msym->sdFnc.sdfOverride = true;
  4737.  
  4738.         /* Declare the   "EndInvoke" method */
  4739.  
  4740.         cmpGlobalST->stExtArgsBeg(args, last, type->tdFnc.tdfArgs, false, true);
  4741.         cmpGlobalST->stExtArgsAdd(args, last, cmpIAsyncRsRefTp, NULL);
  4742.         cmpGlobalST->stExtArgsEnd(args);
  4743.  
  4744.         tmpt = cmpGlobalST->stNewFncType(args, type->tdFnc.tdfRett);
  4745.  
  4746.         msym = cmpDeclFuncMem(dlgSym, mods, tmpt, cmpIdentInvokeEnd); assert(msym);
  4747.         msym->sdIsSealed        = true;
  4748.         msym->sdIsDefined       = true;
  4749.         msym->sdIsImplicit      = true;
  4750.         msym->sdFnc.sdfVirtual  = true;
  4751.         msym->sdFnc.sdfRThasDef = true;
  4752.         msym->sdFnc.sdfOverride = true;
  4753.  
  4754.     DONE_ASYNC:
  4755.  
  4756.         /* Declare the ctor as "ctor(Object obj, naturaluint fnc)" */
  4757.  
  4758. #if     defined(__IL__) && !defined(_MSC_VER)
  4759.         cmpParser->parseArgListNew(args,
  4760.                                    2,
  4761.                                    true, cmpFindObjectType(), A"obj",
  4762.                                          cmpTypeInt         , A"fnc",
  4763. //                                       cmpTypeNatUint     , A"fnc",
  4764.                                          NULL);
  4765. #else
  4766.         cmpParser->parseArgListNew(args,
  4767.                                    2,
  4768.                                    true, cmpFindObjectType(),  "obj",
  4769.                                          cmpTypeInt         ,  "fnc",
  4770. //                                       cmpTypeNatUint     ,  "fnc",
  4771.                                          NULL);
  4772. #endif
  4773.  
  4774.         type = cmpGlobalST->stNewFncType(args, cmpTypeVoid);
  4775.  
  4776.         /* First see if the user himself has supplied a constructor */
  4777.  
  4778.         msym = cmpCurST->stLookupOperND(OVOP_CTOR_INST, dlgSym);
  4779.         if  (msym && msym->sdSymKind == SYM_FNC)
  4780.         {
  4781.             if  (cmpCurST->stFindOvlFnc(msym, type))
  4782.                 goto DONE_DLG;
  4783.         }
  4784.  
  4785.         msym = cmpDeclFuncMem(dlgSym, mods, type, dlgSym->sdName);
  4786.         msym->sdIsDefined       = true;
  4787.         msym->sdFnc.sdfCtor     = true;
  4788.         msym->sdIsImplicit      = true;
  4789.         msym->sdFnc.sdfRThasDef = true;
  4790.     }
  4791.  
  4792. DONE_DLG:
  4793.  
  4794.     /* We're finished with this declaration */
  4795.  
  4796.     cmpParser->parseDoneText(save);
  4797. }
  4798.  
  4799. void                compiler::cmpFindHiddenBaseFNs(SymDef fncSym,
  4800.                                                    SymDef clsSym)
  4801. {
  4802.     SymTab          ourSymTab = cmpGlobalST;
  4803.     Ident           fncName   = fncSym->sdName;
  4804.  
  4805.     for (;;)
  4806.     {
  4807.         SymDef          baseMFN = ourSymTab->stLookupClsSym(fncName, clsSym);
  4808.         SymDef          ovlSym;
  4809.  
  4810.         if  (baseMFN)
  4811.         {
  4812.             /* Look for any hidden methods in the base */
  4813.  
  4814.             for (ovlSym = baseMFN; ovlSym; ovlSym = ovlSym->sdFnc.sdfNextOvl)
  4815.             {
  4816.                 if  (!ourSymTab->stFindOvlFnc(fncSym, ovlSym->sdType))
  4817.                     cmpWarnQnm(WRNhideVirt, ovlSym);
  4818.             }
  4819.  
  4820.             return;
  4821.         }
  4822.  
  4823.         if  (!clsSym->sdType->tdClass.tdcBase)
  4824.             break;
  4825.  
  4826.         clsSym = clsSym->sdType->tdClass.tdcBase->tdClass.tdcSymbol;
  4827.     }
  4828. }
  4829.  
  4830. /*****************************************************************************
  4831.  *
  4832.  *  The given class is not explicitly 'abstract' but it contains/inherits
  4833.  *  the specified abstract method; report the appropriate diagnostic.
  4834.  */
  4835.  
  4836. void                compiler::cmpClsImplAbs(SymDef clsSym, SymDef fncSym)
  4837. {
  4838.     if      (cmpConfig.ccPedantic)
  4839.         cmpErrorQSS(ERRimplAbst, clsSym, fncSym);
  4840.     else
  4841.         cmpWarnSQS (WRNimplAbst, clsSym, fncSym);
  4842.  
  4843.     clsSym->sdIsAbstract = true;
  4844. }
  4845.  
  4846. /*****************************************************************************
  4847.  *
  4848.  *  We've finished declaring a class that includes some interfaces. Check any
  4849.  *  methods that implement interface methods and all that.
  4850.  */
  4851.  
  4852. void                compiler::cmpCheckClsIntf(SymDef clsSym)
  4853. {
  4854.     TypDef          clsTyp;
  4855.     SymDef          baseSym;
  4856.  
  4857.     assert(clsSym->sdSymKind == SYM_CLASS);
  4858.  
  4859.     /* Get hold of the class type and the base class symbol (if any) */
  4860.  
  4861.     clsTyp  = clsSym->sdType;
  4862.  
  4863.     baseSym = NULL;
  4864.     if  (clsTyp->tdClass.tdcBase)
  4865.         baseSym = clsTyp->tdClass.tdcBase->tdClass.tdcSymbol;
  4866.  
  4867.     /* For each interface method see if it's being implemented by the class */
  4868.  
  4869.     for (;;)
  4870.     {
  4871.         /* Check the interfaces of the current class */
  4872.  
  4873.         if  (clsTyp->tdClass.tdcIntf)
  4874.             cmpCheckIntfLst(clsSym, baseSym, clsTyp->tdClass.tdcIntf);
  4875.  
  4876.         /* Continue with the base class, if it has any interfaces */
  4877.  
  4878.         clsTyp = clsTyp->tdClass.tdcBase;
  4879.         if  (!clsTyp)
  4880.             break;
  4881.         if  (!clsTyp->tdClass.tdcHasIntf)
  4882.             break;
  4883.     }
  4884. }
  4885.  
  4886. SymDef              compiler::cmpFindIntfImpl(SymDef    clsSym,
  4887.                                               SymDef    ifcSym,
  4888.                                               SymDef  * impOvlPtr)
  4889. {
  4890.     SymDef          oldSym;
  4891.     SymDef          ovlSym = NULL;
  4892.     SymDef          chkSym = NULL;
  4893.  
  4894.     Ident           name = ifcSym->sdName;
  4895.  
  4896.     if  (hashTab::tokenOfIdent(name) != tkNone)
  4897.     {
  4898.         UNIMPL(!"intfimpl for an operator?! getoutahere!");
  4899.     }
  4900.     else
  4901.     {
  4902.         /* Linear search, eh ? Hmmm .... */
  4903.  
  4904.         for (oldSym = clsSym->sdScope.sdScope.sdsChildList;
  4905.              oldSym;
  4906.              oldSym = oldSym->sdNextInScope)
  4907.         {
  4908.             if  (oldSym->sdName    != name)
  4909.                 continue;
  4910.             if  (oldSym->sdSymKind != SYM_FNC)
  4911.                 continue;
  4912.             if  (oldSym->sdFnc.sdfIntfImpl == false)
  4913.                 continue;
  4914.  
  4915.             ovlSym = oldSym;
  4916.  
  4917.             for (chkSym = oldSym; chkSym; chkSym = chkSym->sdFnc.sdfNextOvl)
  4918.             {
  4919.                 assert(chkSym->sdFnc.sdfIntfImpl);
  4920.                 assert(chkSym->sdNameSpace == NS_HIDE);
  4921.  
  4922.                 if  (chkSym->sdFnc.sdfIntfImpSym == ifcSym)
  4923.                     goto DONE;
  4924.             }
  4925.         }
  4926.     }
  4927.  
  4928. DONE:
  4929.  
  4930.     if  (impOvlPtr)
  4931.         *impOvlPtr = ovlSym;
  4932.  
  4933.     return  chkSym;
  4934. }
  4935.  
  4936. /*****************************************************************************
  4937.  *
  4938.  *  Check the given list of interfaces (and any interfaces they inherit) for
  4939.  *  methods not implemented by the current class. Returns true if t
  4940.  */
  4941.  
  4942. void                compiler::cmpCheckIntfLst(SymDef        clsSym,
  4943.                                               SymDef        baseSym,
  4944.                                               TypList       intfList)
  4945. {
  4946.     SymTab          ourStab = cmpGlobalST;
  4947.  
  4948.     declMods        mfnMods;
  4949.  
  4950.     /* Process all interfaces in the list */
  4951.  
  4952.     while (intfList)
  4953.     {
  4954.         TypDef          intfType = intfList->tlType;
  4955.         SymDef          intfSym;
  4956.  
  4957.         assert(intfType->tdTypeKind        == TYP_CLASS);
  4958.         assert(intfType->tdClass.tdcFlavor == STF_INTF);
  4959.  
  4960.         /* Does the interface inherit any others? */
  4961.  
  4962.         if  (intfType->tdClass.tdcIntf)
  4963.             cmpCheckIntfLst(clsSym, baseSym, intfType->tdClass.tdcIntf);
  4964.  
  4965.         /* Check all the methods in this interface */
  4966.  
  4967.         for (intfSym = intfType->tdClass.tdcSymbol->sdScope.sdScope.sdsChildList;
  4968.              intfSym;
  4969.              intfSym = intfSym->sdNextInScope)
  4970.         {
  4971.             SymDef          intfOvl;
  4972.             SymDef          implSym;
  4973.  
  4974.             if  (intfSym->sdSymKind != SYM_FNC)
  4975.                 continue;
  4976.             if  (intfSym->sdFnc.sdfCtor)
  4977.                 continue;
  4978.  
  4979.             assert(intfSym->sdFnc.sdfOper == OVOP_NONE);
  4980.  
  4981.             /* Look for a matching member in the class we're declaring */
  4982.  
  4983.             implSym = ourStab->stLookupClsSym(intfSym->sdName, clsSym);
  4984.             if  (implSym && implSym->sdSymKind != SYM_FNC)
  4985.                 implSym = NULL;
  4986.  
  4987.             /* Process all overloaded flavors of the interface method */
  4988.  
  4989.             intfOvl = intfSym;
  4990.             do
  4991.             {
  4992.                 SymDef          baseCls;
  4993.                 SymDef          implOvl;
  4994.  
  4995.                 /* Look for a matching method defined in our class */
  4996.  
  4997.                 implOvl = implSym ? ourStab->stFindOvlFnc(implSym, intfOvl->sdType)
  4998.                                   : NULL;
  4999.  
  5000.                 if  (implOvl)
  5001.                 {
  5002.                     /* Mark the symbol as implementing an interface method */
  5003.  
  5004.                     implSym->sdFnc.sdfIsIntfImp = true;
  5005.                     goto NEXT_OVL;
  5006.                 }
  5007.  
  5008.                 /* Let's try the base classes as well */
  5009.  
  5010.                 for (baseCls = clsSym;;)
  5011.                 {
  5012.                     TypDef          baseTyp;
  5013.  
  5014.                     baseTyp = baseCls->sdType->tdClass.tdcBase;
  5015.                     if  (!baseTyp)
  5016.                         break;
  5017.  
  5018.                     assert(baseTyp->tdTypeKind == TYP_CLASS);
  5019.                     baseCls = baseTyp->tdClass.tdcSymbol;
  5020.                     assert(baseCls->sdSymKind  == SYM_CLASS);
  5021.  
  5022.                     implSym = ourStab->stLookupClsSym(intfSym->sdName, baseCls);
  5023.                     if  (implSym && implSym->sdSymKind != SYM_FNC)
  5024.                         continue;
  5025.  
  5026.                     if  (ourStab->stFindOvlFnc(implSym, intfOvl->sdType))
  5027.                         goto NEXT_OVL;
  5028.                 }
  5029.  
  5030.                 /* Last chance - check for a specific interface impl */
  5031.  
  5032.                 if  (cmpFindIntfImpl(clsSym, intfOvl))
  5033.                     goto NEXT_OVL;
  5034.  
  5035.                 /*
  5036.                     The class didn't define a matching method at all, but we
  5037.                     may need to check the base class since we need to detect
  5038.                     whether the class leaves any intf methods unimplemented.
  5039.  
  5040.                     If we already know that the class is abstract, we won't
  5041.                     bother with the check, of course.
  5042.                  */
  5043.  
  5044.                 if  (!clsSym->sdIsAbstract)
  5045.                 {
  5046.                     if  (baseSym)
  5047.                     {
  5048.                         /* See if a base class implements this method */
  5049.  
  5050.                         implOvl = ourStab->stFindInBase(intfOvl, baseSym);
  5051.                         if  (implOvl)
  5052.                         {
  5053.                             if  (ourStab->stFindOvlFnc(implOvl, intfOvl->sdType))
  5054.                                 goto NEXT_OVL;
  5055.                         }
  5056.                     }
  5057.  
  5058.                     /* This interface method isn't implemented by the class */
  5059.  
  5060.                     cmpClsImplAbs(clsSym, intfOvl);
  5061.                 }
  5062.  
  5063.                 /* Add a matching abstract method to the class */
  5064.  
  5065.                 mfnMods.dmAcc = ACL_PUBLIC;
  5066.                 mfnMods.dmMod = DM_ABSTRACT|DM_VIRTUAL;
  5067.  
  5068.                 implSym = cmpDeclFuncMem(clsSym, mfnMods, intfOvl->sdType, intfOvl->sdName);
  5069. //              printf("Pulling intf method: '%s'\n", cmpGlobalST->stTypeName(implSym->sdType, implSym, NULL, NULL, true));
  5070.                 implSym->sdFnc.sdfVirtual = true;
  5071.  
  5072.                 assert(implSym->sdIsAbstract);
  5073.                 assert(implSym->sdAccessLevel == ACL_PUBLIC);
  5074.  
  5075.             NEXT_OVL:
  5076.  
  5077.                 intfOvl = intfOvl->sdFnc.sdfNextOvl;
  5078.             }
  5079.             while (intfOvl);
  5080.         }
  5081.  
  5082.         intfList = intfList->tlNext;
  5083.     }
  5084. }
  5085.  
  5086. /*****************************************************************************
  5087.  *
  5088.  *  Declare the default constructor for the given class.
  5089.  */
  5090.  
  5091. void                compiler::cmpDeclDefCtor(SymDef clsSym)
  5092. {
  5093.     declMods        ctorMod;
  5094.     SymDef          ctorSym;
  5095.  
  5096.     // UNDONE: unmanaged classes may need a ctor as well!
  5097.  
  5098.     clearDeclMods(&ctorMod);
  5099.  
  5100.     ctorSym = cmpDeclFuncMem(clsSym, ctorMod, cmpTypeVoidFnc, clsSym->sdName);
  5101.     if  (ctorSym)
  5102.     {
  5103.         ctorSym->sdFnc.sdfCtor = true;
  5104.         ctorSym->sdIsImplicit  = true;
  5105.         ctorSym->sdIsDefined   = true;
  5106.         ctorSym->sdAccessLevel = ACL_PUBLIC;    // ISSUE: is this correct?
  5107.  
  5108. //      printf("dcl ctor %08X for '%s'\n", ctorSym, clsSym->sdSpelling());
  5109.  
  5110.         ctorSym->sdSrcDefList  = cmpGlobalST->stRecordMemSrcDef(clsSym->sdName,
  5111.                                                                 NULL,
  5112.                                                                 cmpCurComp,
  5113.                                                                 cmpCurUses,
  5114.                                                                 NULL,
  5115.                                                                 0);
  5116.     }
  5117. }
  5118.  
  5119. /*****************************************************************************
  5120.  *
  5121.  *  Bring the given class to "declared" state.
  5122.  */
  5123.  
  5124. void                compiler::cmpDeclClass(SymDef clsSym, bool noCnsEval)
  5125. {
  5126.     SymTab          ourSymTab  = cmpGlobalST;
  5127.     Parser          ourParser  = cmpParser;
  5128.     Scanner         ourScanner = cmpScanner;
  5129.  
  5130.     unsigned        saveRec;
  5131.  
  5132.     TypDef          clsTyp;
  5133.     DefList         clsDef;
  5134.     ExtList         clsMem;
  5135.  
  5136.     bool            tagged;
  5137.     SymDef          tagSym;
  5138.  
  5139.     bool            isIntf;
  5140.  
  5141.     TypDef          baseCls;
  5142.     unsigned        nextVtbl;
  5143.     bool            hasVirts;
  5144.     bool            hasCtors;
  5145.     bool            hadOvlds;
  5146.  
  5147.     bool            hadMemInit;
  5148.  
  5149.     ExtList         constList;
  5150.     ExtList         constLast;
  5151.  
  5152.     unsigned        dclSkip = 0;
  5153.  
  5154.     bool            rest = false;
  5155.     parserState     save;
  5156.  
  5157.     assert(clsSym && clsSym->sdSymKind == SYM_CLASS);
  5158.  
  5159.     /* If we're already at the desired compile-state, we're done */
  5160.  
  5161.     if  (clsSym->sdCompileState >= CS_DECLARED)
  5162.     {
  5163.         /* Does the class have any deferred initializers? */
  5164.  
  5165.         if  (clsSym->sdClass.sdcDeferInit && !cmpDeclClassRec)
  5166.         {
  5167.             IniList         init = cmpDeferCnsList;
  5168.             IniList         last = NULL;
  5169.  
  5170.             NO_WAY(!"this never seems to be reached -- until now, that is");
  5171.  
  5172.             // LAME: linear search
  5173.  
  5174.             while (init->ilCls != clsSym)
  5175.             {
  5176.                 last = init;
  5177.                 init = init->ilNext;
  5178.                 assert(init);
  5179.             }
  5180.  
  5181.             if  (last)
  5182.                 last->ilNext    = init->ilNext;
  5183.             else
  5184.                 cmpDeferCnsList = init->ilNext;
  5185.  
  5186.             cmpEvalMemInits(NULL, NULL, false, init);
  5187.         }
  5188.  
  5189.         return;
  5190.     }
  5191.  
  5192.     /* Detect amd report recursive death */
  5193.  
  5194.     if  (clsSym->sdCompileState == CS_DECLSOON)
  5195.     {
  5196.         // UNDONE: set the source position for the error message
  5197.  
  5198.         cmpError(ERRcircDep, clsSym);
  5199.         clsSym->sdCompileState = CS_DECLARED;
  5200.         return;
  5201.     }
  5202.  
  5203.     if  (clsSym->sdIsImport)
  5204.     {
  5205.         cycleCounterPause();
  5206.         clsSym->sdClass.sdcMDimporter->MDimportClss(0, clsSym, 0, true);
  5207.         cycleCounterResume();
  5208.         return;
  5209.     }
  5210.  
  5211.     /* Until we get there, we're on our way there */
  5212.  
  5213.     clsSym->sdCompileState = CS_DECLSOON;
  5214.  
  5215. #ifdef DEBUG
  5216.     if  (cmpConfig.ccVerbose >= 2) printf("Declare/1 class '%s'\n", clsSym->sdSpelling());
  5217. #endif
  5218.  
  5219.     cmpCurScp  = NULL;
  5220.     cmpCurCls  = clsSym;
  5221.     cmpCurNS   = ourSymTab->stNamespOfSym(clsSym);
  5222.     cmpCurST   = ourSymTab;
  5223.  
  5224.     hasVirts   = false;
  5225.     hasCtors   = false;
  5226.     hadOvlds   = false;
  5227.  
  5228.     constList  =
  5229.     constLast  = NULL;
  5230.  
  5231.     hadMemInit = false;
  5232.  
  5233.     /*
  5234.         If we've been invoked recursively, we'll have to defer processing
  5235.         of initializers, lest we get into an invalid recursive situation.
  5236.      */
  5237.  
  5238.     saveRec = cmpDeclClassRec++;
  5239.     if  (saveRec)
  5240.         noCnsEval = true;
  5241.  
  5242.     /* Is this an instance of a generic class ? */
  5243.  
  5244.     if  (clsSym->sdClass.sdcSpecific)
  5245.     {
  5246.         cmpDeclInstType(clsSym);
  5247.         return;
  5248.     }
  5249.  
  5250.     /* Assume that we have a plain old data type until proven otherwise */
  5251.  
  5252.     /* The following loops over all the definition entries for the symbol */
  5253.  
  5254.     clsDef = clsSym->sdSrcDefList;
  5255.     if  (!clsDef)
  5256.         goto DONE_DEF;
  5257.  
  5258. LOOP_DEF:
  5259.  
  5260.     accessLevels    acc;
  5261.     TypDef          baseTp;
  5262.     declMods        memMod;
  5263.  
  5264.     SymDef          clsComp;
  5265.     UseList         clsUses;
  5266.  
  5267.     bool            memCond;
  5268.     bool            memDepr;
  5269.     Ident           memName;
  5270.     TypDef          memType;
  5271.  
  5272.     __int32         tagVal;
  5273.     bool            tagDef;
  5274.  
  5275.     bool            isCtor;
  5276.  
  5277.     bool            oldStyleDecl;
  5278.  
  5279.     SymXinfo        xtraList;
  5280.  
  5281. //  if  (!strcmp(clsSym->sdSpelling(), "<class name here>")) forceDebugBreak();
  5282.  
  5283.     /* Get hold of the class type */
  5284.  
  5285.     clsTyp = clsSym->sdTypeGet(); assert(clsTyp && clsTyp->tdClass.tdcSymbol == clsSym);
  5286.  
  5287.     /* Do we have a definition of the class? */
  5288.  
  5289.     if  (!clsDef->dlHasDef)
  5290.         goto NEXT_DEF;
  5291.  
  5292.     /* Tell everyone which compilation unit the source we're processing belongs to */
  5293.  
  5294.     cmpCurComp = clsComp = clsDef->dlComp;
  5295.  
  5296.     /* Prepare in case we have to report any diagnostics */
  5297.  
  5298.     cmpSetErrPos(&clsDef->dlDef, clsDef->dlComp);
  5299.  
  5300.     /* Bind any "using" declarations the class may need */
  5301.  
  5302.     clsUses = clsDef->dlUses; cmpBindUseList(clsUses);
  5303.  
  5304.     /* Mark the class type as defined */
  5305.  
  5306.     clsSym->sdIsDefined = true;
  5307.  
  5308.     /* What kind of a beast do we have ? */
  5309.  
  5310.     isIntf = false;
  5311.  
  5312.     switch (clsSym->sdClass.sdcFlavor)
  5313.     {
  5314.     default:
  5315.         break;
  5316.  
  5317.     case STF_UNION:
  5318.     case STF_STRUCT:
  5319.         if  (clsSym->sdIsManaged)
  5320.             clsSym->sdIsSealed = true;
  5321.         break;
  5322.  
  5323.     case STF_INTF:
  5324.  
  5325.         isIntf = true;
  5326.  
  5327.         /* Interfaces are abstract by default */
  5328.  
  5329.         clsSym->sdIsAbstract = true;
  5330.         break;
  5331.     }
  5332.  
  5333.     /* Is this a delegate, by any chance? */
  5334.  
  5335.     if  (clsSym->sdClass.sdcFlavor == STF_DELEGATE && !clsSym->sdClass.sdcBuiltin)
  5336.     {
  5337.         cmpDeclDelegate(clsDef, clsSym, ACL_DEFAULT);
  5338.         goto RET;
  5339.     }
  5340.  
  5341.     /* Is this an old-style file-scope class? */
  5342.  
  5343.     oldStyleDecl = clsSym->sdClass.sdcOldStyle = (bool)clsDef->dlOldStyle;
  5344.  
  5345.     /* Are we processing a tagged union? */
  5346.  
  5347.     tagged = clsSym->sdClass.sdcTagdUnion;
  5348.  
  5349.     /* If this is a generic class, we better read its "header" section */
  5350.  
  5351.     assert(clsSym->sdClass.sdcGeneric == false || clsDef->dlHasBase);
  5352.  
  5353.     /* First process any base class specifications */
  5354.  
  5355.     if  (clsDef->dlHasBase)
  5356.     {
  5357.         TypList         intf;
  5358.  
  5359.         assert(rest == false);
  5360.  
  5361.         /* Plain old data types don't have a base */
  5362.  
  5363.         /* Start reading from the class name and skip over it */
  5364.  
  5365.         cmpParser->parsePrepText(&clsDef->dlDef, clsDef->dlComp, save);
  5366.  
  5367.         /* Remember that we've started reading from a saved text section */
  5368.  
  5369.         rest = true;
  5370.  
  5371.         /* Check for various things that may precede the class itself */
  5372.  
  5373.         for (;;)
  5374.         {
  5375.             switch (ourScanner->scanTok.tok)
  5376.             {
  5377.                 SymXinfo        linkDesc;
  5378.  
  5379.                 AtComment       atcList;
  5380.  
  5381.                 unsigned        attrMask;
  5382.                 genericBuff     attrAddr;
  5383.                 size_t          attrSize;
  5384.                 SymDef          attrCtor;
  5385.  
  5386.             case tkLBrack:
  5387.                 linkDesc = ourParser->parseBrackAttr(true, ATTR_MASK_SYS_STRUCT|ATTR_MASK_GUID);
  5388.                 clsSym->sdClass.sdcExtraInfo = cmpAddXtraInfo(clsSym->sdClass.sdcExtraInfo,
  5389.                                                               linkDesc);
  5390.                 clsSym->sdClass.sdcMarshInfo = true;
  5391.                 continue;
  5392.  
  5393.             case tkCAPABILITY:
  5394.  
  5395.                 clsSym->sdClass.sdcExtraInfo = cmpAddXtraInfo(clsSym->sdClass.sdcExtraInfo,
  5396.                                                               ourParser->parseCapability(true));
  5397.                 continue;
  5398.  
  5399.             case tkPERMISSION:
  5400.  
  5401.                 clsSym->sdClass.sdcExtraInfo = cmpAddXtraInfo(clsSym->sdClass.sdcExtraInfo,
  5402.                                                               ourParser->parsePermission(true));
  5403.                 continue;
  5404.  
  5405.             case tkAtComment:
  5406.  
  5407.                 for (atcList = ourScanner->scanTok.atComm.tokAtcList;
  5408.                      atcList;
  5409.                      atcList = atcList->atcNext)
  5410.                 {
  5411.                     switch (atcList->atcFlavor)
  5412.                     {
  5413.                     case AC_COM_CLASS:
  5414.                         break;
  5415.  
  5416.                     case AC_DLL_STRUCT:
  5417.  
  5418.                         clsSym->sdClass.sdcMarshInfo = true;
  5419.                         clsSym->sdClass.sdcExtraInfo = cmpAddXtraInfo(clsSym->sdClass.sdcExtraInfo,
  5420.                                                                       atcList);
  5421.                         break;
  5422.  
  5423.                     case AC_DLL_IMPORT:
  5424.  
  5425.                         if  (atcList->atcInfo.atcImpLink->ldDLLname == NULL ||
  5426.                              atcList->atcInfo.atcImpLink->ldSYMname != NULL)
  5427.                         {
  5428.                             cmpError(ERRclsImpName);
  5429.                         }
  5430.  
  5431.                         // Fall through ....
  5432.  
  5433.                     case AC_COM_INTF:
  5434.                     case AC_COM_REGISTER:
  5435.                         clsSym->sdClass.sdcExtraInfo = cmpAddXtraInfo(clsSym->sdClass.sdcExtraInfo,
  5436.                                                                       atcList);
  5437.                         break;
  5438.  
  5439.                     case AC_DEPRECATED:
  5440.                         clsSym->sdIsDeprecated = true;
  5441.                         break;
  5442.  
  5443.                     default:
  5444.                         cmpError(ERRbadAtCmPlc);
  5445.                         break;
  5446.                     }
  5447.  
  5448.                     ourScanner->scan();
  5449.                 }
  5450.  
  5451.                 continue;
  5452.  
  5453.             case tkATTRIBUTE:
  5454.  
  5455.                 /* Check for the "class __attribute(AttributeTargets.xxx)" case */
  5456.  
  5457.                 if  (ourScanner->scanLookAhead() == tkLParen)
  5458.                     break;
  5459.  
  5460.                  /* Parse the attribute blob */
  5461.  
  5462.                 attrCtor = cmpParser->parseAttribute((clsSym->sdClass.sdcFlavor == STF_INTF) ? ATGT_Interfaces : ATGT_Classes,
  5463.                                                      attrMask,
  5464.                                                      attrAddr,
  5465.                                                      attrSize);
  5466.  
  5467.                 /* Add the attribute to the list of "extra info" */
  5468.  
  5469.                 if  (attrSize)
  5470.                 {
  5471.                     clsSym->sdClass.sdcExtraInfo = cmpAddXtraInfo(clsSym->sdClass.sdcExtraInfo,
  5472.                                                                   attrCtor,
  5473.                                                                   attrMask,
  5474.                                                                   attrSize,
  5475.                                                                   attrAddr);
  5476.  
  5477.                     if  (attrMask)
  5478.                     {
  5479.                         clsSym->sdClass.sdcAttribute = true;
  5480.  
  5481.                         /* Did the ctor arglist include the "allowDups" value ? */
  5482.  
  5483.                         if  (attrSize >= 8)
  5484.                         {
  5485.                             /*
  5486.                                 The following is utterly hideous, but then
  5487.                                 so is the feature itself, isn't it?
  5488.                              */
  5489.  
  5490.                             if  (((BYTE*)attrAddr)[6])
  5491.                                 clsSym->sdClass.sdcAttrDupOK = true;
  5492.                         }
  5493.                     }
  5494.                 }
  5495.  
  5496.                 continue;
  5497.  
  5498.             default:
  5499.  
  5500.                 /* If we have "class", swallow it */
  5501.  
  5502.                 if  (ourScanner->scanTok.tok == tkCLASS)
  5503.                     ourScanner->scan();
  5504.  
  5505.                 break;
  5506.             }
  5507.             break;
  5508.         }
  5509.  
  5510.         if  (ourScanner->scanTok.tok == tkLParen)
  5511.         {
  5512.             Ident       tagName;
  5513.             SymDef      parent;
  5514.  
  5515.             /* This must be a tagged union */
  5516.  
  5517.             assert(tagged);
  5518.  
  5519.             /* Get hold of the tag member name and make sure it's kosher */
  5520.  
  5521.             ourScanner->scan(); assert(ourScanner->scanTok.tok == tkID);
  5522.  
  5523.             tagName = ourScanner->scanTok.id.tokIdent;
  5524.  
  5525.             /* Look for a member with a matching name */
  5526.  
  5527.             for (parent = clsSym->sdParent;;)
  5528.             {
  5529.                 assert(parent->sdSymKind == SYM_CLASS);
  5530.  
  5531.                 tagSym = cmpCurST->stLookupClsSym(tagName, parent);
  5532.                 if  (tagSym)
  5533.                     break;
  5534.  
  5535.                 if  (!symTab::stIsAnonUnion(parent))
  5536.                     break;
  5537.  
  5538.                 parent = parent->sdParent;
  5539.             }
  5540.  
  5541.             if  (!tagSym || tagSym->sdSymKind != SYM_VAR
  5542.                          || tagSym->sdIsStatic)
  5543.             {
  5544.                 /* There is no suitable data member with a matching name */
  5545.  
  5546.                 cmpError(ERRbadUTag, tagName);
  5547.             }
  5548.             else
  5549.             {
  5550.                 var_types           vtp = tagSym->sdType->tdTypeKindGet();
  5551.  
  5552.                 /* Make sure the member has an integer/enum/bool type */
  5553.  
  5554.                 if  (!varTypeIsIntegral(vtp))
  5555.                 {
  5556.                     cmpError(ERRbadUTag, tagName);
  5557.                 }
  5558.                 else
  5559.                 {
  5560.                     /* Everything looks good, record the tag symbol */
  5561.  
  5562.                     clsSym->sdClass.sdcExtraInfo = cmpAddXtraInfo(clsSym->sdClass.sdcExtraInfo, tagSym, XI_UNION_TAG);
  5563.                 }
  5564.             }
  5565.  
  5566.             /* Make sure the closing ")" is present */
  5567.  
  5568.             ourScanner->scan(); assert(ourScanner->scanTok.tok == tkRParen);
  5569.             ourScanner->scan();
  5570.         }
  5571.  
  5572.         for (;;)
  5573.         {
  5574.             TypDef          type;
  5575.  
  5576.             /* Do we have a generic class formal argument list? */
  5577.  
  5578.             if  (ourScanner->scanTok.tok == tkLT)
  5579.             {
  5580.                 GenArgDsc       genArgLst;
  5581.                 unsigned        genArgNum;
  5582.  
  5583.                 assert(clsSym->sdClass.sdcGeneric);
  5584.  
  5585.                 /* Pass 1: create a member symbol + type for each formal */
  5586.  
  5587.                 for (genArgLst = clsSym->sdClass.sdcArgLst, genArgNum = 1;
  5588.                      genArgLst;
  5589.                      genArgLst = genArgLst->gaNext        , genArgNum++)
  5590.                 {
  5591.                     GenArgDscF      paramDesc = (GenArgDscF)genArgLst;
  5592.                     Ident           paramName = paramDesc->gaName;
  5593.                     SymDef          paramSym;
  5594.  
  5595.                     assert(genArgLst->gaBound == false);
  5596.  
  5597.                     /* Declare a member symbol for the parameter */
  5598.  
  5599.                     paramSym = ourSymTab->stLookupScpSym(paramName, clsSym);
  5600.                     if  (paramSym)
  5601.                     {
  5602.                         cmpRedefSymErr(paramSym, ERRredefMem);
  5603.                         paramDesc->gaMsym = NULL;
  5604.                         continue;
  5605.                     }
  5606.  
  5607.                     paramSym = paramDesc->gaMsym = ourSymTab->stDeclareSym(paramName,
  5608.                                                                            SYM_CLASS,
  5609.                                                                            NS_NORM,
  5610.                                                                            clsSym);
  5611.  
  5612.                     paramSym->sdAccessLevel     = ACL_PRIVATE;
  5613.                     paramSym->sdIsManaged       = true;
  5614.                     paramSym->sdClass.sdcFlavor = STF_GENARG;
  5615.                     paramSym->sdClass.sdcGenArg = genArgNum;
  5616.                     paramSym->sdCompileState    = CS_DECLARED;
  5617.  
  5618. //                  printf("Generic arg [%08X] '%s'\n", paramSym, paramSym->sdSpelling());
  5619.  
  5620.                     /* Make sure we create the class type */
  5621.  
  5622.                     paramSym->sdTypeGet()->tdIsGenArg = true;
  5623.  
  5624.                     /* Set the default required base class / interface list */
  5625.  
  5626.                     paramDesc->gaBase = NULL; // cmpClassObject->sdType;
  5627.                     paramDesc->gaIntf = NULL;
  5628.                 }
  5629.  
  5630.                 /* Pass 2: process the formal argument bounds */
  5631.  
  5632.                 assert(ourScanner->scanTok.tok == tkLT);
  5633.  
  5634.                 for (genArgLst = clsSym->sdClass.sdcArgLst;
  5635.                      genArgLst;
  5636.                      genArgLst = genArgLst->gaNext)
  5637.                 {
  5638.                     GenArgDscF      paramDesc = (GenArgDscF)genArgLst;
  5639.                     SymDef          paramSym  = paramDesc->gaMsym;
  5640.                     TypDef          paramType = paramSym->sdType;
  5641.  
  5642.                     assert(genArgLst->gaBound == false);
  5643.  
  5644.                     /* The argument symbol is NULL if it had an error earlier */
  5645.  
  5646.                     if  (paramSym)
  5647.                     {
  5648.                         ourScanner->scan(); assert(ourScanner->scanTok.tok == tkCLASS);
  5649.                         ourScanner->scan(); assert(ourScanner->scanTok.tok == tkID);
  5650.                         ourScanner->scan();
  5651.  
  5652.                         if  (ourScanner->scanTok.tok == tkColon)
  5653.                         {
  5654.                             UNIMPL(!"process generic arg - base");
  5655.                         }
  5656.  
  5657.                         if  (ourScanner->scanTok.tok == tkIMPLEMENTS)
  5658.                         {
  5659.                             UNIMPL(!"process generic arg - intf");
  5660.                         }
  5661.  
  5662.                         if  (ourScanner->scanTok.tok == tkINCLUDES)
  5663.                         {
  5664.                             UNIMPL(!"process generic arg - incl");
  5665.                         }
  5666.                     }
  5667.                     else
  5668.                     {
  5669.                         UNIMPL(!"skip over erroneuos generic arg");
  5670.                     }
  5671.  
  5672.                     paramType->tdClass.tdcBase = paramDesc->gaBase;
  5673.                     paramType->tdClass.tdcIntf = paramDesc->gaIntf;
  5674.  
  5675.                     /* Make sure things are still in synch */
  5676.  
  5677.                     assert(ourScanner->scanTok.tok == tkComma && genArgLst->gaNext != NULL ||
  5678.                            ourScanner->scanTok.tok == tkGT    && genArgLst->gaNext == NULL);
  5679.                 }
  5680.  
  5681.                 assert(ourScanner->scanTok.tok == tkGT); ourScanner->scan();
  5682.             }
  5683.  
  5684.             /* Is there are an "attribute" modifier? */
  5685.  
  5686.             if  (ourScanner->scanTok.tok == tkATTRIBUTE)
  5687.             {
  5688.                 constVal        cval;
  5689.  
  5690.                 /* Remember that this class has been marked as an attribute */
  5691.  
  5692.                 clsSym->sdClass.sdcAttribute = true;
  5693.  
  5694.                 if  (ourScanner->scan() != tkLParen)
  5695.                     continue;
  5696.  
  5697.                 cmpParser->parseConstExpr(cval);
  5698.                 continue;
  5699.             }
  5700.  
  5701.             /* Check for context crap */
  5702.  
  5703.             if  (ourScanner->scanTok.tok == tkAPPDOMAIN)
  5704.             {
  5705.                 clsTyp->tdClass.tdcContext = 1;
  5706.                 ourScanner->scan();
  5707.                 continue;
  5708.             }
  5709.  
  5710.             if  (ourScanner->scanTok.tok == tkCONTEXTFUL)
  5711.             {
  5712.                 clsTyp->tdClass.tdcContext = 2;
  5713.                 ourScanner->scan();
  5714.                 continue;
  5715.             }
  5716.  
  5717.             /* Is there a base class? */
  5718.  
  5719.             if  (ourScanner->scanTok.tok == tkColon)
  5720.             {
  5721.                 if  (isIntf)
  5722.                     goto INTFLIST;
  5723.  
  5724.                 /* Swallow the ":" and parse the base class */
  5725.  
  5726.                 if  (ourScanner->scan() == tkPUBLIC)
  5727.                      ourScanner->scan();
  5728.  
  5729.                 type = cmpGetClassSpec(false);
  5730.                 if  (type)
  5731.                 {
  5732.                     assert(type->tdTypeKind == TYP_CLASS);
  5733.  
  5734.                     clsTyp->tdClass.tdcBase = type;
  5735.  
  5736.                     /* Make sure this inheritance is legal */
  5737.  
  5738.                     if  (type->tdIsManaged != clsTyp->tdIsManaged)
  5739.                         cmpError(ERRxMgdInh, type);
  5740.  
  5741.                     /* Managed struct can't inherit from anything */
  5742.  
  5743.                     if  (clsTyp->tdIsManaged && clsTyp->tdClass.tdcFlavor == STF_STRUCT)
  5744.                         cmpError(ERRstrInhCls, type);
  5745.  
  5746.                     /* Inherit context crap by default */
  5747.  
  5748.                     if  (!clsTyp->tdClass.tdcContext)
  5749.                         clsTyp->tdClass.tdcContext = type->tdClass.tdcContext;
  5750.  
  5751.                     /* Make sure context stuff agrees with base */
  5752.  
  5753.                     if  (clsTyp->tdClass.tdcContext != type->tdClass.tdcContext)
  5754.                     {
  5755.                         SymDef      baseCls = type->tdClass.tdcSymbol;
  5756.  
  5757.                         /* Absurd hack for the BCL */
  5758.  
  5759.                         if  ( clsSym->sdParent == cmpNmSpcSystem &&
  5760.                              baseCls->sdParent == cmpNmSpcSystem
  5761.                                         &&
  5762.                              !strcmp(baseCls->sdSpelling(), "MarshalByRefObject") &&
  5763.                              !strcmp( clsSym->sdSpelling(), "ContextBoundObject"))
  5764.                         {
  5765.                             // Allow this as a special case
  5766.                         }
  5767.                         else
  5768.                             cmpError(ERRxCtxInh, type);
  5769.                     }
  5770.                 }
  5771.  
  5772.                 if  (ourScanner->scanTok.tok != tkINCLUDES &&
  5773.                      ourScanner->scanTok.tok != tkIMPLEMENTS)
  5774.                     break;
  5775.             }
  5776.  
  5777.             /* Is there an interface list? */
  5778.  
  5779.             if  (ourScanner->scanTok.tok == tkINCLUDES ||
  5780.                  ourScanner->scanTok.tok == tkIMPLEMENTS)
  5781.             {
  5782.                 TypList         intfList;
  5783.                 TypList         intfLast;
  5784.  
  5785.             INTFLIST:
  5786.  
  5787.                 if  (!clsSym->sdIsManaged)
  5788.                     cmpError(ERRunmIntf);
  5789.  
  5790.                 /* Swallow the "includes" and parse the interface list */
  5791.  
  5792.                 intfList =
  5793.                 intfLast = NULL;
  5794.  
  5795.                 do
  5796.                 {
  5797.                     TypDef          type;
  5798.  
  5799.                     ourScanner->scan();
  5800.  
  5801.                     /* Get the next interface and add it to the list */
  5802.  
  5803.                     type = cmpGetClassSpec(true);
  5804.                     if  (type)
  5805.                         intfList = ourSymTab->stAddIntfList(type, intfList, &intfLast);
  5806.                 }
  5807.                 while (ourScanner->scanTok.tok == tkComma);
  5808.  
  5809.                 clsTyp->tdClass.tdcIntf    = intfList;
  5810.                 clsTyp->tdClass.tdcHasIntf = true;
  5811.  
  5812.                 if  (ourScanner->scanTok.tok != tkColon)
  5813.                     break;
  5814.             }
  5815.  
  5816.             if  (ourScanner->scanTok.tok == tkLCurly)
  5817.                 break;
  5818.  
  5819.             assert(ourScanner->scanTok.tok != tkEOF); ourScanner->scan();
  5820.         }
  5821.  
  5822.         /* We're done reading source text from the class base */
  5823.  
  5824.         assert(rest); cmpParser->parseDoneText(save); rest = false;
  5825.  
  5826.         /* Make sure any base classes / interfaces are declared */
  5827.  
  5828.         if  (clsTyp->tdClass.tdcBase)
  5829.         {
  5830.             SymDef          baseSym = clsTyp->tdClass.tdcBase->tdClass.tdcSymbol;
  5831.  
  5832.             cmpDeclClsNoCns(baseSym);
  5833.  
  5834.             if  (baseSym->sdIsSealed)
  5835.                 cmpError(ERRsealedInh, baseSym);
  5836.         }
  5837.  
  5838.         for (intf = clsTyp->tdClass.tdcIntf; intf; intf = intf->tlNext)
  5839.             cmpDeclClsNoCns(intf->tlType->tdClass.tdcSymbol);
  5840.     }
  5841.     else
  5842.     {
  5843.         assert(tagged == false);
  5844.     }
  5845.  
  5846. //  printf("Class ctx = [%u] '%s'\n", clsTyp->tdClass.tdcContext, clsSym->sdSpelling());
  5847.  
  5848.     /* Record the base class */
  5849.  
  5850.     baseCls = clsTyp->tdClass.tdcBase;
  5851.  
  5852.     if  (clsTyp->tdIsManaged)
  5853.     {
  5854.         /* The default base of a managed class is "Object" */
  5855.  
  5856.         if  (!baseCls)
  5857.         {
  5858.             cmpFindObjectType();
  5859.  
  5860.             /* Special case: "Object" doesn't have a base class */
  5861.  
  5862.             if  (clsTyp == cmpClassObject->sdType)
  5863.                 goto DONE_BASE;
  5864.  
  5865.             baseCls = clsTyp->tdClass.tdcBase = cmpClassObject->sdType;
  5866.         }
  5867.  
  5868.         clsTyp->tdClass.tdcHasIntf |= baseCls->tdClass.tdcHasIntf;
  5869.     }
  5870.  
  5871. DONE_BASE:
  5872.  
  5873. #ifdef DEBUG
  5874.     if  (cmpConfig.ccVerbose >= 2) printf("Declare/2 class '%s'\n", clsSym->sdSpelling());
  5875. #endif
  5876.  
  5877.     /* Determine where we'll be adding virtuals */
  5878.  
  5879.     nextVtbl = baseCls ? baseCls->tdClass.tdcSymbol->sdClass.sdcVirtCnt
  5880.                        : 0;
  5881.  
  5882.     /* Determine default management mode */
  5883.  
  5884.     cmpManagedMode = clsSym->sdIsManaged;
  5885.  
  5886.     /* No access specifiers have been found yet */
  5887.  
  5888.     acc = (oldStyleDecl || isIntf) ? ACL_PUBLIC
  5889.                                    : ACL_DEFAULT;
  5890.  
  5891.     /* The loop over members starts here */
  5892.  
  5893.     clsMem = clsSym->sdClass.sdcMemDefList;
  5894.     if  (!clsMem)
  5895.         goto NEXT_DEF;
  5896.  
  5897. LOOP_MEM:
  5898.  
  5899.     xtraList = NULL;
  5900.  
  5901.     if  (clsMem->mlSym)
  5902.     {
  5903.         SymDef          memSym = clsMem->mlSym;
  5904.  
  5905.         /* Is this a delegate member? */
  5906.  
  5907.         if  (memSym->sdSymKind == SYM_CLASS &&
  5908.              memSym->sdClass.sdcFlavor == STF_DELEGATE)
  5909.         {
  5910.             cmpDeclDelegate(clsMem, memSym, acc);
  5911.             goto DONE_MEM;
  5912.         }
  5913.  
  5914.         /* Is this a property accessor method? */
  5915.  
  5916.         if  (memSym->sdSymKind == SYM_FNC && memSym->sdFnc.sdfProperty)
  5917.             goto DONE_MEM;
  5918.  
  5919.         /* Is the member a nested anonymous union? */
  5920.  
  5921.         if  (clsMem->dlAnonUnion)
  5922.         {
  5923.             SymDef          aumSym;
  5924.             Ident           memName = clsMem->mlName;
  5925.  
  5926.             assert(memSym->sdSymKind == SYM_CLASS);
  5927.  
  5928.             assert(memSym->        sdClass.sdcAnonUnion);
  5929.             assert(memSym->sdType->tdClass.tdcAnonUnion);
  5930.  
  5931.             /* Recursively process the anonymous union type definition */
  5932.  
  5933.             cmpDeclClass(memSym);
  5934.  
  5935.             initDeclMods(&memMod, acc);
  5936.  
  5937.             /* Is this really an anonymous union? */
  5938.  
  5939.             if  (hashTab::hashIsIdHidden(memName))
  5940.             {
  5941.                 SymDef          tmpSym;
  5942.  
  5943.                 /* Declare a data member to hold the union */
  5944.  
  5945.                 aumSym = cmpDeclDataMem(clsSym, memMod, memSym->sdType, memName);
  5946.  
  5947.                 /* Make sure the anonymous union members aren't redefined */
  5948.  
  5949.                 assert(clsSym->sdSymKind == SYM_CLASS);
  5950.                 assert(memSym->sdSymKind == SYM_CLASS);
  5951.                 assert(memSym->sdParent  == clsSym);
  5952.  
  5953.                 for (tmpSym = memSym->sdScope.sdScope.sdsChildList;
  5954.                      tmpSym;
  5955.                      tmpSym = tmpSym->sdNextInScope)
  5956.                 {
  5957.                     Ident               name = tmpSym->sdName;
  5958.  
  5959.                     if  (tmpSym->sdSymKind != SYM_VAR)
  5960.                         continue;
  5961.  
  5962.                     /* Mark the member as belonging to an anonymoys union */
  5963.  
  5964.                     tmpSym->sdVar.sdvAnonUnion = true;
  5965.  
  5966.                     /* Make sure the enclosing class doesn't have a member with the same name */
  5967.  
  5968.                     if  (ourSymTab->stLookupScpSym(name, clsSym))
  5969.                         cmpError(ERRredefAnMem, name);
  5970.                 }
  5971.  
  5972.                 /* Record the member that holds the value in the union type */
  5973.  
  5974.                 memSym->sdClass.sdcExtraInfo = cmpAddXtraInfo(memSym->sdClass.sdcExtraInfo,
  5975.                                                               aumSym,
  5976.                                                               XI_UNION_MEM);
  5977.             }
  5978.             else
  5979.             {
  5980.                 /* There is a member name after all, so it's not an anonymous union */
  5981.  
  5982.                 memSym->        sdClass.sdcAnonUnion = false;
  5983.                 memSym->sdType->tdClass.tdcAnonUnion = false;
  5984.  
  5985.                 /* Declare a data member to hold the union */
  5986.  
  5987.                 aumSym = cmpDeclDataMem(clsSym, memMod, memSym->sdType, memName);
  5988.             }
  5989.  
  5990.             goto DONE_MEM;
  5991.         }
  5992.     }
  5993.  
  5994.     /* Start reading source text from the definition */
  5995.  
  5996.     assert(rest == false);
  5997.     cmpParser->parsePrepText(&clsMem->dlDef, clsMem->dlComp, save);
  5998.     rest = true;
  5999.  
  6000.     /* We might have to skip intervening declarators */
  6001.  
  6002.     dclSkip = clsMem->dlDeclSkip;
  6003.  
  6004.     /* The member isn't conditional or deprecated (etc) until proven so */
  6005.  
  6006.     memCond = memDepr = false;
  6007.  
  6008.     /* Note whether the member is a constructor */
  6009.  
  6010.     isCtor  = clsMem->dlIsCtor;
  6011.  
  6012.     /* Parse any leading modifiers */
  6013.  
  6014.     switch (ourScanner->scanTok.tok)
  6015.     {
  6016.         constVal        cval;
  6017.         bool            hadMods;
  6018.         SymXinfo        linkDesc;
  6019.  
  6020.     case tkEXTERN:
  6021.  
  6022.         /* Parse the linkage specifier */
  6023.  
  6024.         linkDesc = ourParser->parseBrackAttr(true, ATTR_MASK_SYS_IMPORT, &memMod);
  6025.         xtraList = cmpAddXtraInfo(xtraList, linkDesc);
  6026.  
  6027.         /* Remember that the class has methods with linkage specifiers */
  6028.  
  6029.         clsSym->sdClass.sdcHasLinks = true;
  6030.  
  6031.         /* The member really wasn't declared "extern" */
  6032.  
  6033.         memMod.dmMod &= ~DM_EXTERN;
  6034.         break;
  6035.  
  6036.     case tkLBrack:
  6037.     case tkAtComment:
  6038.     case tkCAPABILITY:
  6039.     case tkPERMISSION:
  6040.     case tkATTRIBUTE:
  6041.  
  6042.         for (hadMods = false;;)
  6043.         {
  6044.             switch (ourScanner->scanTok.tok)
  6045.             {
  6046.                 SymXinfo        linkDesc;
  6047.  
  6048.                 AtComment       atcList;
  6049.  
  6050.                 unsigned        attrMask;
  6051.                 genericBuff     attrAddr;
  6052.                 size_t          attrSize;
  6053.                 SymDef          attrCtor;
  6054.  
  6055.             case tkLBrack:
  6056.                 linkDesc = ourParser->parseBrackAttr(true, ATTR_MASK_SYS_IMPORT|ATTR_MASK_NATIVE_TYPE, &memMod);
  6057.                 xtraList = cmpAddXtraInfo(xtraList, linkDesc);
  6058.                 hadMods  = true;
  6059.  
  6060.                 /* Stupid thing: parseBrackAttr() sets "extern", just clear it here */
  6061.  
  6062.                 memMod.dmMod &= ~DM_EXTERN;
  6063.                 continue;
  6064.  
  6065.             case tkAtComment:
  6066.  
  6067.                 for (atcList = ourScanner->scanTok.atComm.tokAtcList;
  6068.                      atcList;
  6069.                      atcList = atcList->atcNext)
  6070.                 {
  6071.                     switch (atcList->atcFlavor)
  6072.                     {
  6073.                     case AC_DLL_IMPORT:
  6074.  
  6075.                         /* Was there a DLL name? */
  6076.  
  6077.                         if  (!atcList->atcInfo.atcImpLink->ldDLLname)
  6078.                         {
  6079.                             /* The class better supply the DLL name */
  6080.  
  6081.                             if  (!clsSym->sdClass.sdcExtraInfo)
  6082.                             {
  6083.                         NO_DLL:
  6084.                                 cmpError(ERRnoDLLname);
  6085.                             }
  6086.                             else
  6087.                             {
  6088.                                 SymXinfoAtc     clsImp = cmpFindATCentry(clsSym->sdClass.sdcExtraInfo,
  6089.                                                                          AC_DLL_IMPORT);
  6090.                                 if  (!clsImp)
  6091.                                     goto NO_DLL;
  6092.  
  6093.                                 assert(clsImp->xiAtcInfo);
  6094.                                 assert(clsImp->xiAtcInfo->atcFlavor == AC_DLL_IMPORT);
  6095.  
  6096.                                 atcList->atcInfo.atcImpLink->ldDLLname = clsImp->xiAtcInfo->atcInfo.atcImpLink->ldDLLname;
  6097.                             }
  6098.                         }
  6099.  
  6100.                         xtraList = cmpAddXtraInfo(xtraList, atcList->atcInfo.atcImpLink);
  6101.                         break;
  6102.  
  6103.                     case AC_COM_METHOD:
  6104.                     case AC_COM_PARAMS:
  6105.                     case AC_DLL_STRUCTMAP:
  6106.                         xtraList = cmpAddXtraInfo(xtraList, atcList);
  6107.                         break;
  6108.  
  6109.                     case AC_DEPRECATED:
  6110.                         memDepr = true;
  6111.                         break;
  6112.  
  6113.                     case AC_CONDITIONAL:
  6114.                         memCond = !atcList->atcInfo.atcCondYes;
  6115.                         break;
  6116.  
  6117.                     default:
  6118.                         cmpError(ERRbadAtCmPlc);
  6119.                         break;
  6120.                     }
  6121.                 }
  6122.                 ourScanner->scan();
  6123.                 continue;
  6124.  
  6125.             case tkCAPABILITY:
  6126.                 xtraList = cmpAddXtraInfo(xtraList, ourParser->parseCapability(true));
  6127.                 continue;
  6128.  
  6129.             case tkPERMISSION:
  6130.                 xtraList = cmpAddXtraInfo(xtraList, ourParser->parsePermission(true));
  6131.                 continue;
  6132.  
  6133.             case tkATTRIBUTE:
  6134.                 attrCtor = cmpParser->parseAttribute(ATGT_Methods|ATGT_Fields|ATGT_Constructors|ATGT_Properties,
  6135.                                                      attrMask,
  6136.                                                      attrAddr,
  6137.                                                      attrSize);
  6138.                 if  (attrSize)
  6139.                 {
  6140.                     xtraList = cmpAddXtraInfo(xtraList, attrCtor,
  6141.                                                         attrMask,
  6142.                                                         attrSize,
  6143.                                                         attrAddr);
  6144.                 }
  6145.                 continue;
  6146.  
  6147.             default:
  6148.                 break;
  6149.             }
  6150.  
  6151.             break;
  6152.         }
  6153.  
  6154.         if  (hadMods)
  6155.             break;
  6156.  
  6157.         // Fall through ...
  6158.  
  6159.     default:
  6160.  
  6161.         /* If the member record doesn't indicate an access level, use the default */
  6162.  
  6163.         if  (clsMem->dlDefAcc == ACL_ERROR)
  6164.              clsMem->dlDefAcc = acc;
  6165.  
  6166.         ourParser->parseDeclMods((accessLevels)clsMem->dlDefAcc, &memMod);
  6167.  
  6168.         /* Special case: constructors have no return type specifications */
  6169.  
  6170.         if  (isCtor)
  6171.         {
  6172.             /* Pretend we've parsed a type spec already */
  6173.  
  6174.             baseTp = cmpTypeVoid;
  6175.  
  6176.             assert(ourScanner->scanTok.tok != tkLCurly);
  6177.             goto DCL_MEM;
  6178.  
  6179.         }
  6180.  
  6181.         break;
  6182.  
  6183.     case tkCASE:
  6184.  
  6185.         /* This must be a member of a tagged union */
  6186.  
  6187.         ourScanner->scan();
  6188.  
  6189.         /* Parse and evaluate the tag value */
  6190.  
  6191.         if  (ourParser->parseConstExpr(cval, NULL, tagSym->sdType))
  6192.             tagVal = cval.cvValue.cvIval;
  6193.  
  6194.         /* Accept both "case tagval:" and "case(tagval)" */
  6195.  
  6196.         if  (ourScanner->scanTok.tok == tkColon)
  6197.             ourScanner->scan();
  6198.  
  6199.         tagDef = false;
  6200.         goto NEXT_MEM;
  6201.  
  6202.     case tkDEFAULT:
  6203.  
  6204.         /* Check for a default property member declaration */
  6205.  
  6206.         if  (ourScanner->scan() == tkPROPERTY)
  6207.         {
  6208.             assert(ourScanner->scanTok.tok == tkPROPERTY || cmpErrorCount);
  6209.  
  6210.             ourParser->parseDeclMods(acc, &memMod);
  6211.             memMod.dmMod |= DM_DEFAULT;
  6212.             break;
  6213.         }
  6214.  
  6215.         /* This is the default member of a tagged union */
  6216.  
  6217.         ourScanner->scan();
  6218.  
  6219.         // UNDONE: check for duplicate default
  6220.  
  6221.         tagDef = true;
  6222.         goto NEXT_MEM;
  6223.     }
  6224.  
  6225.     /* Parse the type specification */
  6226.  
  6227.     baseTp = ourParser->parseTypeSpec(&memMod, true);
  6228.  
  6229.     /* Do we need to skip over any declarators that might be in the way? */
  6230.  
  6231.     if  (dclSkip)
  6232.     {
  6233.         if  (dclSkip & dlSkipBig)
  6234.         {
  6235.             NumPair         dist;
  6236.  
  6237.             /* We have to skip a "large" distance -- retrieve the info */
  6238.  
  6239.             dist = (NumPair)cmpGetVecEntry(dclSkip & ~dlSkipBig, VEC_TOKEN_DIST);
  6240.  
  6241.             ourScanner->scanSkipSect(dist->npNum1, dist->npNum2);
  6242.         }
  6243.         else
  6244.             ourScanner->scanSkipSect(dclSkip);
  6245.     }
  6246.  
  6247.     /* We have the type, now parse any declarators that follow */
  6248.  
  6249.     for (;;)
  6250.     {
  6251.         SymDef          msym;
  6252.         QualName        qual;
  6253.         dclrtrName      reqName;
  6254.  
  6255.         /* Check for an unnamed bitfield */
  6256.  
  6257.         if  (ourScanner->scanTok.tok == tkColon)
  6258.         {
  6259.             memType = baseTp;
  6260.             memName = cmpNewAnonymousName();
  6261.  
  6262.             goto BITFIELD;
  6263.         }
  6264.  
  6265.     DCL_MEM:
  6266.  
  6267.         /* Parse the next declarator */
  6268.  
  6269.         reqName = (dclrtrName)(DN_REQUIRED|DN_QUALOK);
  6270.  
  6271.         memName = ourParser->parseDeclarator(&memMod,
  6272.                                              baseTp,
  6273.                                              reqName,
  6274.                                              &memType,
  6275.                                              &qual,
  6276.                                              true);
  6277.  
  6278.         /* Skip the member if there were errors parsing it */
  6279.  
  6280.         if  (!memName || !memType)
  6281.         {
  6282.             /* Special case: qualified methods are allowed for interface impls */
  6283.  
  6284.             if  (qual && memType)
  6285.             {
  6286.                 /* Only methods may be qualified; in particular, no property crap here --right ? */
  6287.  
  6288.                 if  (memType->tdTypeKind == TYP_FNC)
  6289.                 {
  6290.                     if  (!(memMod.dmMod & DM_PROPERTY))
  6291.                     {
  6292.                         /* Looks good, we'll take care of the rest below */
  6293.  
  6294.                         goto DEF_MEM;
  6295.                     }
  6296.  
  6297.                     cmpError(ERRbadQualid);
  6298.                 }
  6299.             }
  6300.  
  6301.             cmpParser->parseResync(tkComma, tkSColon);
  6302.             if  (ourScanner->scanTok.tok != tkComma)
  6303.                 break;
  6304.  
  6305.             continue;
  6306.         }
  6307.  
  6308.     DEF_MEM:
  6309.  
  6310. #ifdef DEBUG
  6311.  
  6312.         if  (cmpConfig.ccVerbose >= 2)
  6313.         {
  6314.             printf("Declaring class member: ");
  6315.             if  (memMod.dmMod & DM_TYPEDEF)
  6316.                 printf("typedef ");
  6317.             printf("%s\n", ourSymTab->stTypeName(memType, NULL, memName, NULL, true));
  6318.         }
  6319.  
  6320. #endif
  6321.  
  6322.         msym = NULL;
  6323.  
  6324.         /* We don't allow "managed" specifiers on class members */
  6325.  
  6326.         if  (memMod.dmMod & (DM_MANAGED|DM_UNMANAGED))
  6327.         {
  6328.             if  (memMod.dmMod & DM_MANAGED)
  6329.                 cmpError(ERRbadMgdMod, cmpGlobalHT->tokenToIdent(tkMANAGED));
  6330.             if  (memMod.dmMod & DM_UNMANAGED)
  6331.                 cmpError(ERRbadMgdMod, cmpGlobalHT->tokenToIdent(tkUNMANAGED));
  6332.         }
  6333.  
  6334.         /* Make sure we bind the type */
  6335.  
  6336.         cmpBindType(memType, false, false);
  6337.  
  6338.         /* Declare a symbol for the name */
  6339.  
  6340.         if  (memMod.dmMod & DM_TYPEDEF)
  6341.         {
  6342.             UNIMPL(!"declare typedef class member - is this even allowed?");
  6343.         }
  6344.         else
  6345.         {
  6346.             switch (memType->tdTypeKind)
  6347.             {
  6348.                 tokens          memNtok;
  6349.  
  6350.             case TYP_FNC:
  6351.  
  6352.                 /* Is this a property member? */
  6353.  
  6354.                 if  (memMod.dmMod & DM_PROPERTY)
  6355.                     goto DECL_PROP;
  6356.  
  6357.                 /* Plain old data types don't have member functions */
  6358.  
  6359.                 /* Was the name qualified ? */
  6360.  
  6361.                 if  (qual && !memName)
  6362.                 {
  6363.                     SymDef          ifncSym;
  6364.                     SymDef          intfSym;
  6365.  
  6366.                     SymDef           oldSym;
  6367.  
  6368.                     /* This better be a managed class with interfaces */
  6369.  
  6370.                     if  (!clsSym->sdIsManaged || clsSym->sdClass.sdcFlavor != STF_CLASS)
  6371.                     {
  6372.                         cmpError(ERRbadQualid);
  6373.                         break;
  6374.                     }
  6375.  
  6376.                     /* The name should denote an interface method */
  6377.  
  6378.                     ifncSym = cmpBindQualName(qual, false);
  6379.                     if  (!ifncSym)
  6380.                         break;
  6381.  
  6382.                     if  (ifncSym->sdSymKind != SYM_FNC)
  6383.                     {
  6384.                     BAD_IIF:
  6385.                         cmpErrorQnm(ERRintfImpl, ifncSym);
  6386.                         break;
  6387.                     }
  6388.  
  6389.                     if  (ifncSym->sdIsMember  == false)
  6390.                         goto BAD_IIF;
  6391.                     if  (ifncSym->sdIsManaged == false)
  6392.                         goto BAD_IIF;
  6393.  
  6394.                     intfSym = ifncSym->sdParent;
  6395.  
  6396.                     if  (intfSym->sdSymKind != SYM_CLASS)
  6397.                         goto BAD_IIF;
  6398.                     if  (intfSym->sdIsManaged == false)
  6399.                         goto BAD_IIF;
  6400.                     if  (intfSym->sdClass.sdcFlavor != STF_INTF)
  6401.                         goto BAD_IIF;
  6402.  
  6403.                     /* Make sure our class implements this interface */
  6404.  
  6405.                     if  (!cmpGlobalST->stIsBaseClass(intfSym->sdType, clsTyp))
  6406.                         goto BAD_IIF;
  6407.  
  6408.                     /* Get hold of the method's name */
  6409.  
  6410.                     memName = ifncSym->sdName; assert(memName == qual->qnTable[qual->qnCount - 1]);
  6411.  
  6412.                     /* Look for an existing matching method impl */
  6413.  
  6414.                     if  (cmpFindIntfImpl(clsSym, ifncSym, &oldSym))
  6415.                     {
  6416.                         cmpErrorQnm(ERRredefBody, ifncSym);
  6417.                         goto NEXT_MEM;
  6418.                     }
  6419.  
  6420.                     if  (oldSym)
  6421.                     {
  6422.                         /* The method is a new overload */
  6423.  
  6424.                         msym = cmpCurST->stDeclareOvl(oldSym);
  6425.  
  6426.                         /* Copy over some info from the existing method */
  6427.  
  6428.                         msym->sdFnc.sdfOverload = oldSym->sdFnc.sdfOverload;
  6429.                     }
  6430.                     else
  6431.                     {
  6432.                         /* Create a member symbol and add it to the class */
  6433.  
  6434.                         msym = cmpCurST->stDeclareSym(memName, SYM_FNC, NS_HIDE, clsSym);
  6435.                     }
  6436.  
  6437.                     /* Fill in the method's type, access level, and so on */
  6438.  
  6439.                     msym->sdType              = memType;
  6440.                     msym->sdAccessLevel       = (accessLevels)memMod.dmAcc;
  6441.                     msym->sdIsMember          = true;
  6442.                     msym->sdIsManaged         = true;
  6443.                     msym->sdCompileState      = CS_DECLARED;
  6444.  
  6445.                     msym->sdFnc.sdfIntfImpl   = true;
  6446.                     msym->sdFnc.sdfIntfImpSym = ifncSym;
  6447.  
  6448.                     /* Make sure the return type matches */
  6449.  
  6450.                     if  (!ourSymTab->stMatchTypes(        memType->tdFnc.tdfRett,
  6451.                                                   ifncSym->sdType->tdFnc.tdfRett))
  6452.                     {
  6453.                         cmpErrorQSS(ERRdiffVirtRet, msym, ifncSym);
  6454.                     }
  6455.  
  6456.                     /* Make sure the access level matches */
  6457.  
  6458.                     if  (ifncSym->sdAccessLevel < msym->sdAccessLevel)
  6459.                         cmpErrorQnm(ERRvirtAccess, ifncSym);
  6460.  
  6461.                     /* Skip over the rest of method processing */
  6462.  
  6463.                     clsSym->sdClass.sdcHasMeths = true;
  6464.                     break;
  6465.                 }
  6466.  
  6467.                 /* Interface methods have a number of restrictions */
  6468.  
  6469.                 if  (isIntf)
  6470.                 {
  6471.                     memMod.dmMod |= DM_ABSTRACT;
  6472.  
  6473.                     if  (memMod.dmAcc != ACL_PUBLIC &&
  6474.                          memMod.dmAcc != ACL_DEFAULT)
  6475.                     {
  6476.                         cmpError(ERRintfFNacc);
  6477.                     }
  6478.                 }
  6479.  
  6480.                 /* Declare the member function symbol */
  6481.  
  6482.                 msym = cmpDeclFuncMem(clsSym, memMod, memType, memName);
  6483.                 if  (!msym)
  6484.                     break;
  6485.  
  6486.                 /* Remember whether the method is marked as "deprecated" */
  6487.  
  6488.                 msym->sdIsDeprecated     = memDepr;
  6489.  
  6490.                 // UNDONE: check to make sure the specs are legal!!!!
  6491.  
  6492.                 msym->sdFnc.sdfExtraInfo = xtraList;
  6493.  
  6494.                 /* Is this a constructor? */
  6495.  
  6496.                 if  (isCtor)
  6497.                 {
  6498.                     msym->sdFnc.sdfCtor = true;
  6499.                     if  (!msym->sdIsStatic)
  6500.                         hasCtors = true;
  6501.                     break;
  6502.                 }
  6503.                 else
  6504.                 {
  6505.                     if  (memName == clsSym->sdName)
  6506.                         cmpError(ERRctorRetTP);
  6507.                 }
  6508.  
  6509.                 /* Note whether the method is overloading the base */
  6510.  
  6511.                 if  ((memMod.dmMod & DM_OVERLOAD) || msym->sdFnc.sdfOverload)
  6512.                 {
  6513.                     hadOvlds                = true;
  6514.                     msym->sdFnc.sdfOverload = true;
  6515.                 }
  6516.  
  6517.                 /* Was the method declared as 'abstract' ? */
  6518.  
  6519.                 if  (memMod.dmMod & DM_ABSTRACT)
  6520.                 {
  6521.                     if  (memMod.dmMod & DM_STATIC)
  6522.                         cmpModifierError(ERRdmModifier, DM_STATIC);
  6523.  
  6524.                     /* Is the class itself marked as abstract ? */
  6525.  
  6526.                     if  (!clsSym->sdIsAbstract)
  6527.                         cmpClsImplAbs(clsSym, msym);
  6528.                 }
  6529.  
  6530.                 /* Is this an overloaded operator method? */
  6531.  
  6532.                 memNtok = hashTab::tokenOfIdent(memName);
  6533.  
  6534.                 if  (memNtok != tkNone)
  6535.                 {
  6536.                     ArgDef          arg1;
  6537.                     ArgDef          arg2;
  6538.                     unsigned        argc;
  6539.                     bool            argx;
  6540.  
  6541.                     unsigned        prec;
  6542.                     treeOps         oper;
  6543.  
  6544.                     /* Operators must be static (for now) */
  6545.  
  6546.                     if  (!msym->sdIsStatic)
  6547.                         cmpError(ERRbadOvlOp);
  6548.  
  6549.                     /* Count the arguments and make sure there are no defaults */
  6550.  
  6551.                     arg1 = memType->tdFnc.tdfArgs.adArgs;
  6552.                     argx = memType->tdFnc.tdfArgs.adExtRec;
  6553.                     argc = 0;
  6554.  
  6555.                     if  (!msym->sdIsStatic)
  6556.                         argc++;
  6557.  
  6558.                     if  (arg1)
  6559.                     {
  6560.                         argc++;
  6561.  
  6562.                         if  (argx && (((ArgExt)arg1)->adFlags & ARGF_DEFVAL))
  6563.                             cmpError(ERRdefOvlVal);
  6564.  
  6565.                         arg2 = arg1->adNext;
  6566.                         if  (arg2)
  6567.                         {
  6568.                             argc++;
  6569.  
  6570.                             if  (argx && (((ArgExt)arg2)->adFlags & ARGF_DEFVAL))
  6571.                                 cmpError(ERRdefOvlVal);
  6572.  
  6573.                             if  (arg2->adNext)
  6574.                                 argc++;
  6575.                         }
  6576.                     }
  6577.  
  6578.                     /* Conversion operators are handled a bit differently */
  6579.  
  6580.                     switch (memNtok)
  6581.                     {
  6582.                         bool            op1;
  6583.                         bool            op2;
  6584.  
  6585.                     case OPNM_CONV_EXP:
  6586.                         msym->sdFnc.sdfOper     = OVOP_CONV_EXP;
  6587.                         msym->sdFnc.sdfConvOper = true;
  6588.                         break;
  6589.  
  6590.                     case OPNM_CONV_IMP:
  6591.                         msym->sdFnc.sdfOper     = OVOP_CONV_IMP;
  6592.                         msym->sdFnc.sdfConvOper = true;
  6593.                         break;
  6594.  
  6595.                     case OPNM_EQUALS:
  6596.                         msym->sdFnc.sdfOper     = OVOP_EQUALS;
  6597.                         if  (cmpDirectType(memType->tdFnc.tdfRett)->tdTypeKind != TYP_BOOL)
  6598.                             cmpError(ERRbadOvlEq , memName);
  6599.                         goto CHK_OP_ARGTP;
  6600.  
  6601.                     case OPNM_COMPARE:
  6602.                         msym->sdFnc.sdfOper     = OVOP_COMPARE;
  6603.                         if  (cmpDirectType(memType->tdFnc.tdfRett)->tdTypeKind != TYP_INT)
  6604.                             cmpError(ERRbadOvlCmp, memName);
  6605.                         goto CHK_OP_ARGTP;
  6606.  
  6607.                     default:
  6608.  
  6609.                         /* Some operators may be both unary and binary */
  6610.  
  6611.                         op1 = cmpGlobalHT->tokenIsUnop (memNtok, &prec, &oper) && oper != TN_NONE;
  6612.                         op2 = cmpGlobalHT->tokenIsBinop(memNtok, &prec, &oper) && oper != TN_NONE;
  6613.  
  6614.                         if      (argc == 1 && op1)
  6615.                         {
  6616.                             TypDef          rett;
  6617.  
  6618.                             // OK:  unary operator and 1 argument
  6619.  
  6620.                             rett = cmpDirectType(memType->tdFnc.tdfRett);
  6621.  
  6622.                             if  (rett->tdTypeKind == TYP_REF && rett->tdIsImplicit)
  6623.                                 rett = rett->tdRef.tdrBase;
  6624.                             if  (rett->tdTypeKind != TYP_CLASS &&
  6625.                                  !cmpCurST->stMatchTypes(rett, clsSym->sdType))
  6626.                             {
  6627.                                 cmpError(ERRbadOvlRet, clsSym);
  6628.                             }
  6629.                         }
  6630.                         else if (argc == 2 && op2)
  6631.                         {
  6632.                             // OK: binary operator and 2 arguments
  6633.                         }
  6634.                         else
  6635.                         {
  6636.                             if      (op1 && op2)
  6637.                                 cmpError(ERRbadOvlOp12, memName);
  6638.                             else if (op1)
  6639.                                 cmpError(ERRbadOvlOp1 , memName);
  6640.                             else
  6641.                                 cmpError(ERRbadOvlOp2 , memName);
  6642.                         }
  6643.  
  6644.                     CHK_OP_ARGTP:;
  6645.  
  6646.                     }
  6647.  
  6648.                     break;
  6649.                 }
  6650.  
  6651.                 /* If there is a base class or interfaces ... */
  6652.  
  6653.                 if  (baseCls || clsTyp->tdClass.tdcIntf)
  6654.                 {
  6655.                     SymDef          bsym;
  6656.                     SymDef          fsym = NULL;
  6657.  
  6658.                     /* Look for a matching method in the base / interfaces */
  6659.  
  6660.                     bsym = ourSymTab->stFindBCImem(clsSym, memName, memType, SYM_FNC, fsym, true);
  6661.  
  6662.                     // UNDONE: The method may appear in more than interface, etc.
  6663.  
  6664.                     if  (bsym)
  6665.                     {
  6666.                         if  (!(memMod.dmMod & DM_STATIC) && bsym->sdFnc.sdfVirtual)
  6667.                         {
  6668.                             /* Is the base method a property accessor ? */
  6669.  
  6670.                             if  (bsym->sdFnc.sdfProperty)
  6671.                             {
  6672.                                 cmpErrorQnm(ERRpropAccDef, bsym);
  6673.                                 break;
  6674.                             }
  6675.  
  6676.                             /* Make sure the return type matches */
  6677.  
  6678.                             if  (!ourSymTab->stMatchTypes(     memType->tdFnc.tdfRett,
  6679.                                                           bsym->sdType->tdFnc.tdfRett))
  6680.                             {
  6681.                                 cmpErrorQSS(ERRdiffVirtRet, msym, bsym);
  6682.                             }
  6683.  
  6684.                             /* Make sure the access level matches */
  6685.  
  6686.                             if  (bsym->sdAccessLevel < msym->sdAccessLevel)
  6687.                                 cmpErrorQnm(ERRvirtAccess, bsym);
  6688.  
  6689.                             /* Copy the vtable index, we'll reuse the slot */
  6690.  
  6691.                             msym->sdFnc.sdfVtblx    = bsym->sdFnc.sdfVtblx;
  6692.                             msym->sdFnc.sdfVirtual  = true;
  6693.                             msym->sdFnc.sdfOverride = true;
  6694.                             hasVirts                = true;
  6695.                             break;
  6696.                         }
  6697.                     }
  6698.                     else if (fsym)
  6699.                     {
  6700.                         /* See if we're hiding any base methods */
  6701.  
  6702.                         if  (!msym->sdFnc.sdfOverload)
  6703.                         {
  6704.                             SymDef          begSym = ourSymTab->stLookupClsSym(memName, clsSym); assert(begSym);
  6705.  
  6706.                             hadOvlds                  = true;
  6707.                             begSym->sdFnc.sdfBaseHide = true;
  6708.                         }
  6709.                     }
  6710.                 }
  6711.  
  6712.                 /* Has the method been explicitly declared as "virtual" ? */
  6713.  
  6714.                 if  (memMod.dmMod & DM_VIRTUAL)
  6715.                 {
  6716.                     msym->sdFnc.sdfVirtual = true;
  6717.                     hasVirts               = true;
  6718.  
  6719.                     /* Is the class unmanaged? */
  6720.  
  6721.                     if  (!clsSym->sdIsManaged)
  6722.                     {
  6723.                         /* Add a slot for this function to the vtable */
  6724.  
  6725.                         msym->sdFnc.sdfVtblx = ++nextVtbl;
  6726.                     }
  6727.                 }
  6728.                 else if (msym->sdIsAbstract     != false &&
  6729.                          msym->sdFnc.sdfVirtual == false)
  6730.                 {
  6731.                     cmpErrorQnm(ERRabsNotVirt, msym); msym->sdIsAbstract = false;
  6732.                 }
  6733.                 break;
  6734.  
  6735.             case TYP_VOID:
  6736.                 cmpError(ERRbadVoid, memName);
  6737.                 continue;
  6738.  
  6739.             default:
  6740.  
  6741.                 /* Is this an overloaded operator method? */
  6742.  
  6743.                 if  (hashTab::tokenOfIdent(memName) != tkNone)
  6744.                 {
  6745.                     UNIMPL("what kind of a data member is this?");
  6746.                 }
  6747.  
  6748.                 /* Is this a property member? */
  6749.  
  6750.                 if  (memMod.dmMod & DM_PROPERTY)
  6751.                 {
  6752.                     /* Plain old data types don't have properties */
  6753.  
  6754.                     /* Parse the argument list if it's present */
  6755.  
  6756.                     if  (ourScanner->scanTok.tok == tkLBrack)
  6757.                     {
  6758.                         ArgDscRec       args;
  6759.  
  6760.                         /* Parse the argument list */
  6761.  
  6762.                         ourParser->parseArgList(args);
  6763.  
  6764.                         /* Create the function type */
  6765.  
  6766.                         memType = ourSymTab->stNewFncType(args, memType);
  6767.                     }
  6768.  
  6769.                 DECL_PROP:
  6770.  
  6771.                     /* Is there no "{ get/set }" thing present ? */
  6772.  
  6773.                     if  (ourScanner->scanTok.tok != tkLCurly)
  6774.                     {
  6775.                         if  (memMod.dmMod & DM_ABSTRACT)
  6776.                         {
  6777.                             if  (ourScanner->scanTok.tok != tkSColon)
  6778.                             {
  6779.                                 cmpError(ERRnoSmLc);
  6780.                                 goto NEXT_MEM;
  6781.                             }
  6782.                         }
  6783.                         else
  6784.                         {
  6785.                             cmpError(ERRnoPropDef);
  6786.                             goto NEXT_MEM;
  6787.                         }
  6788.                     }
  6789.  
  6790.                     /* Declare the member symbol for the property */
  6791.  
  6792.                     msym = cmpDeclPropMem(clsSym, memType, memName);
  6793.                     if  (!msym)
  6794.                         goto NEXT_MEM;
  6795.  
  6796.                     /* Record the access level of the property */
  6797.  
  6798.                     msym->sdAccessLevel = (accessLevels)memMod.dmAcc;
  6799.  
  6800.                     /* Properties in interfaces are always abstract */
  6801.  
  6802.                     if  (clsSym->sdClass.sdcFlavor == STF_INTF)
  6803.                         memMod.dmMod |= DM_ABSTRACT;
  6804.  
  6805.                     /* Is this a static/sealed/etc property? */
  6806.  
  6807.                     if  (memMod.dmMod & DM_SEALED)
  6808.                         msym->sdIsSealed   = true;
  6809.  
  6810.                     if  (memMod.dmMod & DM_DEFAULT)
  6811.                     {
  6812.                         msym->sdIsDfltProp = true;
  6813.  
  6814.                     }
  6815.  
  6816.                     if  (memMod.dmMod & DM_ABSTRACT)
  6817.                     {
  6818.                         msym->sdIsAbstract = true;
  6819.  
  6820.                         /* Is the class itself marked as abstract ? */
  6821.  
  6822.                         if  (!clsSym->sdIsAbstract)
  6823.                             cmpClsImplAbs(clsSym, msym);
  6824.                     }
  6825.  
  6826.                     if  (memMod.dmMod & DM_STATIC)
  6827.                     {
  6828.                         msym->sdIsStatic   = true;
  6829.                     }
  6830.                     else
  6831.                     {
  6832.                         SymDef          baseSym;
  6833.                         SymDef          tossSym = NULL;
  6834.  
  6835.                         /* Is this a virtual property ? */
  6836.  
  6837.                         if  (memMod.dmMod & DM_VIRTUAL)
  6838.                             msym->sdIsVirtProp = true;
  6839.  
  6840.                         /*
  6841.                             Check the base class / interfaces for a
  6842.                             matching property.
  6843.                          */
  6844.  
  6845.                         baseSym = ourSymTab->stFindBCImem(clsSym, memName, memType, SYM_PROP, tossSym, true);
  6846.  
  6847.                         if  (baseSym && baseSym->sdIsVirtProp)
  6848.                         {
  6849.                             /* The property inherits virtualness */
  6850.  
  6851.                             hasVirts           = true;
  6852.                             msym->sdIsVirtProp = true;
  6853.  
  6854.                             /* Make sure the types match */
  6855.  
  6856.                             if  (!ourSymTab->stMatchTypes(memType,
  6857.                                                           baseSym->sdType))
  6858.                             {
  6859.                                 cmpErrorQSS(ERRdiffPropTp, msym, baseSym);
  6860.                             }
  6861.                         }
  6862.                     }
  6863.  
  6864.                     /* Remember whether the property is "deprecated" */
  6865.  
  6866.                     msym->sdIsDeprecated = memDepr;
  6867.  
  6868. //                  printf("Declaring property '%s'\n", ourSymTab->stTypeName(msym->sdType, msym, NULL, NULL, false));
  6869.  
  6870.                     if  (xtraList)
  6871.                     {
  6872.                         SymXinfo        xtraTemp;
  6873.  
  6874.                         /* Walk the list of specs, making sure they look kosher */
  6875.  
  6876.                         for (xtraTemp = xtraList; xtraTemp; xtraTemp = xtraTemp->xiNext)
  6877.                         {
  6878.                             switch (xtraTemp->xiKind)
  6879.                             {
  6880.                             case XI_ATTRIBUTE:
  6881.  
  6882.                                 SymXinfoAttr    attrdsc = (SymXinfoAttr)xtraTemp;
  6883.  
  6884.                                 msym->sdProp.sdpExtraInfo = cmpAddXtraInfo(msym->sdProp.sdpExtraInfo,
  6885.                                                                            attrdsc->xiAttrCtor,
  6886.                                                                            attrdsc->xiAttrMask,
  6887.                                                                            attrdsc->xiAttrSize,
  6888.                                                                            attrdsc->xiAttrAddr);
  6889.                                 continue;
  6890.                             }
  6891.  
  6892.                             cmpError(ERRbadAtCmPlc);
  6893.                             break;
  6894.                         }
  6895.  
  6896.                         xtraList = NULL;
  6897.                     }
  6898.  
  6899.                     /* Declare the accessor methods and all that */
  6900.  
  6901.                     cmpDeclProperty(msym, memMod, clsDef);
  6902.  
  6903.                     goto NEXT_MEM;
  6904.                 }
  6905.  
  6906.                 /* Interface members have a number of restrictions */
  6907.  
  6908.                 if  (isIntf)
  6909.                 {
  6910.                     /* Only constants are allowed as interface data members */
  6911.  
  6912.                     if  (!(memMod.dmMod & DM_CONST))
  6913.                         cmpError(ERRintfDM);
  6914.                 }
  6915.  
  6916.                 /* Make sure that unmanaged classes don't have managed fields */
  6917.  
  6918.                 if  (!clsSym->sdIsManaged && (memType->tdIsManaged ||
  6919.                                               memType->tdTypeKind == TYP_REF))
  6920.                 {
  6921.                     cmpError(ERRumgFldMgd);
  6922.                 }
  6923.  
  6924.                 /* Declare a symbol for the member */
  6925.  
  6926.                 msym = cmpDeclDataMem(clsSym, memMod, memType, memName);
  6927.                 if  (!msym)
  6928.                     break;
  6929.  
  6930.                 /* Remember whether the member is "deprecated" */
  6931.  
  6932.                 msym->sdIsDeprecated = memDepr;
  6933.  
  6934.                 /* Is the member marked as "transient" ? */
  6935.  
  6936.                 if  (memMod.dmMod & DM_TRANSIENT)
  6937.                     msym->sdIsTransient = true;
  6938.  
  6939.                 /* Check for any marshalling / other specifications */
  6940.  
  6941.                 if  (xtraList)
  6942.                 {
  6943.                     SymXinfo        xtraTemp;
  6944.  
  6945.                     /* Walk the list of specs, making sure they look kosher */
  6946.  
  6947.                     for (xtraTemp = xtraList; xtraTemp; xtraTemp = xtraTemp->xiNext)
  6948.                     {
  6949.                         switch (xtraTemp->xiKind)
  6950.                         {
  6951.                         case XI_ATCOMMENT:
  6952.  
  6953.                             AtComment       atcList;
  6954.  
  6955.                             /* We only allow "@dll.structmap" for data members */
  6956.  
  6957.                             for (atcList = ((SymXinfoAtc)xtraTemp)->xiAtcInfo;
  6958.                                  atcList;
  6959.                                  atcList = atcList->atcNext)
  6960.                             {
  6961.                                 switch (atcList->atcFlavor)
  6962.                                 {
  6963.                                 case AC_DLL_STRUCTMAP:
  6964.  
  6965.                                     /* If we have a symbol, record the info */
  6966.  
  6967.                                     if  (!msym)
  6968.                                         break;
  6969.  
  6970.                                     clsSym->sdClass.sdcMarshInfo = true;
  6971.  
  6972.                                     msym->sdVar.sdvMarshInfo     = true;
  6973.                                     msym->sdVar.sdvFldInfo       = cmpAddXtraInfo(msym->sdVar.sdvFldInfo,
  6974.                                                                                   atcList->atcInfo.atcMarshal);
  6975.                                     break;
  6976.  
  6977.                                 default:
  6978.                                     goto BAD_XI;
  6979.                                 }
  6980.                             }
  6981.  
  6982.                             continue;
  6983.  
  6984.                         case XI_MARSHAL:
  6985.  
  6986.                             msym->sdVar.sdvFldInfo  = cmpAddXtraInfo(msym->sdVar.sdvFldInfo,
  6987.                                                                      ((SymXinfoCOM)xtraTemp)->xiCOMinfo);
  6988.                             continue;
  6989.  
  6990.                         case XI_ATTRIBUTE:
  6991.  
  6992.                             SymXinfoAttr    attrdsc = (SymXinfoAttr)xtraTemp;
  6993.  
  6994.                             msym->sdVar.sdvFldInfo  = cmpAddXtraInfo(msym->sdVar.sdvFldInfo,
  6995.                                                                      attrdsc->xiAttrCtor,
  6996.                                                                      attrdsc->xiAttrMask,
  6997.                                                                      attrdsc->xiAttrSize,
  6998.                                                                      attrdsc->xiAttrAddr);
  6999.                             continue;
  7000.                         }
  7001.  
  7002.                     BAD_XI:
  7003.  
  7004.                         cmpError(ERRbadAtCmPlc);
  7005.                         break;
  7006.                     }
  7007.  
  7008.                     xtraList = NULL;
  7009.                 }
  7010.  
  7011.                 break;
  7012.             }
  7013.         }
  7014.  
  7015.         /* Record the member's access level */
  7016.  
  7017.         if  (msym)
  7018.             msym->sdAccessLevel = (accessLevels)memMod.dmAcc;
  7019.  
  7020.         /* Is there an initializer or method body? */
  7021.  
  7022.         switch (ourScanner->scanTok.tok)
  7023.         {
  7024.             unsigned        maxbf;
  7025.             constVal        cval;
  7026.  
  7027.             genericBuff     defFpos;
  7028.             unsigned        defLine;
  7029.  
  7030.         case tkAsg:
  7031.  
  7032.             /* Only data members can be given initializers */
  7033.  
  7034.             if  (memType->tdTypeKind == TYP_FNC || !clsDef)
  7035.             {
  7036.                 if  (oldStyleDecl)
  7037.                 {
  7038.                     cmpError(ERRbadInit);
  7039.  
  7040.                     /* Swallow the rest of the initializer */
  7041.  
  7042.                     cmpParser->parseResync(tkComma, tkSColon);
  7043.                 }
  7044.  
  7045.                 break;
  7046.             }
  7047.  
  7048.             /* Is this an old-style file scope class? */
  7049.  
  7050.             if  (oldStyleDecl && !clsSym->sdIsManaged)
  7051.             {
  7052.                 /* Is this a constant member? */
  7053.  
  7054.                 if  (memMod.dmMod & DM_CONST)
  7055.                 {
  7056.                     if  (msym)
  7057.                     {
  7058.                         /* Evaluate and record the constant value */
  7059.  
  7060.                         ourScanner->scan();
  7061.                         cmpParseConstDecl(msym);
  7062.                     }
  7063.                     else
  7064.                     {
  7065.                         /* Error above, just skip over the initializer */
  7066.  
  7067.                         ourScanner->scanSkipText(tkNone, tkNone, tkComma);
  7068.                     }
  7069.                 }
  7070.                 else
  7071.                 {
  7072.                     /* Figure out where we are */
  7073.  
  7074.                     defFpos = ourScanner->scanGetTokenPos(&defLine);
  7075.  
  7076.                     /* Swallow the initializer */
  7077.  
  7078.                     ourScanner->scanSkipText(tkNone, tkNone, tkComma);
  7079.  
  7080.                     /* Record the position of the initializer */
  7081.  
  7082.                     if  (msym)
  7083.                     {
  7084.                         DefList         memDef;
  7085.  
  7086.                         /* Mark the member var as having an initializer */
  7087.  
  7088.                         msym->sdIsDefined      = true;
  7089.                         msym->sdVar.sdvHadInit = true;
  7090.  
  7091.                         /* Remember where the initializer is, we'll come back to it later */
  7092.  
  7093.                         assert(clsDef);
  7094.  
  7095.                         memDef = ourSymTab->stRecordSymSrcDef(msym,
  7096.                                                               clsDef->dlComp,
  7097.                                                               clsDef->dlUses,
  7098.                                                               defFpos,
  7099. //                                                            ourScanner->scanGetFilePos(),
  7100.                                                               defLine);
  7101.                         memDef->dlHasDef = true;
  7102.                     }
  7103.                 }
  7104.             }
  7105.             else
  7106.             {
  7107.                 assert(clsMem && clsMem->dlExtended);
  7108.  
  7109.                 clsMem->mlSym    = msym;
  7110.                 clsMem->dlHasDef = true;
  7111.  
  7112.                 /* Swallow the "=" token */
  7113.  
  7114.                 ourScanner->scan();
  7115.  
  7116.                 /* Figure out where we are */
  7117.  
  7118.                 defFpos = ourScanner->scanGetTokenPos(&defLine);
  7119.  
  7120.                 /* Swallow the constant expression */
  7121.  
  7122.                 if  (ourScanner->scanTok.tok == tkLCurly)
  7123.                 {
  7124.                     ourScanner->scanSkipText(tkLCurly, tkRCurly);
  7125.                     if  (ourScanner->scanTok.tok == tkRCurly)
  7126.                         ourScanner->scan();
  7127.                 }
  7128.                 else
  7129.                     ourScanner->scanSkipText(tkLParen, tkRParen, tkComma);
  7130.  
  7131.                 /* Record the position of the constant (unless we had errors) */
  7132.  
  7133.                 if  (msym)
  7134.                 {
  7135.                     constList = cmpTempMLappend(constList, &constLast,
  7136.                                                 msym,
  7137.                                                 clsMem->dlComp,
  7138.                                                 clsMem->dlUses,
  7139.                                                 defFpos,
  7140. //                                              ourScanner->scanGetFilePos(),
  7141.                                                 defLine);
  7142.  
  7143.                     /* Remember that we have found a member initializer */
  7144.  
  7145.                     hadMemInit              = true;
  7146.                     msym->sdVar.sdvHadInit  = true;
  7147.                     msym->sdVar.sdvDeferCns = true;
  7148.                 }
  7149.             }
  7150.             break;
  7151.  
  7152.         case tkLCurly:
  7153.  
  7154.             /* Is this a variable? */
  7155.  
  7156.             if  (memType->tdTypeKind != TYP_FNC || !clsDef)
  7157.             {
  7158.                 cmpError(ERRbadFNbody);
  7159.  
  7160.             BAD_BOD:
  7161.  
  7162.                 /* Skip over the bogus function body */
  7163.  
  7164.                 ourScanner->scanSkipText(tkLCurly, tkRCurly);
  7165.                 if  (ourScanner->scanTok.tok == tkRCurly)
  7166.                     ourScanner->scan();
  7167.  
  7168.                 goto NEXT_MEM;
  7169.             }
  7170.  
  7171.         FNC_DEF:
  7172.  
  7173.             /* Make sure the method isn't abstract */
  7174.  
  7175.             if  (memMod.dmMod & DM_ABSTRACT)
  7176.             {
  7177.                 cmpError(ERRabsFNbody, msym);
  7178.                 goto BAD_BOD;
  7179.             }
  7180.  
  7181.             assert(clsMem);
  7182.  
  7183.             /* Is this method conditionally disabled? */
  7184.  
  7185.             if  (memCond)
  7186.             {
  7187.                 /* There better not be a return value */
  7188.  
  7189.                 if  (cmpActualVtyp(msym->sdType->tdFnc.tdfRett) == TYP_VOID)
  7190.                 {
  7191.                     msym->sdFnc.sdfDisabled = true;
  7192.                     goto NEXT_MEM;
  7193.                 }
  7194.  
  7195.                 cmpError(ERRbadCFNret);
  7196.             }
  7197.  
  7198.             /* Record the member symbol in the declaration entry */
  7199.  
  7200.             clsMem->mlSym     = msym;
  7201.             clsMem->dlHasDef  = true;
  7202.  
  7203.             /* Mark the method as having a body */
  7204.  
  7205.             if  (msym)
  7206.                 msym->sdIsDefined = true;
  7207.  
  7208.             /* Remember that the class had some method bodies */
  7209.  
  7210.             clsSym->sdClass.sdcHasBodies = true;
  7211.  
  7212.             goto NEXT_MEM;
  7213.  
  7214.         case tkColon:
  7215.  
  7216.             /* Is this a base class ctor call ? */
  7217.  
  7218.             if  (isCtor)
  7219.             {
  7220.                 assert(memType->tdTypeKind == TYP_FNC);
  7221.  
  7222.                 /* Simply skip over the base ctor call for now */
  7223.  
  7224.                 ourScanner->scanSkipText(tkNone, tkNone, tkLCurly);
  7225.  
  7226.                 if  (ourScanner->scanTok.tok == tkLCurly)
  7227.                     goto FNC_DEF;
  7228.  
  7229.                 break;
  7230.             }
  7231.  
  7232.             // Fall through, must be a bitfield ...
  7233.  
  7234.         BITFIELD:
  7235.  
  7236.             /* This is a bitfield */
  7237.  
  7238.             memType = cmpDirectType(memType);
  7239.  
  7240.             if  (varTypeIsIntegral(memType->tdTypeKindGet()))
  7241.             {
  7242.                 maxbf = cmpGetTypeSize(memType) * 8;
  7243.             }
  7244.             else
  7245.             {
  7246.                 cmpError(ERRbadBfld, memType);
  7247.                 maxbf = 0;
  7248.             }
  7249.  
  7250.             /* A static data member can't be a bitfield */
  7251.  
  7252.             if  (msym->sdIsStatic)
  7253.                 cmpError(ERRstmBfld);
  7254.  
  7255.             /* We don't support bitfields in managed classes */
  7256.  
  7257.             if  (clsTyp->tdIsManaged)
  7258.                 cmpWarn(WRNmgdBF);
  7259.  
  7260.             /* Swallow the ":" and parse the bitfield width expression */
  7261.  
  7262.             ourScanner->scan();
  7263.  
  7264.             if  (cmpParser->parseConstExpr(cval))
  7265.             {
  7266.                 /* Make sure the value is an integer */
  7267.  
  7268.                 if  (!varTypeIsIntegral((var_types)cval.cvVtyp) ||
  7269.                                                    cval.cvVtyp > TYP_UINT)
  7270.                 {
  7271.                     cmpError(ERRnoIntExpr);
  7272.                 }
  7273.                 else if (msym && msym->sdSymKind == SYM_VAR)
  7274.                 {
  7275.                     unsigned        bits = cval.cvValue.cvIval;
  7276.  
  7277.                     /* Make sure the bitfield width isn't too big */
  7278.  
  7279.                     if  ((bits == 0 || bits > maxbf) && maxbf)
  7280.                     {
  7281.                         cmpGenError(ERRbadBFsize, bits, maxbf);
  7282.                     }
  7283.                     else
  7284.                     {
  7285.                         /* Record the bitfield width in the member symbol */
  7286.  
  7287.                         msym->sdVar.sdvBitfield         = true;
  7288.                         msym->sdVar.sdvBfldInfo.bfWidth = (BYTE)bits;
  7289.                     }
  7290.                 }
  7291.             }
  7292.  
  7293.             break;
  7294.  
  7295.         default:
  7296.  
  7297.             if  (memType->tdTypeKind == TYP_FNC)
  7298.             {
  7299.                 /* Remember the symbol, though we don't have a definition yet */
  7300.  
  7301.                 clsMem->mlSym    = msym;
  7302.                 clsMem->dlHasDef = false;
  7303.  
  7304.             }
  7305.  
  7306.             break;
  7307.         }
  7308.  
  7309.         /* Are there any more declarators? */
  7310.  
  7311.         if  (ourScanner->scanTok.tok != tkComma)
  7312.             break;
  7313.  
  7314.         /* Are we processing a tagged union? */
  7315.  
  7316.         if  (tagged)
  7317.             cmpError(ERRmulUmem);
  7318.  
  7319.         if  (!oldStyleDecl)
  7320.             goto NEXT_MEM;
  7321.  
  7322.         assert(isCtor == false);    // ISSUE: this is not allowed, right?
  7323.  
  7324.         /* Swallow the "," and go get the next declarator */
  7325.  
  7326.         ourScanner->scan();
  7327.     }
  7328.  
  7329.     /* Make sure we've consumed the expected amount of text */
  7330.  
  7331.     if  (ourScanner->scanTok.tok != tkSColon)
  7332.     {
  7333.         cmpError(ERRnoCmSc);
  7334.     }
  7335.     else
  7336.     {
  7337.         /* Are we processing a tagged union? */
  7338.  
  7339.         if  (tagged)
  7340.         {
  7341.             /* Make sure there isn't another member present */
  7342.  
  7343.             switch (ourScanner->scan())
  7344.             {
  7345.             case tkRCurly:
  7346.             case tkCASE:
  7347.             case tkDEFAULT:
  7348.                 // ISSUE: Any other tokens to check for ?
  7349.                 break;
  7350.  
  7351.             default:
  7352.                 cmpError(ERRmulUmem);
  7353.                 break;
  7354.             }
  7355.         }
  7356.     }
  7357.  
  7358. NEXT_MEM:
  7359.  
  7360.     /* We're done reading source text from the definition */
  7361.  
  7362.     assert(rest); cmpParser->parseDoneText(save); rest = false;
  7363.  
  7364. DONE_MEM:
  7365.  
  7366.     /* Process the next member, if any */
  7367.  
  7368.     clsMem = (ExtList)clsMem->dlNext;
  7369.     if  (clsMem)
  7370.         goto LOOP_MEM;
  7371.  
  7372. NEXT_DEF:
  7373.  
  7374.     clsDef = clsDef->dlNext;
  7375.     if  (clsDef)
  7376.         goto LOOP_DEF;
  7377.  
  7378. DONE_DEF:
  7379.  
  7380.     /* We've reached 'declared' state successfully */
  7381.  
  7382.     clsSym->sdCompileState = CS_DECLARED;
  7383.  
  7384.     /* Remember how many vtable slots we've used */
  7385.  
  7386.     clsSym->sdClass.sdcVirtCnt = nextVtbl;
  7387.  
  7388.     /* We're done reading the definition */
  7389.  
  7390.     if  (rest)
  7391.         cmpParser->parseDoneText(save);
  7392.  
  7393.     /* Actually, did we really succeed? */
  7394.  
  7395.     if  (clsSym->sdIsDefined)
  7396.     {
  7397.         /* If there were no ctors, we may have to add one */
  7398.  
  7399.         if  (!hasCtors && clsSym->sdIsManaged && !isIntf)
  7400.              cmpDeclDefCtor(clsSym);
  7401.  
  7402.         /* Did we have any members with initializers? */
  7403.  
  7404.         if  (hadMemInit)
  7405.             cmpEvalMemInits(clsSym, constList, noCnsEval, NULL);
  7406.  
  7407.         /* Did we have any base overloads? */
  7408.  
  7409.         if  (hadOvlds && baseCls)
  7410.         {
  7411.             SymDef          baseSym = baseCls->tdClass.tdcSymbol;
  7412.             SymDef          memSym;
  7413.  
  7414.             /*
  7415.                 Check all function members for being overloaded, also detect and flag
  7416.                 any methods that hide (don't overload) any base class methods.
  7417.              */
  7418.  
  7419.             for (memSym = clsSym->sdScope.sdScope.sdsChildList;
  7420.                  memSym;
  7421.                  memSym = memSym->sdNextInScope)
  7422.             {
  7423.                 SymDef          baseFnc;
  7424.  
  7425.                 if  (memSym->sdSymKind != SYM_FNC)
  7426.                     continue;
  7427.  
  7428. #ifndef NDEBUG
  7429.  
  7430.                 /* Make sure the head of the overload list is marked correctly */
  7431.  
  7432.                 for (SymDef fncSym = memSym; fncSym; fncSym = fncSym->sdFnc.sdfNextOvl)
  7433.                 {
  7434.                     assert(fncSym->sdFnc.sdfOverload == false || memSym->sdFnc.sdfOverload);
  7435.                     assert(fncSym->sdFnc.sdfBaseHide == false || memSym->sdFnc.sdfBaseHide);
  7436.                 }
  7437.  
  7438. #endif
  7439.  
  7440.                 if  (memSym->sdFnc.sdfBaseHide != false)
  7441.                 {
  7442.                     /* Some base class methods may be hidden */
  7443.  
  7444.                     cmpFindHiddenBaseFNs(memSym, baseCls->tdClass.tdcSymbol);
  7445.                     continue;
  7446.                 }
  7447.  
  7448.                 /* If there are no base overloads, ignore this method */
  7449.  
  7450.                 if  (memSym->sdFnc.sdfOverload == false)
  7451.                     continue;
  7452.  
  7453.                 /* See if a base class contains an overload */
  7454.  
  7455.                 baseFnc = ourSymTab->stLookupAllCls(memSym->sdName,
  7456.                                                     baseSym,
  7457.                                                     NS_NORM,
  7458.                                                     CS_DECLSOON);
  7459.  
  7460.                 if  (baseFnc && baseFnc->sdSymKind == SYM_FNC)
  7461.                 {
  7462.                     /* Mark our method as having base overloads */
  7463.  
  7464.                     memSym->sdFnc.sdfBaseOvl = true;
  7465.                 }
  7466.             }
  7467.         }
  7468.  
  7469.         /* Is this a class with interfaces or an abstract base class ? */
  7470.  
  7471.         if  (clsTyp->tdClass.tdcFlavor != STF_INTF)
  7472.         {
  7473.             if  (clsTyp->tdClass.tdcHasIntf)
  7474.                 cmpCheckClsIntf(clsSym);
  7475.  
  7476.             /* Is there an abstract base class? */
  7477.  
  7478.             if  (baseCls && baseCls->tdClass.tdcSymbol->sdIsAbstract
  7479.                          && !clsSym->                   sdIsAbstract)
  7480.             {
  7481.                 SymDef          baseSym;
  7482.  
  7483. //              printf("Checking [%u] class '%s'\n", clsTyp->tdClass.tdcHasIntf, clsSym->sdSpelling());
  7484.  
  7485.                 for (baseSym = baseCls->tdClass.tdcSymbol->sdScope.sdScope.sdsChildList;
  7486.                      baseSym;
  7487.                      baseSym = baseSym->sdNextInScope)
  7488.                 {
  7489.                     SymDef          baseOvl;
  7490.                     SymDef          implSym;
  7491.  
  7492.                     /* Is this a method? */
  7493.  
  7494.                     if  (baseSym->sdSymKind != SYM_FNC)
  7495.                     {
  7496.                         /* Is this a property member ? */
  7497.  
  7498.                         if  (baseSym->sdSymKind != SYM_PROP)
  7499.                             continue;
  7500.  
  7501.                         /* Ignore non-abstract members */
  7502.  
  7503.                         if  (baseSym->sdIsAbstract == false)
  7504.                             continue;
  7505.  
  7506.                         /* Look for a matching property in the class */
  7507.  
  7508.                         implSym = ourSymTab->stLookupClsSym(baseSym->sdName, clsSym);
  7509.                         if  (implSym && implSym->sdSymKind == SYM_PROP)
  7510.                             continue;
  7511.  
  7512.                         baseOvl = baseSym;
  7513.                         goto NON_IMPL;
  7514.                     }
  7515.  
  7516.                     /* Ignore property accessor methods */
  7517.  
  7518.                     if  (baseSym->sdFnc.sdfProperty)
  7519.                         continue;
  7520.  
  7521.                     /* Ignore operators, they can't be abstract anyway [ISSUE] */
  7522.  
  7523.                     if  (baseSym->sdFnc.sdfOper != OVOP_NONE)
  7524.                         continue;
  7525.  
  7526.                     /* Look for a matching member in the class we're declaring */
  7527.  
  7528.                     implSym = ourSymTab->stLookupClsSym(baseSym->sdName, clsSym);
  7529.                     if  (implSym && implSym->sdSymKind != SYM_FNC)
  7530.                         implSym = NULL;
  7531.  
  7532.                     /* Process all overloaded flavors of the method */
  7533.  
  7534.                     baseOvl = baseSym;
  7535.                     do
  7536.                     {
  7537.                         SymDef          implOvl;
  7538.  
  7539.                         /* Ignore non-abstract members */
  7540.  
  7541.                         if  (baseOvl->sdIsAbstract)
  7542.                         {
  7543.                             /* Look for a matching method defined in our class */
  7544.  
  7545.                             implOvl = implSym ? ourSymTab->stFindOvlFnc(implSym, baseOvl->sdType)
  7546.                                               : NULL;
  7547.  
  7548.                             if  (!implOvl)
  7549.                             {
  7550.                                 /* This abstract method isn't implemented by the class */
  7551.  
  7552.                             NON_IMPL:
  7553.  
  7554.                                 cmpClsImplAbs(clsSym, baseOvl);
  7555.  
  7556.                                 clsSym->sdIsAbstract = true;
  7557.  
  7558.                                 goto DONE_ABS;
  7559.                             }
  7560.                         }
  7561.  
  7562.                         baseOvl = baseOvl->sdFnc.sdfNextOvl;
  7563.                     }
  7564.                     while (baseOvl);
  7565.                 }
  7566.             }
  7567.         }
  7568.  
  7569.     DONE_ABS:
  7570.  
  7571.         /* For unmanaged classes, now is the time to do layout */
  7572.  
  7573.         clsSym->sdClass.sdcHasVptr = hasVirts;
  7574.  
  7575.         if  (!clsSym->sdIsManaged)
  7576.             cmpLayoutClass(clsSym);
  7577.  
  7578.         /* Does the class contain any nested types? */
  7579.  
  7580.         if  (clsSym->sdClass.sdcNestTypes)
  7581.         {
  7582.             SymDef          memSym;
  7583.  
  7584.             for (memSym = clsSym->sdScope.sdScope.sdsChildList;
  7585.                  memSym;
  7586.                  memSym = memSym->sdNextInScope)
  7587.             {
  7588.                 if  (memSym->sdSymKind == SYM_CLASS &&
  7589.                      memSym->sdClass.sdcAnonUnion == false)
  7590.                 {
  7591.                     cmpDeclClass(memSym);
  7592.                 }
  7593.             }
  7594.         }
  7595.     }
  7596.     else
  7597.     {
  7598.         /* We didn't find a definition, and that's a problem unless we invented it */
  7599.  
  7600.         if  (!clsSym->sdIsImplicit)
  7601.             cmpError(ERRnoClassDef, clsSym);
  7602.     }
  7603.  
  7604. RET:
  7605.  
  7606.     cmpDeclClassRec = saveRec;
  7607. }
  7608.  
  7609. /*****************************************************************************
  7610.  *
  7611.  *  Create a specific instance of the given method.
  7612.  */
  7613.  
  7614. SymDef              compiler::cmpInstanceMeth(INOUT SymDef REF newOvl,
  7615.                                                     SymDef     clsSym,
  7616.                                                     SymDef     ovlSym)
  7617. {
  7618.     ExtList         mfnDef;
  7619.     SymDef          newSym;
  7620.     TypDef          fncType;
  7621.     Ident           fncName = ovlSym->sdName;
  7622.     SymTab          ourStab = cmpCurST;
  7623.  
  7624.     /* Instantiate the type */
  7625.  
  7626.     fncType = cmpInstanceType(ovlSym->sdType);
  7627.  
  7628.     /* Declare the method symbol */
  7629.  
  7630.     if  (!newOvl)
  7631.     {
  7632.         ovlOpFlavors    ovop = ovlSym->sdFnc.sdfOper;
  7633.  
  7634.         /* This is the first overload, start the list */
  7635.  
  7636.         if  (ovop == OVOP_NONE)
  7637.             newSym = newOvl = ourStab->stDeclareSym (fncName, SYM_FNC, NS_NORM, clsSym);
  7638.         else
  7639.             newSym = newOvl = ourStab->stDeclareOper(ovop, clsSym);
  7640.     }
  7641.     else
  7642.     {
  7643.         SymDef          tmpSym;
  7644.  
  7645.         /* Make sure we don't end up with a duplicate */
  7646.  
  7647.         tmpSym = ourStab->stFindOvlFnc(newOvl, fncType);
  7648.         if  (tmpSym)
  7649.         {
  7650.             cmpRedefSymErr(tmpSym, ERRredefMem);
  7651.             return  NULL;
  7652.         }
  7653.  
  7654.         newSym = ourStab->stDeclareOvl(newOvl);
  7655.     }
  7656.  
  7657.     newSym->sdType             = fncType;
  7658.  
  7659.     newSym->sdIsDefined        = true;
  7660.     newSym->sdIsImplicit       = true;
  7661.     newSym->sdFnc.sdfInstance  = true;
  7662.  
  7663.     newSym->sdIsStatic         = ovlSym->sdIsStatic;
  7664.     newSym->sdIsSealed         = ovlSym->sdIsSealed;
  7665.     newSym->sdIsAbstract       = ovlSym->sdIsAbstract;
  7666.     newSym->sdAccessLevel      = ovlSym->sdAccessLevel;
  7667.     newSym->sdIsMember         = ovlSym->sdIsMember;
  7668.     newSym->sdIsManaged        = ovlSym->sdIsManaged;
  7669.  
  7670.     newSym->sdFnc.sdfCtor      = ovlSym->sdFnc.sdfCtor;
  7671.     newSym->sdFnc.sdfOper      = ovlSym->sdFnc.sdfOper;
  7672.     newSym->sdFnc.sdfNative    = ovlSym->sdFnc.sdfNative;
  7673.     newSym->sdFnc.sdfVirtual   = ovlSym->sdFnc.sdfVirtual;
  7674.     newSym->sdFnc.sdfExclusive = ovlSym->sdFnc.sdfExclusive;
  7675.  
  7676.     newSym->sdCompileState     = CS_DECLARED;
  7677.     newSym->sdFnc.sdfGenSym    = ovlSym;
  7678.  
  7679.     /* Remember which generic method we instantiated from */
  7680.  
  7681.     mfnDef = ourStab->stRecordMemSrcDef(fncName,
  7682.                                         NULL,
  7683.                                         NULL, // memDef->dlComp,
  7684.                                         NULL, // memDef->dlUses,
  7685.                                         NULL, // defFpos,
  7686.                                         0);   // defLine);
  7687.     mfnDef->dlHasDef     = true;
  7688.     mfnDef->dlInstance   = true;
  7689.     mfnDef->mlSym        = ovlSym;
  7690.  
  7691.     /* Save the definition record in the instance method */
  7692.  
  7693.     newSym->sdSrcDefList = mfnDef;
  7694.  
  7695.     /* Return the new method symbol to the caller */
  7696.  
  7697.     return  newSym;
  7698. }
  7699.  
  7700. /*****************************************************************************
  7701.  *
  7702.  *  Bring an instance of a generic class to "declared" state.
  7703.  */
  7704.  
  7705. void                compiler::cmpDeclInstType(SymDef clsSym)
  7706. {
  7707.     SymList         instList = NULL;
  7708.  
  7709.     SymDef          genSym;
  7710.     SymDef          memSym;
  7711.  
  7712.     int             generic;
  7713.     bool            nested;
  7714.  
  7715.     SymTab          ourStab = cmpCurST;
  7716.  
  7717.     assert(clsSym);
  7718.     assert(clsSym->sdSymKind == SYM_CLASS);
  7719.     assert(clsSym->sdCompileState < CS_DECLARED);
  7720.  
  7721. //  printf("Instance cls [%08X]: '%s'\n", clsSym, ourStab->stTypeName(NULL, clsSym, NULL, NULL, false));
  7722.  
  7723.     /* Get hold of the generic class itself */
  7724.  
  7725.     genSym  = clsSym->sdClass.sdcGenClass;
  7726.  
  7727.     /* Is this a generic instance or just a nested class ? */
  7728.  
  7729.     generic = clsSym->sdClass.sdcSpecific;
  7730.  
  7731.     if  (generic)
  7732.     {
  7733.         /* Add an entry to the current instance list */
  7734.  
  7735.         if  (cmpGenInstFree)
  7736.         {
  7737.             instList = cmpGenInstFree;
  7738.                        cmpGenInstFree = instList->slNext;
  7739.         }
  7740.         else
  7741.         {
  7742. #if MGDDATA
  7743.             instList = new SymList;
  7744. #else
  7745.             instList =    (SymList)cmpAllocPerm.nraAlloc(sizeof(*instList));
  7746. #endif
  7747.         }
  7748.  
  7749.         instList->slSym   = clsSym;
  7750.         instList->slNext  = cmpGenInstList;
  7751.                             cmpGenInstList = instList;
  7752.     }
  7753.  
  7754.     /* Walk all the members of the class and instantiate them */
  7755.  
  7756.     for (memSym = genSym->sdScope.sdScope.sdsChildList, nested = false;
  7757.          memSym;
  7758.          memSym = memSym->sdNextInScope)
  7759.     {
  7760.         Ident           name = memSym->sdName;
  7761.  
  7762. //      printf("Instantiating member '%s'\n", ourStab->stTypeName(memSym->sdType, memSym, NULL, NULL, false));
  7763.  
  7764.         switch (memSym->sdSymKind)
  7765.         {
  7766.             SymDef          newSym;
  7767.             SymDef          ovlSym;
  7768.             SymDef          newOvl;
  7769.  
  7770.         case SYM_VAR:
  7771.  
  7772.             /* Declare the specific field */
  7773.  
  7774.             newSym = ourStab->stDeclareSym(name, SYM_VAR, NS_NORM, clsSym);
  7775.  
  7776.             newSym->sdType          = cmpInstanceType(memSym->sdType);
  7777.  
  7778.             newSym->sdIsStatic      = memSym->sdIsStatic;
  7779.             newSym->sdIsSealed      = memSym->sdIsSealed;
  7780.             newSym->sdAccessLevel   = memSym->sdAccessLevel;
  7781.             newSym->sdIsMember      = memSym->sdIsMember;
  7782.             newSym->sdIsManaged     = memSym->sdIsManaged;
  7783.  
  7784.             newSym->sdCompileState  = CS_DECLARED;
  7785.             newSym->sdVar.sdvGenSym = memSym;
  7786.  
  7787. //          printf("Instance var [%08X]: '%s'\n", newSym, ourStab->stTypeName(newSym->sdType, newSym, NULL, NULL, false));
  7788.  
  7789.             break;
  7790.  
  7791.         case SYM_FNC:
  7792.  
  7793.             newOvl = NULL;
  7794.  
  7795.             for (ovlSym = memSym; ovlSym; ovlSym = ovlSym->sdFnc.sdfNextOvl)
  7796.             {
  7797.                 /* Property accessors are handled below */
  7798.  
  7799.                 if  (!ovlSym->sdFnc.sdfProperty)
  7800.                     cmpInstanceMeth(newOvl, clsSym, ovlSym);
  7801.             }
  7802.  
  7803.             break;
  7804.  
  7805.         case SYM_PROP:
  7806.  
  7807.             for (ovlSym = memSym; ovlSym; ovlSym = ovlSym->sdProp.sdpNextOvl)
  7808.             {
  7809.                 SymDef          accSym;
  7810.  
  7811.                 /* Create the specific property instance symbol */
  7812.  
  7813.                 newSym = cmpDeclPropMem(clsSym,
  7814.                                         cmpInstanceType(ovlSym->sdType),
  7815.                                         name);
  7816.  
  7817.                 newSym->sdAccessLevel   = memSym->sdAccessLevel;
  7818.                 newSym->sdIsStatic      = memSym->sdIsStatic;
  7819.                 newSym->sdIsSealed      = memSym->sdIsSealed;
  7820.                 newSym->sdIsMember      = memSym->sdIsMember;
  7821.                 newSym->sdIsManaged     = memSym->sdIsManaged;
  7822.                 newSym->sdIsDfltProp    = memSym->sdIsDfltProp;
  7823.  
  7824.                 newSym->sdCompileState  = CS_DECLARED;
  7825.  
  7826.                 /* Is this the default property of the class ? */
  7827.  
  7828.                 if  (memSym == genSym->sdClass.sdcDefProp)
  7829.                 {
  7830.                     assert(memSym->sdIsDfltProp);
  7831.  
  7832.                     newSym->sdIsDfltProp       = true;
  7833.                     clsSym->sdClass.sdcDefProp = newSym;
  7834.                 }
  7835.  
  7836.                 /* Instantiate the accessors (if any) */
  7837.  
  7838.                 if  (ovlSym->sdProp.sdpGetMeth)
  7839.                 {
  7840.                     accSym = ovlSym->sdProp.sdpGetMeth;
  7841.                     newOvl = ourStab->stLookupClsSym(accSym->sdName, clsSym);
  7842.  
  7843.                     newSym->sdProp.sdpGetMeth = cmpInstanceMeth(newOvl, clsSym, accSym);
  7844.                 }
  7845.  
  7846.                 if  (ovlSym->sdProp.sdpSetMeth)
  7847.                 {
  7848.                     accSym = ovlSym->sdProp.sdpSetMeth;
  7849.                     newOvl = ourStab->stLookupClsSym(accSym->sdName, clsSym);
  7850.  
  7851.                     newSym->sdProp.sdpSetMeth = cmpInstanceMeth(newOvl, clsSym, accSym);
  7852.                 }
  7853.             }
  7854.  
  7855.             break;
  7856.  
  7857.         case SYM_CLASS:
  7858.  
  7859.             /* Nested classes are handled in a separate pass below */
  7860.  
  7861.             if  (!memSym->sdClass.sdcGenArg)
  7862.                 nested = true;
  7863.  
  7864.             break;
  7865.  
  7866.         default:
  7867.             NO_WAY(!"unexpected generic class member");
  7868.         }
  7869.     }
  7870.  
  7871.     /* Did we have any nested classes? */
  7872.  
  7873.     if  (nested)
  7874.     {
  7875.         for (memSym = genSym->sdScope.sdScope.sdsChildList;
  7876.              memSym;
  7877.              memSym = memSym->sdNextInScope)
  7878.         {
  7879.             SymDef          newSym;
  7880.  
  7881.             if  (memSym->sdSymKind != SYM_CLASS)
  7882.                 continue;
  7883.             if  (memSym->sdClass.sdcGenArg)
  7884.                 continue;
  7885.  
  7886.             /* Declare a new nested class symbol */
  7887.  
  7888.             newSym = cmpGlobalST->stDeclareSym(memSym->sdName,
  7889.                                                SYM_CLASS,
  7890.                                                NS_HIDE,
  7891.                                                clsSym);
  7892.  
  7893.             newSym->sdAccessLevel       = memSym->sdAccessLevel;
  7894.             newSym->sdIsManaged         = memSym->sdIsManaged;
  7895.             newSym->sdClass.sdcFlavor   = memSym->sdClass.sdcFlavor;
  7896.             newSym->sdCompileState      = CS_KNOWN;
  7897.  
  7898.             newSym->sdClass.sdcSpecific = false;
  7899.             newSym->sdClass.sdcArgLst   = NULL;
  7900.             newSym->sdClass.sdcGenClass = memSym;
  7901.  
  7902.             newSym->sdTypeGet();
  7903.  
  7904.             /* Recursively process the nested class */
  7905.  
  7906.             cmpDeclInstType(newSym);
  7907.         }
  7908.     }
  7909.  
  7910.     /* Looks like we've made it */
  7911.  
  7912.     clsSym->sdCompileState = CS_DECLARED;
  7913.  
  7914.     /* Move our entry from the instantiation list to the free list */
  7915.  
  7916.     if  (generic)
  7917.     {
  7918.         cmpGenInstList = instList->slNext;
  7919.                          instList->slNext = cmpGenInstFree;
  7920.                                             cmpGenInstFree = instList;
  7921.     }
  7922. }
  7923.  
  7924. /*****************************************************************************
  7925.  *
  7926.  *  Perform any type argument substitutions in the given type, return the new
  7927.  *  type.
  7928.  */
  7929.  
  7930. TypDef              compiler::cmpInstanceType(TypDef genType, bool chkOnly)
  7931. {
  7932.     TypDef          newType;
  7933.     SymTab          ourStab;
  7934.  
  7935.     var_types       kind = genType->tdTypeKindGet();
  7936.  
  7937.     if  (kind <= TYP_lastIntrins)
  7938.         return  genType;
  7939.  
  7940.     ourStab = cmpGlobalST;
  7941.  
  7942.     switch  (kind)
  7943.     {
  7944.         ArgDscRec       argDsc;
  7945.         SymDef          clsSym;
  7946.         ArgDef          newArgs;
  7947.         SymList         instList;
  7948.  
  7949.     case TYP_PTR:
  7950.     case TYP_REF:
  7951.  
  7952.         /* Process the base type and see if it's different */
  7953.  
  7954.         newType = cmpInstanceType(genType->tdRef.tdrBase, chkOnly);
  7955.         if  (newType == genType->tdRef.tdrBase)
  7956.             return  genType;
  7957.  
  7958.         if  (chkOnly)
  7959.             return  NULL;
  7960.  
  7961.         return  ourStab->stNewRefType(genType->tdTypeKindGet(),
  7962.                                       newType,
  7963.                                 (bool)genType->tdIsImplicit);
  7964.  
  7965.     case TYP_FNC:
  7966.  
  7967.         /* Instantiate the return type */
  7968.  
  7969.         newType = cmpInstanceType(genType->tdFnc.tdfRett, chkOnly);
  7970.  
  7971.         /* See if we need to create a new argument list */
  7972.  
  7973.         argDsc  = genType->tdFnc.tdfArgs;
  7974.         newArgs = argDsc.adArgs;
  7975.  
  7976.         if  (newArgs)
  7977.         {
  7978.             ArgDef          argList = newArgs;
  7979.  
  7980.             do
  7981.             {
  7982.                 if  (cmpInstanceType(argList->adType, true) != argList->adType)
  7983.                 {
  7984.                     ArgDef          list;
  7985.                     ArgDef          last;
  7986.                     ArgDef          next;
  7987.  
  7988.                     bool            exts;
  7989.  
  7990.                     if  (chkOnly)
  7991.                         return  NULL;
  7992.  
  7993.                     /* We'll have to create a new argument list */
  7994.  
  7995. #if MGDDATA
  7996.                     argDsc = new ArgDscRec;
  7997. #else
  7998.                     memset(&argDsc, 0, sizeof(argDsc));
  7999. #endif
  8000.  
  8001.                     exts = genType->tdFnc.tdfArgs.adExtRec;
  8002.  
  8003.                     for (argList = newArgs, list = last = NULL;
  8004.                          argList;
  8005.                          argList = argList->adNext)
  8006.                     {
  8007.                         Ident           argName = NULL;
  8008.  
  8009.                         /* Create the new argument entry */
  8010.  
  8011.                         if  (exts)
  8012.                         {
  8013.                             ArgExt          xarg;
  8014. #if MGDDATA
  8015.                             next =
  8016.                             xarg = new ArgExt;
  8017. #else
  8018.                             next =
  8019.                             xarg =    (ArgExt)cmpAllocPerm.nraAlloc(sizeof(*xarg));
  8020. #endif
  8021.                             xarg->adFlags = ((ArgExt)argList)->adFlags;
  8022.                         }
  8023.                         else
  8024.                         {
  8025. #if MGDDATA
  8026.                             next = new ArgDef;
  8027. #else
  8028.                             next =    (ArgDef)cmpAllocPerm.nraAlloc(sizeof(*next));
  8029. #endif
  8030.                         }
  8031.  
  8032.                         next->adType  = cmpInstanceType(argList->adType, false);
  8033.                         next->adName  = argName;
  8034.  
  8035. #ifdef  DEBUG
  8036.                         next->adIsExt = exts;
  8037. #endif
  8038.  
  8039.                         /* Append the argument to the end of the list */
  8040.  
  8041.                         if  (list)
  8042.                             last->adNext = next;
  8043.                         else
  8044.                             list         = next;
  8045.  
  8046.                         last = next;
  8047.                     }
  8048.  
  8049.                     if  (last)
  8050.                         last->adNext = NULL;
  8051.  
  8052.                     /* Save the argument list and count */
  8053.  
  8054.                     argDsc.adCount = genType->tdFnc.tdfArgs.adCount;
  8055.                     argDsc.adArgs  = newArgs = list;
  8056.  
  8057.                     break;
  8058.                 }
  8059.  
  8060.                 argList = argList->adNext;
  8061.             }
  8062.             while (argList);
  8063.         }
  8064.  
  8065.         /* Has either the return type or the argument list changed? */
  8066.  
  8067.         if  (newArgs != genType->tdFnc.tdfArgs.adArgs ||
  8068.              newType != genType->tdFnc.tdfRett)
  8069.         {
  8070.             if  (chkOnly)
  8071.                 return  NULL;
  8072.  
  8073.             argDsc.adExtRec = genType->tdFnc.tdfArgs.adExtRec;
  8074.  
  8075.             genType = ourStab->stNewFncType(argDsc, newType);
  8076.         }
  8077.  
  8078.         return  genType;
  8079.  
  8080.     case TYP_CLASS:
  8081.  
  8082.         /* Is this a generic type argument? */
  8083.  
  8084.         clsSym = genType->tdClass.tdcSymbol;
  8085.  
  8086.         if  (!clsSym->sdClass.sdcGenArg)
  8087.             return  genType;
  8088.  
  8089.         if  (chkOnly)
  8090.             return  NULL;
  8091.  
  8092.         /* Look for the argument in the current set of bindings */
  8093.  
  8094.         for (instList = cmpGenInstList;
  8095.              instList;
  8096.              instList = instList->slNext)
  8097.         {
  8098.             SymDef          argSym;
  8099.             SymDef          genCls;
  8100.             SymDef          instSym = instList->slSym;
  8101.  
  8102.             assert(instSym->sdSymKind == SYM_CLASS);
  8103.             assert(instSym->sdClass.sdcSpecific);
  8104.  
  8105.             genCls = instSym->sdClass.sdcGenClass;
  8106.  
  8107.             assert(genCls->sdSymKind == SYM_CLASS);
  8108.             assert(genCls->sdClass.sdcGeneric);
  8109.  
  8110.             argSym = ourStab->stLookupScpSym(clsSym->sdName, genCls);
  8111.  
  8112.             if  (argSym && argSym->sdSymKind == SYM_CLASS
  8113.                         && argSym->sdClass.sdcGenArg)
  8114.             {
  8115.                 GenArgDscA      argList;
  8116.                 unsigned        argNum =  clsSym->sdClass.sdcGenArg;
  8117.  
  8118.                 /* Got the right class, now locate the argument */
  8119.  
  8120.                 argList = (GenArgDscA)instSym->sdClass.sdcArgLst;
  8121.  
  8122.                 while (--argNum)
  8123.                 {
  8124.                     argList = (GenArgDscA)argList->gaNext; assert(argList);
  8125.                 }
  8126.  
  8127.                 assert(argList && argList->gaBound);
  8128.  
  8129.                 return  argList->gaType;
  8130.             }
  8131.         }
  8132.  
  8133.         NO_WAY(!"didn't find generic argument binding");
  8134.  
  8135.         return  ourStab->stNewErrType(clsSym->sdName);
  8136.  
  8137.     case TYP_ENUM:
  8138.         return  genType;
  8139.  
  8140.     default:
  8141. #ifdef  DEBUG
  8142.         printf("Generic type: '%s'\n", ourStab->stTypeName(genType, NULL, NULL, NULL, false));
  8143. #endif
  8144.         UNIMPL(!"instantiate type");
  8145.     }
  8146.  
  8147.     UNIMPL(!"");
  8148.     return  genType;
  8149. }
  8150.  
  8151. /*****************************************************************************
  8152.  *
  8153.  *  Process all member initializers of the given class.
  8154.  */
  8155.  
  8156. void                compiler::cmpEvalMemInits(SymDef    clsSym,
  8157.                                               ExtList   constList,
  8158.                                               bool      noEval,
  8159.                                               IniList   deferLst)
  8160. {
  8161.     ExtList         constThis;
  8162.     ExtList         constLast;
  8163.  
  8164.     SymDef          clsComp;
  8165.     UseList         clsUses;
  8166.  
  8167. #ifdef  DEBUG
  8168.     clsComp = NULL;
  8169.     clsUses = NULL;
  8170. #endif
  8171.  
  8172.     /* Are we processing a deferred initializer list? */
  8173.  
  8174.     if  (deferLst)
  8175.     {
  8176.         assert(noEval == false);
  8177.  
  8178.         /* Get hold of the class and initializer list */
  8179.  
  8180.         clsSym    = deferLst->ilCls;
  8181.         constList = deferLst->ilInit;
  8182.  
  8183.         /* The class won't have deferred initializers shortly */
  8184.  
  8185.         assert(clsSym->sdClass.sdcDeferInit);
  8186.                clsSym->sdClass.sdcDeferInit = false;
  8187.  
  8188.         /* Setup scoping context for proper binding */
  8189.  
  8190.         cmpCurCls  = clsSym;
  8191.         cmpCurNS   = cmpGlobalST->stNamespOfSym(clsSym);
  8192.         cmpCurST   = cmpGlobalST;
  8193.  
  8194.         clsComp    = constList->dlComp;
  8195.         clsUses    = constList->dlUses;
  8196.  
  8197.         cmpBindUseList(clsUses);
  8198.  
  8199.         /* Move the entry to the free list */
  8200.  
  8201.         deferLst->ilNext = cmpDeferCnsFree;
  8202.                            cmpDeferCnsFree = deferLst;
  8203.     }
  8204.  
  8205.     /* Walk the list of initializers, looking for work to do */
  8206.  
  8207.     constLast = NULL;
  8208.     constThis = constList; assert(constThis);
  8209.  
  8210.     do
  8211.     {
  8212.         ExtList         constNext = (ExtList)constThis->dlNext;
  8213.  
  8214.         /* Process this member's initializer (if it hasn't happened already) */
  8215.  
  8216.         if  (constThis->mlSym)
  8217.         {
  8218.             SymDef          memSym = constThis->mlSym;
  8219.  
  8220.             assert(memSym->sdSrcDefList   == constThis);
  8221.             assert(memSym->sdCompileState == CS_DECLARED);
  8222.  
  8223.             /* Are we supposed to defer the initializer evaluation? */
  8224.  
  8225.             if  (noEval)
  8226.             {
  8227.                 /* Mark the member is having a deferred initializer */
  8228.  
  8229.                 memSym->sdVar.sdvDeferCns = true;
  8230.  
  8231.                 /* Update the last surviving entry value */
  8232.  
  8233.                 constLast = constThis;
  8234.  
  8235.                 goto NEXT;
  8236.             }
  8237.             else
  8238.             {
  8239.                 if  (memSym->sdCompileState <= CS_DECLARED)
  8240.                 {
  8241.                     /* Record the comp-unit and use-list, just in case */
  8242.  
  8243.                     clsComp = constThis->dlComp;
  8244.                     clsUses = constThis->dlUses;
  8245.  
  8246.                     /* See if the initializer is a constant */
  8247.  
  8248.                     cmpEvalMemInit(constThis);
  8249.                 }
  8250.             }
  8251.         }
  8252.         else
  8253.         {
  8254.             /* The initializer was already processed ("on demand") */
  8255.         }
  8256.  
  8257.         /* Free up the entry we've just processed */
  8258.  
  8259.         cmpTempMLrelease(constThis);
  8260.  
  8261.         /* Remove the entry from the linked list */
  8262.  
  8263.         if  (constLast)
  8264.         {
  8265.             assert(constLast->dlNext == constThis);
  8266.                    constLast->dlNext  = constNext;
  8267.         }
  8268.         else
  8269.         {
  8270.             assert(constList         == constThis);
  8271.                    constList          = constNext;
  8272.         }
  8273.  
  8274.         /* Continue with the next entry, if any */
  8275.  
  8276.     NEXT:
  8277.  
  8278.         constThis = constNext;
  8279.     }
  8280.     while (constThis);
  8281.  
  8282.     /* Were we told to defer all the initializers? */
  8283.  
  8284.     if  (noEval)
  8285.     {
  8286.         IniList         init;
  8287.  
  8288.         /* We'll have to come back to these initializers later */
  8289.  
  8290.         if  (cmpDeferCnsFree)
  8291.         {
  8292.             init = cmpDeferCnsFree;
  8293.                    cmpDeferCnsFree = init->ilNext;
  8294.         }
  8295.         else
  8296.         {
  8297. #if MGDDATA
  8298.             init = new IniList;
  8299. #else
  8300.             init =    (IniList)cmpAllocPerm.nraAlloc(sizeof(*init));
  8301. #endif
  8302.         }
  8303.  
  8304.         init->ilInit = constList;
  8305.         init->ilCls  = clsSym;
  8306.         init->ilNext = cmpDeferCnsList;
  8307.                        cmpDeferCnsList = init;
  8308.  
  8309.         /* Mark the class as having deferred initializers */
  8310.  
  8311.         clsSym->sdClass.sdcDeferInit = true;
  8312.     }
  8313.     else
  8314.     {
  8315.         /* Do we have any runtime initializers for static members? */
  8316.  
  8317.         if  (clsSym->sdClass.sdcStatInit)
  8318.         {
  8319.             /* Make sure the class has a static ctor */
  8320.  
  8321.             if  (!cmpGlobalST->stLookupOper(OVOP_CTOR_STAT, clsSym))
  8322.             {
  8323.                 declMods        ctorMod;
  8324.                 SymDef          ctorSym;
  8325.  
  8326.                 ctorMod.dmAcc = ACL_DEFAULT;
  8327.                 ctorMod.dmMod = DM_STATIC;
  8328.  
  8329.                 ctorSym = cmpDeclFuncMem(clsSym, ctorMod, cmpTypeVoidFnc, clsSym->sdName);
  8330.                 ctorSym->sdAccessLevel = ACL_PUBLIC;
  8331.                 ctorSym->sdFnc.sdfCtor = true;
  8332.                 ctorSym->sdIsImplicit  = true;
  8333.                 ctorSym->sdIsDefined   = true;
  8334.  
  8335.                 assert(clsComp && clsUses);
  8336.  
  8337.                 ctorSym->sdSrcDefList  = cmpGlobalST->stRecordMemSrcDef(clsSym->sdName,
  8338.                                                                         NULL,
  8339.                                                                         clsComp,
  8340.                                                                         clsUses,
  8341.                                                                         NULL,
  8342.                                                                         0);
  8343.             }
  8344.         }
  8345.     }
  8346. }
  8347.  
  8348. /*****************************************************************************
  8349.  *
  8350.  *  Bring the given enum type to "declared" or "evaluated" state.
  8351.  */
  8352.  
  8353. void                compiler::cmpDeclEnum(SymDef enumSym, bool namesOnly)
  8354. {
  8355.     SymTab          ourSymTab  = cmpGlobalST;
  8356.     Parser          ourParser  = cmpParser;
  8357.     Scanner         ourScanner = cmpScanner;
  8358.  
  8359.     bool            hasAttribs = false;
  8360.  
  8361.     bool            oldStyleDecl;
  8362.     bool            classParent;
  8363.  
  8364.     __int64         enumNum;
  8365.     TypDef          enumTyp;
  8366.     DefList         enumDef;
  8367.     TypDef          baseTyp;
  8368.  
  8369.     SymDef          enumList;
  8370.     SymDef          enumLast;
  8371.  
  8372.     parserState     save;
  8373.  
  8374.     assert(enumSym && enumSym->sdSymKind == SYM_ENUM);
  8375.  
  8376. //  if  (!strcmp(enumSym->sdSpelling(), "<enum type name>")) forceDebugBreak();
  8377.  
  8378.     /* If we're already at the desired compile-state, we're done */
  8379.  
  8380.     if  (enumSym->sdCompileState >= CS_CNSEVALD)
  8381.         return;
  8382.     if  (enumSym->sdCompileState == CS_DECLARED && namesOnly)
  8383.         return;
  8384.  
  8385.     /* Did this enum come from an imported symbol table ? */
  8386.  
  8387.     if  (enumSym->sdIsImport)
  8388.     {
  8389.         cycleCounterPause();
  8390.         enumSym->sdEnum.sdeMDimporter->MDimportClss(0, enumSym, 0, true);
  8391.         cycleCounterResume();
  8392.         return;
  8393.     }
  8394.  
  8395.     /* Detect amd report recursive death */
  8396.  
  8397.     if  (enumSym->sdCompileState == CS_DECLSOON)
  8398.     {
  8399.         cmpError(ERRcircDep, enumSym);
  8400.         enumSym->sdCompileState = CS_DECLARED;
  8401.         return;
  8402.     }
  8403.  
  8404.     /* Look for a definition for the enum */
  8405.  
  8406.     for (enumDef = enumSym->sdSrcDefList; enumDef; enumDef = enumDef->dlNext)
  8407.     {
  8408.         if  (enumDef->dlHasDef)
  8409.             goto GOT_DEF;
  8410.     }
  8411.  
  8412.     /* No definition is available for this type, issue an error and give up */
  8413.  
  8414.     cmpError(ERRnoEnumDef, enumSym);
  8415.  
  8416.     /* Don't bother with any more work on this guy */
  8417.  
  8418.     enumSym->sdCompileState = CS_DECLARED;
  8419.  
  8420.     return;
  8421.  
  8422. GOT_DEF:
  8423.  
  8424.     assert(enumSym->sdAccessLevel != ACL_ERROR);
  8425.  
  8426.     cmpCurCls    = enumSym;
  8427.     cmpCurNS     = cmpGlobalST->stNamespOfSym(enumSym);
  8428.     cmpCurST     = cmpGlobalST;
  8429.  
  8430. #ifdef DEBUG
  8431.     if  (cmpConfig.ccVerbose >= 2) printf("Declaring enum  '%s'\n", enumSym->sdSpelling());
  8432. #endif
  8433.  
  8434.     /* Bind any "using" declarations the enum may need */
  8435.  
  8436.     cmpBindUseList(enumDef->dlUses);
  8437.  
  8438.     /* For now we treat old-style file-scope enums differently */
  8439.  
  8440.     oldStyleDecl =  enumDef->dlOldStyle;
  8441.     classParent  = (enumSym->sdParent->sdSymKind == SYM_CLASS);
  8442.  
  8443.     /* Mark the enum type as "almost defined" */
  8444.  
  8445.     if  (enumSym->sdCompileState < CS_DECLARED)
  8446.         enumSym->sdCompileState = CS_DECLSOON;
  8447.  
  8448.     enumSym->sdIsDefined = true;
  8449.  
  8450.     /* Get hold of the enum type */
  8451.  
  8452.     enumTyp = enumSym->sdTypeGet(); assert(enumTyp && enumTyp->tdEnum.tdeSymbol == enumSym);
  8453.  
  8454.     /* The default underlying type is plain old int */
  8455.  
  8456.     baseTyp = ourSymTab->stIntrinsicType(TYP_INT);
  8457.  
  8458.     /* First process any base class specifications */
  8459.  
  8460.     cmpParser->parsePrepText(&enumDef->dlDef, enumDef->dlComp, save);
  8461.  
  8462.     /* Skip over the enum name and look for any custom attributes */
  8463.  
  8464.     while (ourScanner->scanTok.tok != tkLCurly)
  8465.     {
  8466.         switch (ourScanner->scanTok.tok)
  8467.         {
  8468.             declMods        mods;
  8469.  
  8470.             unsigned        attrMask;
  8471.             genericBuff     attrAddr;
  8472.             size_t          attrSize;
  8473.  
  8474.         case tkColon:
  8475.  
  8476.             clearDeclMods(&mods);
  8477.  
  8478.             /* Swallow the ":" and parse the base type */
  8479.  
  8480.             ourScanner->scan();
  8481.  
  8482.             if  (namesOnly)
  8483.             {
  8484.                 for (;;)
  8485.                 {
  8486.                     switch (ourScanner->scan())
  8487.                     {
  8488.                     case tkEOF:
  8489.                     case tkLCurly:
  8490.                     case tkSColon:
  8491.                         break;
  8492.  
  8493.                     default:
  8494.                         continue;
  8495.                     }
  8496.  
  8497.                     break;
  8498.                 }
  8499.             }
  8500.             else
  8501.             {
  8502.                 baseTyp = cmpParser->parseTypeSpec(&mods, true);
  8503.  
  8504.                 if  (baseTyp)
  8505.                 {
  8506.                     // ISSUE: Should we disallow the base being another enum type?
  8507.  
  8508.                     if  (!varTypeIsIntegral(baseTyp->tdTypeKindGet()) ||
  8509.                          baseTyp->tdTypeKind == TYP_BOOL)
  8510.                     {
  8511.                         cmpError(ERRnoIntType);
  8512.                     }
  8513.                 }
  8514.             }
  8515.  
  8516.             break;
  8517.  
  8518.         case tkATTRIBUTE:
  8519.  
  8520.             if  (cmpParser->parseAttribute(0, attrMask, attrAddr, attrSize))
  8521.                 hasAttribs = true;
  8522.  
  8523.             break;
  8524.  
  8525.         default:
  8526.             ourScanner->scan();
  8527.             break;
  8528.         }
  8529.     }
  8530.  
  8531.     enumTyp->tdEnum.tdeIntType = baseTyp;
  8532.  
  8533.     /* Process all of the members of the enum */
  8534.  
  8535.     assert(ourScanner->scanTok.tok == tkLCurly);
  8536.  
  8537.     enumNum  = 0;
  8538.     enumList =
  8539.     enumLast = NULL;
  8540.  
  8541.     while (ourScanner->scan() != tkRCurly)
  8542.     {
  8543.         Ident           name;
  8544.         SymDef          esym;
  8545.  
  8546.         SymXinfo        xtraList = NULL;
  8547.  
  8548.         if  (ourScanner->scanTok.tok != tkID)
  8549.         {
  8550.             /* We could have a custom attribute */
  8551.  
  8552.             while (ourScanner->scanTok.tok == tkATTRIBUTE)
  8553.             {
  8554.                 unsigned        attrMask;
  8555.                 genericBuff     attrAddr;
  8556.                 size_t          attrSize;
  8557.                 SymDef          attrCtor;
  8558.  
  8559.                 attrCtor = cmpParser->parseAttribute(ATGT_Enums,
  8560.                                                      attrMask,
  8561.                                                      attrAddr,
  8562.                                                      attrSize);
  8563.                 if  (attrSize)
  8564.                 {
  8565.                     xtraList = cmpAddXtraInfo(xtraList, attrCtor,
  8566.                                                         attrMask,
  8567.                                                         attrSize,
  8568.                                                         attrAddr);
  8569.                 }
  8570.             }
  8571.  
  8572.             if  (ourScanner->scanTok.tok == tkID)
  8573.                 goto NAM;
  8574.  
  8575.             cmpError(ERRnoIdent);
  8576.  
  8577.         ERR:
  8578.  
  8579.             cmpParser->parseResync(tkComma, tkSColon);
  8580.             if  (ourScanner->scanTok.tok != tkComma)
  8581.                 break;
  8582.  
  8583.             continue;
  8584.         }
  8585.  
  8586.     NAM:
  8587.  
  8588.         /*
  8589.             UNDONE: We don't correctly detect all recursive dependencies,
  8590.                     basically because it's too damn hard. Consider the
  8591.                     following enum declaration:
  8592.  
  8593.                     enum e
  8594.                     {
  8595.                         e1 = e3,
  8596.                         e2,
  8597.                         e3
  8598.                     };
  8599.  
  8600.                     We need to somehow notice that 'e3' depends on 'e2' which
  8601.                     depends on 'e1' which depends on 'e3', but this is rather
  8602.                     difficult.
  8603.          */
  8604.  
  8605.         name = ourScanner->scanTok.id.tokIdent;
  8606.  
  8607.         /* Make sure this is not a redefinition */
  8608.  
  8609.         esym = oldStyleDecl ? ourSymTab->stLookupNspSym(name, NS_NORM, cmpGlobalNS)
  8610.                             : ourSymTab->stLookupClsSym(name, enumSym);
  8611.  
  8612.         if  (esym)
  8613.         {
  8614.             /*  Name already declared - this is only OK if we're doing a second pass */
  8615.  
  8616.             if  (enumSym->sdCompileState == CS_DECLSOON)
  8617.             {
  8618.                 cmpRedefSymErr(esym, ERRredefMem);
  8619.                 goto ERR;
  8620.             }
  8621.  
  8622.             assert(esym->sdType == enumTyp);
  8623.         }
  8624.         else
  8625.         {
  8626.             assert(namesOnly || !oldStyleDecl);
  8627.  
  8628.             /* Declare the enum symbol */
  8629.  
  8630.             if  (oldStyleDecl)
  8631.                 esym = ourSymTab->stDeclareSym(name, SYM_ENUMVAL, NS_NORM, cmpGlobalNS);
  8632.             else
  8633.                 esym = ourSymTab->stDeclareSym(name, SYM_ENUMVAL, NS_NORM, enumSym);
  8634.  
  8635.             /* Save the enum type and other flags */
  8636.  
  8637.             esym->sdType        = enumTyp;
  8638.             esym->sdIsSealed    = true;
  8639.             esym->sdAccessLevel = enumSym->sdAccessLevel;
  8640.  
  8641.             /* Add the enum to the list */
  8642.  
  8643.             if  (enumLast)
  8644.                 enumLast->sdEnumVal.sdeNext = esym;
  8645.             else
  8646.                 enumList                    = esym;
  8647.  
  8648.             enumLast = esym;
  8649.         }
  8650.  
  8651.         /* Check for an explicit value */
  8652.  
  8653.         if  (ourScanner->scan() == tkAsg)
  8654.         {
  8655.             constVal        cval;
  8656.  
  8657.             ourScanner->scan();
  8658.  
  8659.             if  (namesOnly)
  8660.             {
  8661.                 /* For now simply skip over the value */
  8662.  
  8663.                 ourScanner->scanSkipText(tkNone, tkNone, tkComma);
  8664.             }
  8665.             else
  8666.             {
  8667.                 /* This might be a recursive call */
  8668.  
  8669.                 if  (esym->sdCompileState >= CS_DECLSOON)
  8670.                 {
  8671.                     cmpParser->parseExprComma();
  8672.                     goto NEXT;
  8673.                 }
  8674.  
  8675.                 /* Make sure we check for a recursive dependency */
  8676.  
  8677.                 esym->sdCompileState = CS_DECLSOON;
  8678.  
  8679.                 /* Parse the initializer */
  8680.  
  8681.                 if  (cmpParser->parseConstExpr(cval))
  8682.                 {
  8683.                     var_types       vtp = (var_types)cval.cvVtyp;
  8684.  
  8685.                     if  (vtp == TYP_ENUM)
  8686.                     {
  8687.                         if  (!cmpGlobalST->stMatchTypes(enumTyp, cval.cvType))
  8688.                         {
  8689.                             if  (cval.cvType->tdEnum.tdeIntType->tdTypeKind <= baseTyp->tdTypeKind)
  8690.                                 cmpWarn(WRNenumConv);
  8691.                             else
  8692.                                 cmpError(ERRnoIntExpr);
  8693.                         }
  8694.  
  8695.                         vtp = cval.cvType->tdEnum.tdeIntType->tdTypeKindGet();
  8696.                     }
  8697.                     else
  8698.                     {
  8699.                         /* Make sure the value is an integer or enum */
  8700.  
  8701.                         if  (!varTypeIsIntegral((var_types)cval.cvVtyp))
  8702.                         {
  8703.                             if  (cval.cvVtyp != TYP_UNDEF)
  8704.                                 cmpError(ERRnoIntExpr);
  8705.                         }
  8706.                     }
  8707.  
  8708.                     if  (vtp >= TYP_LONG)
  8709.                         enumNum = cval.cvValue.cvLval;
  8710.                     else
  8711.                         enumNum = cval.cvValue.cvIval;
  8712.                 }
  8713.             }
  8714.         }
  8715.  
  8716.         /* UNDONE: Make sure the value fits in the enum's base integer type */
  8717.  
  8718.         esym->sdIsDefined = !namesOnly;
  8719.  
  8720.         /* Record any linkage/security specification */
  8721.  
  8722.         esym->sdEnumVal.sdeExtraInfo = xtraList;
  8723.  
  8724.         /* Record the value in the member */
  8725.  
  8726.         if  (baseTyp->tdTypeKind >= TYP_LONG)
  8727.         {
  8728.             __int64 *       valPtr;
  8729.  
  8730.              valPtr = (__int64*)cmpAllocPerm.nraAlloc(sizeof(*valPtr));
  8731.             *valPtr = enumNum;
  8732.  
  8733.             esym->sdEnumVal.sdEV.sdevLval = valPtr;
  8734.         }
  8735.         else
  8736.         {
  8737.             esym->sdEnumVal.sdEV.sdevIval = (__int32)enumNum;
  8738.         }
  8739.  
  8740.     NEXT:
  8741.  
  8742.         /* Increment the default value and look for more */
  8743.  
  8744.         enumNum++;
  8745.  
  8746.         if  (ourScanner->scanTok.tok == tkComma)
  8747.             continue;
  8748.  
  8749.         if  (ourScanner->scanTok.tok != tkRCurly)
  8750.             cmpError(ERRnoCmRc);
  8751.  
  8752.         break;
  8753.     }
  8754.  
  8755.     /* Terminate the list if we've created one */
  8756.  
  8757.     if  (enumLast)
  8758.     {
  8759.         enumLast->sdEnumVal.sdeNext   = NULL;
  8760.         enumTyp ->tdEnum   .tdeValues = enumList;
  8761.     }
  8762.  
  8763.     /* We're done reading source text from the definition */
  8764.  
  8765.     cmpParser->parseDoneText(save);
  8766.  
  8767.     /* We've reached 'declared' or 'evaluated' state successfully */
  8768.  
  8769.     if  (namesOnly)
  8770.         enumSym->sdCompileState = CS_DECLARED;
  8771.     else
  8772.         enumSym->sdCompileState = CS_CNSEVALD;
  8773.  
  8774.     /* Were there any attributes in front of the thing ? */
  8775.  
  8776.     if  (hasAttribs && !namesOnly)
  8777.     {
  8778.         cmpParser->parsePrepText(&enumDef->dlDef, enumDef->dlComp, save);
  8779.  
  8780.         while (ourScanner->scanTok.tok != tkLCurly)
  8781.         {
  8782.             switch (ourScanner->scanTok.tok)
  8783.             {
  8784.             case tkATTRIBUTE:
  8785.  
  8786.                 unsigned        attrMask;
  8787.                 genericBuff     attrAddr;
  8788.                 size_t          attrSize;
  8789.                 SymDef          attrCtor;
  8790.  
  8791.                 /* Parse the attribute blob */
  8792.  
  8793.                 attrCtor = cmpParser->parseAttribute(ATGT_Enums,
  8794.                                                      attrMask,
  8795.                                                      attrAddr,
  8796.                                                      attrSize);
  8797.  
  8798.                 /* Add the attribute to the list of "extra info" */
  8799.  
  8800.                 if  (attrSize)
  8801.                 {
  8802.                     enumSym->sdEnum.sdeExtraInfo = cmpAddXtraInfo(enumSym->sdEnum.sdeExtraInfo,
  8803.                                                                   attrCtor,
  8804.                                                                   attrMask,
  8805.                                                                   attrSize,
  8806.                                                                   attrAddr);
  8807.                 }
  8808.  
  8809.                 break;
  8810.  
  8811.             default:
  8812.                 ourScanner->scan();
  8813.                 break;
  8814.             }
  8815.         }
  8816.  
  8817.         cmpParser->parseDoneText(save);
  8818.     }
  8819. }
  8820.  
  8821. /*****************************************************************************
  8822.  *
  8823.  *  Bring the given typedef to "declared" state.
  8824.  */
  8825.  
  8826. void                compiler::cmpDeclTdef(SymDef tdefSym)
  8827. {
  8828.     SymTab          ourSymTab  = cmpGlobalST;
  8829.     Parser          ourParser  = cmpParser;
  8830.     Scanner         ourScanner = cmpScanner;
  8831.  
  8832.     DefList         tdefDef;
  8833.     TypDef          tdefTyp;
  8834.  
  8835.     TypDef          baseTyp;
  8836.     TypDef          type;
  8837.     declMods        mods;
  8838.     Ident           name;
  8839.  
  8840.     parserState     save;
  8841.  
  8842.     assert(tdefSym && tdefSym->sdSymKind == SYM_TYPEDEF);
  8843.  
  8844.     /* If we're already at the desired compile-state, we're done */
  8845.  
  8846.     if  (tdefSym->sdCompileState >= CS_DECLARED)
  8847.         return;
  8848.  
  8849.     /* Make sure we have at least one definition for the typedefdef */
  8850.  
  8851.     tdefDef = tdefSym->sdSrcDefList;
  8852.     if  (!tdefDef)
  8853.     {
  8854.         UNIMPL(!"do we need to report an error here?");
  8855.         return;
  8856.     }
  8857.  
  8858.     /* Detect amd report recursive death */
  8859.  
  8860.     if  (tdefSym->sdCompileState == CS_DECLSOON)
  8861.     {
  8862.         cmpError(ERRcircDep, tdefSym);
  8863.         tdefSym->sdCompileState = CS_DECLARED;
  8864.         return;
  8865.     }
  8866.  
  8867.     /* Until we get there, we're on our way there */
  8868.  
  8869.     tdefSym->sdCompileState = CS_DECLSOON;
  8870.  
  8871. #ifdef DEBUG
  8872.     if  (cmpConfig.ccVerbose >= 2) printf("Declaring typedef '%s'\n", tdefSym->sdSpelling());
  8873. #endif
  8874.  
  8875.     cmpCurScp    = NULL;
  8876.     cmpCurCls    = NULL;
  8877.     cmpCurNS     = tdefSym->sdParent;
  8878.  
  8879.     if  (cmpCurNS->sdSymKind == SYM_CLASS)
  8880.     {
  8881.         cmpCurCls = cmpCurNS;
  8882.         cmpCurNS  = cmpCurNS->sdParent;
  8883.     }
  8884.  
  8885.     assert(cmpCurNS->sdSymKind == SYM_NAMESPACE);
  8886.  
  8887.     cmpBindUseList(tdefDef->dlUses);
  8888.  
  8889.     /* Mark the typedef type as defined */
  8890.  
  8891.     tdefSym->sdIsDefined = true;
  8892.  
  8893.     /* Get hold of the typedef type */
  8894.  
  8895.     tdefTyp = tdefSym->sdTypeGet(); assert(tdefTyp && tdefTyp->tdTypedef.tdtSym == tdefSym);
  8896.  
  8897.     /* Start reading the typedef's declaration */
  8898.  
  8899.     cmpParser->parsePrepText(&tdefDef->dlDef, tdefDef->dlComp, save);
  8900.  
  8901.     /* Parse any leading modifiers */
  8902.  
  8903.     ourParser->parseDeclMods(ACL_PUBLIC, &mods);
  8904.  
  8905.     /* Parse the type specification */
  8906.  
  8907.     baseTyp = ourParser->parseTypeSpec(&mods, true);
  8908.  
  8909.     /* Parse the next declarator */
  8910.  
  8911.     name = ourParser->parseDeclarator(&mods,
  8912.                                       baseTyp,
  8913.                                       DN_REQUIRED,
  8914.                                       &type,
  8915.                                       NULL,
  8916.                                       true);
  8917.  
  8918.     if  (name && type)
  8919.     {
  8920.         assert(name == tdefSym->sdName);        // ISSUE: Can this ever fail? If so, issue an error?
  8921.  
  8922.         /* Store the actual type in the typedef */
  8923.  
  8924.         tdefTyp->tdTypedef.tdtType = cmpDirectType(type);
  8925.  
  8926.         /* Make sure the declaration is properly terminated */
  8927.  
  8928.         if  (ourScanner->scanTok.tok != tkSColon)
  8929.             cmpError(ERRnoSemic);
  8930.     }
  8931.  
  8932.     /* Have we seen any other definitions for the same tdef type? */
  8933.  
  8934.     for (;;)
  8935.     {
  8936.         tdefDef = tdefDef->dlNext;
  8937.         if  (!tdefDef)
  8938.             break;
  8939.  
  8940.         UNIMPL(!"need to report a redefinition error at the right location, or is this caught earlier?");
  8941.     }
  8942.  
  8943.     /* We're done reading source text from the definition */
  8944.  
  8945.     cmpParser->parseDoneText(save);
  8946.  
  8947.     /* We've reached 'declared' state successfully */
  8948.  
  8949.     tdefSym->sdCompileState = CS_DECLARED;
  8950. }
  8951.  
  8952. /*****************************************************************************
  8953.  *
  8954.  *  Process a class member initializer - the member either is a constant, or
  8955.  *  we record the initializer so that it can be later added to the appropriate
  8956.  *  constructor body.
  8957.  */
  8958.  
  8959. void                compiler::cmpEvalMemInit(ExtList cnsDef)
  8960. {
  8961.     Scanner         ourScanner = cmpScanner;
  8962.  
  8963.     SymDef          memSym;
  8964.     SymDef          clsSym;
  8965.     parserState     save;
  8966.  
  8967.     assert(cnsDef->dlExtended);
  8968.  
  8969.     memSym = cnsDef->mlSym;    assert(memSym && memSym->sdSymKind == SYM_VAR);
  8970.     clsSym = memSym->sdParent; assert(memSym && clsSym->sdSymKind == SYM_CLASS);
  8971.  
  8972.     assert(memSym->sdVar.sdvDeferCns);
  8973.            memSym->sdVar.sdvDeferCns = false;
  8974.  
  8975.     if  (memSym->sdIsStatic && memSym->sdIsSealed)
  8976.     {
  8977.         Tree            init;
  8978.  
  8979.         /* Prepare to read the member's initializer */
  8980.  
  8981.         cmpParser->parsePrepText(&cnsDef->dlDef, cnsDef->dlComp, save);
  8982.  
  8983.         if  (ourScanner->scanTok.tok != tkLCurly)
  8984.         {
  8985.             /* Parse the initializer expression and see if it's a constant */
  8986.  
  8987.             if  (cmpParseConstDecl(memSym, NULL, &init))
  8988.             {
  8989.                 memSym->sdIsDefined = true;
  8990.  
  8991.                 if  (ourScanner->scanTok.tok != tkComma &&
  8992.                      ourScanner->scanTok.tok != tkSColon)
  8993.                 {
  8994.                     cmpError(ERRnoCmSc);
  8995.                 }
  8996.  
  8997.                 /* The member is a constant, no further init is necessary */
  8998.  
  8999.                 memSym->sdSrcDefList = NULL;
  9000.  
  9001.                 cmpParser->parseDoneText(save);
  9002.                 goto DONE;
  9003.             }
  9004.         }
  9005.  
  9006.         cmpParser->parseDoneText(save);
  9007.     }
  9008.  
  9009.     /* This member will have to be initialized in the constructor(s) */
  9010.  
  9011.     ExtList         savDef;
  9012.  
  9013.     /* Set the proper flag on the class */
  9014.  
  9015.     if  (memSym->sdIsStatic)
  9016.         clsSym->sdClass.sdcStatInit = true;
  9017.     else
  9018.         clsSym->sdClass.sdcInstInit = true;
  9019.  
  9020.     /* Save a permanent copy of this member initializer */
  9021.  
  9022. #if MGDDATA
  9023.     UNIMPL(!"how to copy this sucker when managed?");
  9024. #else
  9025.     savDef = (ExtList)cmpAllocPerm.nraAlloc(sizeof(*savDef)); *savDef = *cnsDef;
  9026. #endif
  9027.  
  9028.    /* Store the (single) definition entry in the symbol */
  9029.  
  9030.     memSym->sdSrcDefList = savDef;
  9031.  
  9032. DONE:
  9033.  
  9034.     /* Clear the entry, we won't need it again */
  9035.  
  9036.     cnsDef->mlSym = NULL;
  9037.  
  9038.     /* This member has been processed */
  9039.  
  9040.     memSym->sdCompileState = CS_CNSEVALD;
  9041. }
  9042.  
  9043. /*****************************************************************************
  9044.  *
  9045.  *  Given a constant symbol, determine its value.
  9046.  */
  9047.  
  9048. void                compiler::cmpEvalCnsSym(SymDef sym, bool saveCtx)
  9049. {
  9050.     STctxSave       save;
  9051.     DefList         defs;
  9052.  
  9053.     assert(sym);
  9054.     assert(sym->sdSymKind  == SYM_VAR);
  9055.     assert(sym->sdIsImport == false);
  9056.  
  9057.     /* Check for recursion */
  9058.  
  9059.     if  (sym->sdCompileState == CS_DECLSOON || sym->sdVar.sdvInEval)
  9060.     {
  9061.         cmpError(ERRcircDep, sym);
  9062.         sym->sdCompileState = CS_CNSEVALD;
  9063.         return;
  9064.     }
  9065.  
  9066.     assert(sym->sdVar.sdvDeferCns);
  9067.  
  9068.     /* Save the current symbol table context information, if necessary */
  9069.  
  9070.     if  (saveCtx)
  9071.         cmpSaveSTctx(save);
  9072.  
  9073.     /* Find the definition for the symbol */
  9074.  
  9075.     for (defs = sym->sdSrcDefList; defs; defs = defs->dlNext)
  9076.     {
  9077.         if  (defs->dlHasDef)
  9078.         {
  9079.             ExtList     decl;
  9080.  
  9081.             assert(defs->dlExtended); decl = (ExtList)defs;
  9082.  
  9083.             if  (sym->sdParent->sdSymKind == SYM_NAMESPACE)
  9084.             {
  9085.                 cmpDeclFileSym(decl, true);
  9086.             }
  9087.             else
  9088.             {
  9089.                 /* Set up the context for the initializer */
  9090.  
  9091.                 cmpCurCls = sym->sdParent; assert(cmpCurCls->sdSymKind == SYM_CLASS);
  9092.                 cmpCurNS  = cmpGlobalST->stNamespOfSym(cmpCurCls);
  9093.                 cmpCurST  = cmpGlobalST;
  9094.  
  9095.                 cmpBindUseList(decl->dlUses);
  9096.  
  9097.                 /* Now we can process the initializer */
  9098.  
  9099.                 cmpEvalMemInit(decl);
  9100.                 break;
  9101.             }
  9102.         }
  9103.  
  9104.         /* Non-global constants always have exactly one relevant definition */
  9105.  
  9106.         assert(sym->sdParent == cmpGlobalNS);
  9107.     }
  9108.  
  9109.     sym->sdCompileState = CS_CNSEVALD;
  9110.  
  9111.     /* Restore the current context information */
  9112.  
  9113.     if  (saveCtx)
  9114.         cmpRestSTctx(save);
  9115. }
  9116.  
  9117. /*****************************************************************************
  9118.  *
  9119.  *  Bring the given symbol to "declared" state (along with its children, if
  9120.  *  "recurse" is true). If "onlySyn" is non-NULL we only do this for that
  9121.  *  one symbol (and if we find it we return true).
  9122.  */
  9123.  
  9124. bool                compiler::cmpDeclSym(SymDef     sym,
  9125.                                          SymDef onlySym, bool recurse)
  9126. {
  9127.     SymDef          child;
  9128.  
  9129.     if  (onlySym && onlySym != sym)
  9130.     {
  9131.         /* Look inside this scope for the desired symbol */
  9132.  
  9133.         for (child = sym->sdScope.sdScope.sdsChildList;
  9134.              child;
  9135.              child = child->sdNextInScope)
  9136.         {
  9137.             if  (cmpDeclSym(child, onlySym, true))
  9138.                 return  true;
  9139.         }
  9140.  
  9141.         return  false;
  9142.     }
  9143.  
  9144.     /* For now, ignore classes imported from metadata */
  9145.  
  9146.     if  (sym->sdIsImport && sym->sdSymKind == SYM_CLASS)
  9147.         return  false;
  9148.  
  9149. #ifdef  __SMC__
  9150. //  if (sym->sdName) printf("Declare '%s'\n", sym->sdSpelling());
  9151. #endif
  9152.  
  9153.     /* We need to bring this symbol to declared state */
  9154.  
  9155.     if  (sym->sdCompileState < CS_DECLARED)
  9156.     {
  9157.         SymDef          scmp = cmpErrorComp;
  9158.  
  9159.         /* What kind of a symbol do we have? */
  9160.  
  9161. #ifdef  DEBUG
  9162.         if  (cmpConfig.ccVerbose >= 2)
  9163.             if  (sym != cmpGlobalNS)
  9164.                 printf("Declaring '%s'\n", cmpGlobalST->stTypeName(sym->sdType, sym, NULL, NULL, true));
  9165. #endif
  9166.  
  9167.         switch (sym->sdSymKind)
  9168.         {
  9169.             ExtList         dcls;
  9170.  
  9171.         case SYM_COMPUNIT:
  9172.             break;
  9173.  
  9174.         case SYM_NAMESPACE:
  9175.  
  9176.             /* Make sure the member list is properly ordered */
  9177.  
  9178.             assert(sym->sdMemListOrder);
  9179.  
  9180. #ifdef  __SMC__
  9181. //          printf("Declare [%08X] %s\n", sym->sdNS.sdnDeclList, sym->sdSpelling());
  9182. #endif
  9183.  
  9184.             /* Process any top-level names in the namespace */
  9185.  
  9186.             for (dcls = sym->sdNS.sdnDeclList; dcls;)
  9187.             {
  9188.                 ExtList         next = (ExtList)dcls->dlNext;
  9189.  
  9190.                 /*
  9191.                     Since cmpDeclFileSym() may move the entry to another list
  9192.                     we need to stash away the 'next' link before calling it.
  9193.                  */
  9194.  
  9195.                 if  (!dcls->dlEarlyDecl)
  9196.                     cmpDeclFileSym(dcls, true);
  9197.  
  9198.                 dcls = next;
  9199.             }
  9200.             break;
  9201.  
  9202.         case SYM_ENUMVAL:
  9203.             break;
  9204.  
  9205.         case SYM_CLASS:
  9206.             cmpDeclClass(sym);
  9207.             break;
  9208.  
  9209.         case SYM_ENUM:
  9210.             cmpDeclEnum(sym);
  9211.             break;
  9212.  
  9213.         case SYM_TYPEDEF:
  9214.             cmpDeclTdef(sym);
  9215.             break;
  9216.  
  9217.         case SYM_PROP:
  9218.             sym->sdCompileState = CS_COMPILED;
  9219.             break;
  9220.  
  9221.         case SYM_VAR:
  9222.             if  (sym->sdVar.sdvDeferCns)
  9223.                 cmpEvalCnsSym(sym, false);
  9224.             sym->sdCompileState = CS_COMPILED;
  9225.             break;
  9226.  
  9227.         default:
  9228.             NO_WAY(!"unexpected symbol");
  9229.         }
  9230.  
  9231.         cmpErrorComp = scmp;
  9232.     }
  9233.  
  9234.     /* Process the children if the caller so desires */
  9235.  
  9236.     if  (recurse && sym->sdSymKind == SYM_NAMESPACE)
  9237.     {
  9238.         for (child = sym->sdScope.sdScope.sdsChildList;
  9239.              child;
  9240.              child = child->sdNextInScope)
  9241.         {
  9242.             cmpDeclSym(child, NULL, true);
  9243.         }
  9244.     }
  9245.  
  9246.     return  true;
  9247. }
  9248.  
  9249. /*****************************************************************************
  9250.  *
  9251.  *  Bring the given symbol to "declared" state - the caller has already
  9252.  *  checked for imports and the symbol being declared.
  9253.  */
  9254.  
  9255. bool                compiler::cmpDeclSymDoit(SymDef sym, bool noCnsEval)
  9256. {
  9257.     SymTab          ourSymTab  = cmpGlobalST;
  9258.     Parser          ourParser  = cmpParser;
  9259.     Scanner         ourScanner = cmpScanner;
  9260.  
  9261.     STctxSave       stabState;
  9262.     scannerState    scanState;
  9263.  
  9264.     assert(sym->sdCompileState < CS_DECLARED);
  9265.     assert(sym->sdIsImport == false);
  9266.  
  9267.     /* Suspend the scanner so that we can process this symbol's definition */
  9268.  
  9269.     ourScanner->scanSuspend(scanState);
  9270.  
  9271.     /* Save the current symbol table context information */
  9272.  
  9273.     cmpSaveSTctx(stabState);
  9274.  
  9275.     /* Declare the symbol */
  9276.  
  9277.     switch (sym->sdSymKind)
  9278.     {
  9279.     case SYM_CLASS:
  9280.         cmpDeclClass(sym, noCnsEval);
  9281.         break;
  9282.  
  9283.     case SYM_ENUM:
  9284.         cmpDeclEnum(sym);
  9285.         break;
  9286.  
  9287.     case SYM_TYPEDEF:
  9288.         cmpDeclTdef(sym);
  9289.         break;
  9290.  
  9291.     default:
  9292.         cmpDeclSym(sym, sym, false);
  9293.         break;
  9294.     }
  9295.  
  9296.     /* Restore the current context information */
  9297.  
  9298.     cmpRestSTctx(stabState);
  9299.  
  9300.     /* Restore the scanner's state */
  9301.  
  9302.     ourScanner->scanResume(scanState);
  9303.  
  9304.     return (sym->sdCompileState < CS_DECLARED);
  9305. }
  9306.  
  9307. /*****************************************************************************
  9308.  *
  9309.  *  Reverse the given member list "in place".
  9310.  */
  9311.  
  9312. ExtList             compiler::cmpFlipMemList(ExtList memList)
  9313. {
  9314.     DefList         tmpMem = memList;
  9315.     DefList         prvMem = NULL;
  9316.  
  9317.     if  (memList)
  9318.     {
  9319.         do
  9320.         {
  9321.             DefList         tempCM;
  9322.  
  9323.             assert(tmpMem->dlExtended);
  9324.  
  9325.             tempCM = tmpMem->dlNext;
  9326.                      tmpMem->dlNext = prvMem;
  9327.  
  9328.             prvMem = tmpMem;
  9329.             tmpMem = tempCM;
  9330.         }
  9331.         while (tmpMem);
  9332.     }
  9333.  
  9334.     return  (ExtList)prvMem;
  9335. }
  9336.  
  9337. /*****************************************************************************
  9338.  *
  9339.  *  Recursively look for any constants and enums and try to declare them.
  9340.  */
  9341.  
  9342. void                compiler::cmpDeclConsts(SymDef sym, bool fullEval)
  9343. {
  9344.     switch (sym->sdSymKind)
  9345.     {
  9346.         ExtList         decl;
  9347.         SymDef          child;
  9348.  
  9349.     case SYM_ENUM:
  9350.         cmpDeclEnum(sym, !fullEval);
  9351.         break;
  9352.  
  9353.     case SYM_VAR:
  9354.         if  (sym->sdVar.sdvConst && fullEval)
  9355.             cmpDeclSym(sym);
  9356.         break;
  9357.  
  9358.     case SYM_NAMESPACE:
  9359.  
  9360.         /* Make sure the member list is properly ordered */
  9361.  
  9362.         if  (!sym->sdMemListOrder)
  9363.         {
  9364.             sym->sdNS.sdnDeclList = cmpFlipMemList(sym->sdNS.sdnDeclList);
  9365.             sym->sdMemListOrder   = true;
  9366.         }
  9367.  
  9368.         /* Visit all declarations in the namespace */
  9369.  
  9370.         for (decl = sym->sdNS.sdnDeclList; decl; decl = (ExtList)decl->dlNext)
  9371.         {
  9372.             if  (decl->dlEarlyDecl)
  9373.                 cmpDeclFileSym(decl, fullEval);
  9374.         }
  9375.  
  9376.         /* Recursively visit all the kid namespaces */
  9377.  
  9378.         for (child = sym->sdScope.sdScope.sdsChildList;
  9379.              child;
  9380.              child = child->sdNextInScope)
  9381.         {
  9382.             cmpDeclConsts(child, fullEval);
  9383.         }
  9384.  
  9385.         break;
  9386.     }
  9387. }
  9388.  
  9389. /*****************************************************************************
  9390.  *
  9391.  *  Start compilation - we do things such as declare any global enum types,
  9392.  *  and so on.
  9393.  */
  9394.  
  9395. bool                compiler::cmpStart(const char *defOutFileName)
  9396. {
  9397.     bool            result;
  9398.  
  9399.     /* Set a trap for any errors */
  9400.  
  9401.     setErrorTrap(this);
  9402.     begErrorTrap
  9403.     {
  9404.         const   char *  outfnm;
  9405.         char            outfbf[_MAX_PATH];
  9406.         SymDef          tmpSym;
  9407.         SymList         arrLst;
  9408.         SymDef          attrCls;
  9409.  
  9410.         const   char *  CORname;
  9411.  
  9412.         char            path[_MAX_PATH ];
  9413.         char            fnam[_MAX_FNAME];
  9414.         char            fext[_MAX_EXT  ];
  9415.  
  9416.         /* Finalize the "using" logic */
  9417.  
  9418.         cmpParser->parseUsingDone();
  9419.  
  9420.         /*
  9421.             Now we visit all namespaces we've seen, looking for enums and
  9422.             constants to pre-declare. That is, we merely enter the names
  9423.             of the enumerator values and constants in the symbol table,
  9424.             and later, in a second pass (right below), we evaluate their
  9425.             actual values.
  9426.          */
  9427.  
  9428.         cmpDeclConsts(cmpGlobalNS, false);
  9429.  
  9430.         /* Prepare the output logic (i.e. IL/metadata generation) */
  9431.  
  9432.         cmpPrepOutput();
  9433.  
  9434.         /* Make sure "String", "Object" and "Class" get declared first */
  9435.  
  9436.         if  (cmpClassObject && !cmpClassObject->sdIsImport)
  9437.             cmpDeclSym(cmpClassObject);
  9438.         if  (cmpClassString && !cmpClassString->sdIsImport)
  9439.             cmpDeclSym(cmpClassString);
  9440.         if  (cmpClassType   && !cmpClassType  ->sdIsImport)
  9441.             cmpDeclSym(cmpClassType);
  9442.  
  9443.         /* Visit all namespaces again, declare constants/enum values for real */
  9444.  
  9445.         cmpDeclConsts(cmpGlobalNS, true);
  9446.  
  9447.         /* We should have bailed by now if something really bad has happened */
  9448.  
  9449.         assert(cmpFatalCount == 0);
  9450.  
  9451.         /* Declare all the symbols we've found */
  9452.  
  9453.         cmpDeclSym(cmpGlobalNS, NULL, true);
  9454.  
  9455.         /* For now, we simply bail if there are errors */
  9456.  
  9457.         if  (cmpErrorCount)
  9458.             goto DONE;
  9459.  
  9460.         /* Are there any deferred member initializers to be processed? */
  9461.  
  9462.         if  (cmpDeferCnsList)
  9463.         {
  9464.             IniList         temp;
  9465.             IniList         init = cmpDeferCnsList;
  9466.  
  9467.             cmpCurScp = NULL;
  9468.  
  9469.             do
  9470.             {
  9471.                 /* Grab the next link, the call will trash it */
  9472.  
  9473.                 temp = init;
  9474.                        init = init->ilNext;
  9475.  
  9476.                 /* Process the initializers and free up the entry */
  9477.  
  9478.                 cmpEvalMemInits(NULL, NULL, false, temp);
  9479.             }
  9480.             while (init);
  9481.         }
  9482.  
  9483.         /* Compile any variables that are undimensioned arrays */
  9484.  
  9485.         for (arrLst = cmpNoDimArrVars; arrLst; arrLst = arrLst->slNext)
  9486.             cmpCompSym(arrLst->slSym, arrLst->slSym, false);
  9487.  
  9488.         /* Figure out the name of the output file */
  9489.  
  9490.         outfnm = cmpConfig.ccOutFileName;
  9491.  
  9492.         if  (outfnm == NULL)
  9493.         {
  9494.             if  (cmpEntryPointCls && cmpEntryPointCls->sdSymKind == SYM_CLASS)
  9495.             {
  9496.                 outfnm = cmpEntryPointCls->sdSpelling();
  9497.             }
  9498.             else if (defOutFileName && defOutFileName[0])
  9499.             {
  9500.                 outfnm = defOutFileName;
  9501.             }
  9502.             else
  9503.                 cmpFatal(ERRnoOutfName);
  9504.  
  9505.             /* Append the appropriate extension to the base file name */
  9506.  
  9507.             strcpy(outfbf, outfnm);
  9508.             strcat(outfbf, cmpConfig.ccOutDLL ? ".dll" : ".exe");
  9509.  
  9510.             outfnm = outfbf;
  9511.         }
  9512.  
  9513.         /* Invent a name for the image if we weren't given one */
  9514.  
  9515.         CORname = cmpConfig.ccOutName;
  9516.  
  9517.         if  (!CORname)
  9518.         {
  9519.             _splitpath(outfnm, NULL, NULL, fnam, fext);
  9520.              _makepath(path,   NULL, NULL, fnam, fext);
  9521.  
  9522.             CORname = path;
  9523.         }
  9524.  
  9525.         /* Set the module name */
  9526.  
  9527.         if  (cmpWmde->SetModuleProps(cmpUniConv(CORname, strlen(CORname)+1)))
  9528.             cmpFatal(ERRmetadata);
  9529.  
  9530.         /* Are we supposed to create an assembly ? */
  9531.  
  9532.         if  (cmpConfig.ccAssembly)
  9533.         {
  9534.             ASSEMBLYMETADATA    assData;
  9535.             mdAssembly          assTok;
  9536.  
  9537.             WCHAR   *           wideName;
  9538.  
  9539.             char                fpath[_MAX_PATH ];
  9540.             char                fname[_MAX_FNAME];
  9541.             char                fext [_MAX_EXT  ];
  9542.  
  9543.             cycleCounterPause();
  9544.  
  9545.             /* First get hold of the assembly emitter interface */
  9546.  
  9547.             if  (FAILED(cmpWmdd->DefineAssem(cmpWmde, &cmpWase)))
  9548.                 cmpFatal(ERRopenCOR);
  9549.  
  9550.             /* Fill in the assembly data descriptor */
  9551.  
  9552.             memset(&assData, 0, sizeof(assData));
  9553.  
  9554.             /* Strip drive/directory from the filename */
  9555.  
  9556.             _splitpath(outfnm, NULL, NULL, fname, fext);
  9557.              _makepath( fpath, NULL, NULL, fname, NULL);
  9558.  
  9559.             wideName = cmpUniConv(fpath, strlen(fpath)+1);
  9560.  
  9561.             /* Ready to start creating our assembly */
  9562.  
  9563.             if  (FAILED(cmpWase->DefineAssembly(NULL, 0,    // originator
  9564.                                                 CALG_SHA1,  // hash algorithm
  9565.                                                 wideName,   // name
  9566.                                                 &assData,   // assembly data
  9567.                                                 NULL,       // title
  9568.                                                 NULL,       // desc
  9569.                                                 wideName,   // default alias
  9570.                                                 0,          // flags
  9571.                                                 &assTok)))
  9572.             {
  9573.                 cmpFatal(ERRopenCOR);
  9574.             }
  9575.  
  9576.             cmpCurAssemblyTok = assTok;
  9577.  
  9578.             cycleCounterResume();
  9579.         }
  9580.  
  9581. #ifdef  OLD_IL
  9582.         if  (cmpConfig.ccOILgen) goto SKIP_MD;
  9583. #endif
  9584.  
  9585.         /* Generate metadata for all types */
  9586.  
  9587.         cmpGenTypMetadata(cmpGlobalNS);
  9588.  
  9589.         /* Hack: remember whether we've seen class "Attribute" */
  9590.  
  9591.         attrCls = cmpGlobalST->stLookupNspSym(cmpGlobalHT->hashString("Attribute"), NS_NORM, cmpNmSpcSystem);
  9592.  
  9593.         if  (attrCls && attrCls->sdSymKind == SYM_CLASS && attrCls->sdClass.sdcHasBodies)
  9594.             cmpAttrClsSym = attrCls;
  9595.  
  9596.         attrCls = cmpGlobalST->stLookupNspSym(cmpGlobalHT->hashString("AttributeUsageAttribute"), NS_NORM, cmpNmSpcSystem);
  9597.  
  9598.         if  (attrCls && attrCls->sdSymKind == SYM_CLASS && attrCls->sdClass.sdcHasBodies)
  9599.             cmpAuseClsSym = attrCls;
  9600.  
  9601. #ifdef  DEBUG
  9602. #ifndef __IL__
  9603.  
  9604.         if  (1)
  9605.         {
  9606.             /* Find the "System::AttributeTargets" enum */
  9607.  
  9608.             Ident           tname;
  9609.             SymDef          tsym;
  9610.  
  9611.             tname = cmpGlobalHT->hashString("AttributeTargets");
  9612.             tsym  = cmpGlobalST->stLookupNspSym(tname, NS_NORM, cmpNmSpcSystem);
  9613.  
  9614.             if  (!tsym || tsym->sdSymKind != SYM_ENUM)
  9615.             {
  9616.                 cmpGenFatal(ERRbltinTp, "System::AttributeTargets");
  9617.             }
  9618.             else if (tsym->sdCompileState >= CS_CNSEVALD)
  9619.             {
  9620.                 /* Make sure our values agree with what it's in the library */
  9621.  
  9622.                 struct
  9623.                 {
  9624.                     const   char *  atcName;
  9625.                     unsigned        atcMask;
  9626.                 }
  9627.                                 check[] =
  9628.                 {
  9629.                     { "Assembly"    , ATGT_Assemblies  },
  9630.                     { "Module"      , ATGT_Modules     },
  9631.                     { "Class"       , ATGT_Classes     },
  9632.                     { "Struct"      , ATGT_Structs     },
  9633.                     { "Enum"        , ATGT_Enums       },
  9634.                     { "Constructor" , ATGT_Constructors},
  9635.                     { "Method"      , ATGT_Methods     },
  9636.                     { "Property"    , ATGT_Properties  },
  9637.                     { "Field"       , ATGT_Fields      },
  9638.                     { "Event"       , ATGT_Events      },
  9639.                     { "Interface"   , ATGT_Interfaces  },
  9640.                     { "Parameter"   , ATGT_Parameters  },
  9641.                 };
  9642.  
  9643.                 for (unsigned i = 0; i < arraylen(check); i++)
  9644.                 {
  9645.                     const   char *  name;
  9646.                     SymDef          mem;
  9647.  
  9648.                     name = check[i].atcName;
  9649.                     mem  = cmpGlobalST->stLookupScpSym(cmpGlobalHT->hashString(name), tsym);
  9650.  
  9651.                     if  (!mem || mem->sdSymKind != SYM_ENUMVAL)
  9652.                     {
  9653.                         printf("WARNING: didn't find enum value 'System::AttributeTargets::%s'\n", name);
  9654.                     }
  9655.                     else if (mem->sdEnumVal.sdEV.sdevIval != (int)check[i].atcMask)
  9656.                     {
  9657.                         printf("WARNING: value of 'System::AttributeTargets::%s' doesn't agree with compiler\n", name);
  9658.                     }
  9659.                 }
  9660.             }
  9661.         }
  9662.  
  9663. #endif
  9664. #endif
  9665.  
  9666.         /* Generate metadata for all global functions and variables */
  9667.  
  9668.         cmpGenGlbMetadata(cmpGlobalNS);
  9669.  
  9670.         /* Generate metadata for all class/enum members */
  9671.  
  9672.         tmpSym = cmpTypeDefList;
  9673.  
  9674.         while (tmpSym)
  9675.         {
  9676.             cmpGenMemMetadata(tmpSym);
  9677.  
  9678.             switch (tmpSym->sdSymKind)
  9679.             {
  9680.             case SYM_CLASS:
  9681.                 tmpSym = tmpSym->sdClass.sdNextTypeDef;
  9682.                 break;
  9683.  
  9684.             case SYM_ENUM:
  9685.                 tmpSym = tmpSym->sdEnum .sdNextTypeDef;
  9686.                 break;
  9687.  
  9688.             default:
  9689.                 UNIMPL(!"unexpected entry in typedef list");
  9690.             }
  9691.         }
  9692.  
  9693.         /* If we're generating debug info, make sure we have the right interface */
  9694.  
  9695.         if  (cmpConfig.ccLineNums || cmpConfig.ccGenDebug)
  9696.         {
  9697.             if  (!cmpSymWriter)
  9698.             {
  9699.                 if  (cmpWmde->CreateSymbolWriter(cmpUniConv(outfnm,
  9700.                                                             strlen(outfnm)+1),
  9701.                                                             &cmpSymWriter))
  9702.                 {
  9703.                     cmpFatal(ERRmetadata);
  9704. //                  cmpConfig.ccLineNums = cmpConfig.ccGenDebug = false;
  9705.                 }
  9706.  
  9707.                 assert(cmpSymWriter);
  9708.             }
  9709.         }
  9710.  
  9711. #ifdef  OLD_IL
  9712.     SKIP_MD:
  9713. #endif
  9714.  
  9715. #ifdef  OLD_IL
  9716.  
  9717.         if  (cmpConfig.ccOILgen)
  9718.         {
  9719.             result = cmpOIgen->GOIinitialize(this, outfnm, &cmpAllocPerm);
  9720.             goto DONE;
  9721.         }
  9722.  
  9723. #endif
  9724.  
  9725.         /* Tell the output logic what file to generate */
  9726.  
  9727.         cmpPEwriter->WPEsetOutputFileName(outfnm);
  9728.  
  9729.         /* Looks like everything went fine */
  9730.  
  9731.         result = false;
  9732.  
  9733.     DONE:
  9734.  
  9735.         /* End of the error trap's "normal" block */
  9736.  
  9737.         endErrorTrap(this);
  9738.     }
  9739.     chkErrorTrap(fltErrorTrap(this, _exception_code(), NULL)) // _exception_info()))
  9740.     {
  9741.         /* Begin the error trap's cleanup block */
  9742.  
  9743.         hndErrorTrap(this);
  9744.  
  9745.         /* Some kind of a fatal error occurred */
  9746.  
  9747.         result = true;
  9748.     }
  9749.  
  9750.     return  result;
  9751. }
  9752.  
  9753. /*****************************************************************************
  9754.  *
  9755.  *  Compile the class with the matching name and all of its dependents. If
  9756.  *  NULL is passed for the class name, all the classes in the compilation
  9757.  *  units we've seen will be compiled.
  9758.  */
  9759.  
  9760. bool                compiler::cmpClass(const char *name)
  9761. {
  9762.     bool            result;
  9763.  
  9764.     /* Don't bother if something really bad has happened */
  9765.  
  9766.     if  (cmpFatalCount)
  9767.         return  false;
  9768.  
  9769.     assert(name == NULL);   // can't allow specific class compilation for now
  9770.  
  9771.     /* Set a trap for any errors */
  9772.  
  9773.     setErrorTrap(this);
  9774.     begErrorTrap
  9775.     {
  9776.         SymList         vtbls;
  9777.  
  9778.         /* Compile everything we find in all the compilation units */
  9779.  
  9780.         cmpCompSym(cmpGlobalNS, NULL, true);
  9781.  
  9782.         /* Generate any unmanaged vtables */
  9783.  
  9784.         for (vtbls = cmpVtableList; vtbls; vtbls = vtbls->slNext)
  9785.             cmpGenVtableContents(vtbls->slSym);
  9786.  
  9787.         /* Looks like we've succeeded */
  9788.  
  9789.         result = false;
  9790.  
  9791.         /* End of the error trap's "normal" block */
  9792.  
  9793.         endErrorTrap(this);
  9794.     }
  9795.     chkErrorTrap(fltErrorTrap(this, _exception_code(), NULL)) // _exception_info()))
  9796.     {
  9797.         /* Begin the error trap's cleanup block */
  9798.  
  9799.         hndErrorTrap(this);
  9800.  
  9801.         /* Some kind of a fatal error occurred */
  9802.  
  9803.         result = true;
  9804.     }
  9805.  
  9806.     return  result;
  9807. }
  9808.  
  9809. /*****************************************************************************
  9810.  *
  9811.  *  Set the current position to the definition location of the given member.
  9812.  */
  9813.  
  9814. void                compiler::cmpSetSrcPos(SymDef memSym)
  9815. {
  9816.     ExtList         defs;
  9817.     SymDef          clsSym = memSym->sdParent;
  9818.  
  9819.     assert(clsSym && clsSym->sdSymKind == SYM_CLASS);
  9820.  
  9821.     /* Try to find the source position of the member decl */
  9822.  
  9823.     for (defs = clsSym->sdClass.sdcMemDefList;
  9824.          defs;
  9825.          defs = (ExtList)defs->dlNext)
  9826.     {
  9827.         assert(defs->dlExtended);
  9828.  
  9829.         if  (defs->mlSym == memSym)
  9830.         {
  9831.             cmpErrorComp = defs->dlComp;
  9832.  
  9833.             cmpScanner->scanSetTokenPos(defs->dlDef.dsdSrcLno);
  9834.  
  9835.             return;
  9836.         }
  9837.     }
  9838.  
  9839.     cmpErrorComp = NULL;
  9840.     cmpErrorSrcf = NULL;
  9841.     cmpErrorTree = NULL;
  9842. }
  9843.  
  9844. /*****************************************************************************
  9845.  *
  9846.  *  Compile the given class.
  9847.  */
  9848.  
  9849. void                compiler::cmpCompClass(SymDef clsSym)
  9850. {
  9851.     ExtList         defs;
  9852.     SymDef          memSym;
  9853.     bool            genInst;
  9854.  
  9855.     /* Bail if the class has no method bodies at all */
  9856.  
  9857.     if  (!clsSym->sdClass.sdcHasBodies)
  9858.         return;
  9859.  
  9860.     /* Compile all members of the class */
  9861.  
  9862.     if  (!clsSym->sdClass.sdcSpecific)
  9863.     {
  9864.         /* Walk all the member definitions of the class */
  9865.  
  9866.         for (defs = clsSym->sdClass.sdcMemDefList;
  9867.              defs;
  9868.              defs = (ExtList)defs->dlNext)
  9869.         {
  9870.             assert(defs->dlExtended);
  9871.  
  9872.             if  (defs->dlHasDef && defs->mlSym)
  9873.             {
  9874.                 SymDef          memSym = defs->mlSym;
  9875.  
  9876.                 switch (memSym->sdSymKind)
  9877.                 {
  9878.                 case SYM_VAR:
  9879.                     cmpCompVar(memSym, defs);
  9880.                     break;
  9881.  
  9882.                 case SYM_FNC:
  9883.                     cmpCompFnc(memSym, defs);
  9884.                     break;
  9885.  
  9886.                 case SYM_CLASS:
  9887.                     cmpCompClass(memSym);
  9888.                     break;
  9889.                 }
  9890.             }
  9891.         }
  9892.  
  9893. //      printf("Gen code for members of %s\n", clsSym->sdSpelling());
  9894.  
  9895.         /* Compile any compiler-declared methods */
  9896.  
  9897.         if  (clsSym->sdClass.sdcOvlOpers && clsSym->sdClass.sdcFlavor != STF_DELEGATE)
  9898.         {
  9899.             SymDef          ctorSym;
  9900.  
  9901.             ctorSym = cmpGlobalST->stLookupOper(OVOP_CTOR_STAT, clsSym);
  9902.             if  (ctorSym && ctorSym->sdIsImplicit)
  9903.                 cmpCompFnc(ctorSym, NULL);
  9904.  
  9905.             ctorSym = cmpGlobalST->stLookupOper(OVOP_CTOR_INST, clsSym);
  9906.             while (ctorSym)
  9907.             {
  9908.                 if  (ctorSym->sdIsImplicit)
  9909.                     cmpCompFnc(ctorSym, NULL);
  9910.  
  9911.                 ctorSym = ctorSym->sdFnc.sdfNextOvl;
  9912.             }
  9913.         }
  9914.     }
  9915.  
  9916.     genInst = clsSym->sdClass.sdcSpecific;
  9917.  
  9918.     /*
  9919.         Make sure all methods have bodies, compile nested classes, and
  9920.         also make sure all constant members have been initialized.
  9921.      */
  9922.  
  9923.     for (memSym = clsSym->sdScope.sdScope.sdsChildList;
  9924.          memSym;
  9925.          memSym = memSym->sdNextInScope)
  9926.     {
  9927.         switch (memSym->sdSymKind)
  9928.         {
  9929.             SymDef          mfnSym;
  9930.  
  9931.         case SYM_FNC:
  9932.  
  9933.             for (mfnSym = memSym; mfnSym; mfnSym = mfnSym->sdFnc.sdfNextOvl)
  9934.             {
  9935.                 if  (genInst)
  9936.                 {
  9937.                     cmpCompFnc(mfnSym, NULL);
  9938.                     continue;
  9939.                 }
  9940.  
  9941.                 if  (!mfnSym->sdIsDefined     &&
  9942.                      !mfnSym->sdIsAbstract    &&
  9943.                      !mfnSym->sdFnc.sdfNative &&
  9944.                      !mfnSym->sdFnc.sdfDisabled)
  9945.                 {
  9946.                     if  (!cmpFindLinkInfo(mfnSym->sdFnc.sdfExtraInfo))
  9947.                     {
  9948.                         unsigned    errNum = ERRnoFnDef;
  9949.                         SymDef      errSym = mfnSym;
  9950.  
  9951.                         if  (mfnSym->sdFnc.sdfProperty)
  9952.                         {
  9953.                             bool            setter;
  9954.  
  9955.                             /* Find the matching property symbol */
  9956.  
  9957.                             errSym = cmpFindPropertyDM(mfnSym, &setter);
  9958.                             if  (errSym)
  9959.                             {
  9960.                                 assert(errSym->sdSymKind == SYM_PROP);
  9961.  
  9962.                                 assert(errSym->sdProp.sdpGetMeth == mfnSym ||
  9963.                                        errSym->sdProp.sdpSetMeth == mfnSym);
  9964.  
  9965.                                 errNum = setter ? ERRnoPropSet
  9966.                                                 : ERRnoPropGet;
  9967.                             }
  9968.                             else
  9969.                                 errSym = mfnSym;
  9970.                         }
  9971.  
  9972.                         cmpSetSrcPos(mfnSym);
  9973.                         cmpErrorQnm(errNum, errSym);
  9974.                     }
  9975.                 }
  9976.             }
  9977.             break;
  9978.  
  9979.         case SYM_VAR:
  9980.  
  9981.             if  (memSym->sdIsStatic &&
  9982.                  memSym->sdIsSealed && !memSym->sdVar.sdvHadInit)
  9983.             {
  9984.                 cmpSetSrcPos(memSym);
  9985.                 cmpErrorQnm(ERRnoVarInit, memSym);
  9986.             }
  9987.  
  9988.             break;
  9989.  
  9990.         case SYM_CLASS:
  9991.             cmpCompClass(memSym);
  9992.             break;
  9993.         }
  9994.     }
  9995. }
  9996.  
  9997. /*****************************************************************************
  9998.  *
  9999.  *  Compile the given variable.
  10000.  */
  10001.  
  10002. void                compiler::cmpCompVar(SymDef varSym, DefList srcDesc)
  10003. {
  10004.     parserState     save;
  10005.  
  10006.     memBuffPtr      addr = memBuffMkNull();
  10007.  
  10008.     Scanner         ourScanner = cmpScanner;
  10009.  
  10010.     assert(varSym->sdSymKind == SYM_VAR);
  10011.  
  10012.     /* Constants don't need any "compilation", right? */
  10013.  
  10014.     if  (varSym->sdVar.sdvConst)
  10015.         return;
  10016.  
  10017.     /* If the variable is read-only, it better have an initializer */
  10018.  
  10019. #if 0
  10020.     if  (varSym->sdIsSealed && !varSym->sdVar.sdvHadInit)
  10021.         cmpErrorQnm(ERRnoVarInit, varSym);
  10022. #endif
  10023.  
  10024.     /* Initializer for managed class members are handled elsewhere */
  10025.  
  10026.     if  (varSym->sdIsManaged)
  10027.         return;
  10028.  
  10029.     /* The type of the variable better not be a managed one */
  10030.  
  10031.     assert(varSym->sdType->tdIsManaged == false);
  10032.  
  10033.     assert(varSym->sdCompileState == CS_DECLARED ||
  10034.            varSym->sdCompileState == CS_CNSEVALD);
  10035.  
  10036. #ifdef  DEBUG
  10037.  
  10038.     if  (cmpConfig.ccVerbose)
  10039.     {
  10040.         printf("Compiling '%s'\n", cmpGlobalST->stTypeName(varSym->sdType, varSym, NULL, NULL, true));
  10041.  
  10042.         printf("    Defined at ");
  10043.         cmpGlobalST->stDumpSymDef(&srcDesc->dlDef, srcDesc->dlComp);
  10044.         printf("\n");
  10045.  
  10046.         UNIMPL("");
  10047.     }
  10048.  
  10049. #endif
  10050.  
  10051. #ifdef  __SMC__
  10052. //  printf("Beg compile '%s'\n", cmpGlobalST->stTypeName(varSym->sdType, varSym, NULL, NULL, true));
  10053. #endif
  10054.  
  10055.     /* Prepare scoping information for the function */
  10056.  
  10057.     cmpCurScp    = NULL;
  10058.     cmpCurCls    = NULL;
  10059.     cmpCurNS     = varSym->sdParent;
  10060.  
  10061.     /* Is this a class member? */
  10062.  
  10063.     if  (cmpCurNS->sdSymKind == SYM_CLASS)
  10064.     {
  10065.         /* Yes, update the class/namespace scope values */
  10066.  
  10067.         cmpCurCls = cmpCurNS;
  10068.         cmpCurNS  = cmpCurNS->sdParent;
  10069.     }
  10070.  
  10071.     assert(cmpCurNS->sdSymKind == SYM_NAMESPACE);
  10072.  
  10073.     cmpBindUseList(srcDesc->dlUses);
  10074.  
  10075.     /* Start reading from the symbol's definition text */
  10076.  
  10077.     cmpParser->parsePrepText(&srcDesc->dlDef, srcDesc->dlComp, save);
  10078.  
  10079.     /* Skip over to the initializer (it always starts with "=") */
  10080.  
  10081.     if  (srcDesc->dlDeclSkip)
  10082.         ourScanner->scanSkipSect(srcDesc->dlDeclSkip);
  10083.  
  10084.     // ISSUE: This seems fragile - what if "=" could appear within the declarator?
  10085.  
  10086.     while (ourScanner->scan() != tkAsg)
  10087.     {
  10088.         assert(ourScanner->scanTok.tok != tkEOF);
  10089.     }
  10090.  
  10091.     assert(ourScanner->scanTok.tok == tkAsg); ourScanner->scan();
  10092.  
  10093.     /* Process the variable initializer */
  10094.  
  10095.     cmpInitVarAny(addr, varSym->sdType, varSym);
  10096.     cmpInitVarEnd(varSym);
  10097.  
  10098.     /* We're done reading source text from the definition */
  10099.  
  10100.     cmpParser->parseDoneText(save);
  10101.  
  10102. #ifdef  __SMC__
  10103. //  printf("End compile '%s'\n", cmpGlobalST->stTypeName(varSym->sdType, varSym, NULL, NULL, true));
  10104. #endif
  10105.  
  10106.     /* The variable has been fully compiled */
  10107.  
  10108.     varSym->sdCompileState = CS_COMPILED;
  10109. }
  10110.  
  10111. /*****************************************************************************
  10112.  *
  10113.  *  Return a source file cookie (for debug info output) for the specified
  10114.  *  compilation unit.
  10115.  */
  10116.  
  10117. void        *       compiler::cmpSrcFileDocument(SymDef srcSym)
  10118. {
  10119.     void    *       srcDoc;
  10120.  
  10121.     assert(srcSym->sdSymKind == SYM_COMPUNIT);
  10122.  
  10123.     srcDoc = srcSym->sdComp.sdcDbgDocument;
  10124.  
  10125.     if  (!srcDoc)
  10126.     {
  10127.         const   char *  srcFil = srcSym->sdComp.sdcSrcFile;
  10128.  
  10129.         if (cmpSymWriter->DefineDocument(cmpUniConv(srcFil, strlen(srcFil)+1),
  10130.                                          &srcDoc))
  10131.         {
  10132.             cmpGenFatal(ERRdebugInfo);
  10133.         }
  10134.  
  10135.         srcSym->sdComp.sdcDbgDocument = srcDoc;
  10136.     }
  10137.  
  10138.     return  srcDoc;
  10139. }
  10140.  
  10141. /*****************************************************************************
  10142.  *
  10143.  *  Compile the given function.
  10144.  */
  10145.  
  10146. void                compiler::cmpCompFnc(SymDef fncSym, DefList srcDesc)
  10147. {
  10148.     bool            error = false;
  10149.  
  10150.     Tree            body;
  10151.  
  10152.     unsigned        fnRVA;
  10153.  
  10154.     TypDef          fncTyp = fncSym->sdType;
  10155.     bool            isMain = false;
  10156.  
  10157.     Tree            labelList  = NULL;
  10158.     SymDef          labelScope = NULL;
  10159.  
  10160.     nraMarkDsc      allocMark;
  10161.  
  10162.     Scanner         ourScanner = cmpScanner;
  10163.  
  10164.     fncSym->sdCompileState = CS_COMPILED;
  10165.  
  10166. #ifdef  __SMC__
  10167. //  printf("Beg compile '%s'\n", cmpGlobalST->stTypeName(fncSym->sdType, fncSym, NULL, NULL, true));
  10168. #endif
  10169.  
  10170. #ifdef  DEBUG
  10171.  
  10172.     if  (cmpConfig.ccVerbose)
  10173.     {
  10174.         printf("Compiling '%s'\n", cmpGlobalST->stTypeName(fncSym->sdType, fncSym, NULL, NULL, true));
  10175.  
  10176.         if  (srcDesc)
  10177.         {
  10178.             printf("    Defined at ");
  10179.             cmpGlobalST->stDumpSymDef(&srcDesc->dlDef, srcDesc->dlComp);
  10180.         }
  10181.  
  10182.         printf("\n");
  10183.     }
  10184.  
  10185. #endif
  10186.  
  10187.     assert(fncSym->sdFnc.sdfDisabled == false);
  10188.  
  10189. #ifdef  OLD_IL
  10190.     if  (!cmpConfig.ccOILgen)
  10191. #endif
  10192.     {
  10193.         /* Make sure metadata for the class has been generated */
  10194.  
  10195.         if  (!fncSym->sdFnc.sdfMDtoken)
  10196.             cmpGenFncMetadata(fncSym);
  10197.  
  10198.         /* Make sure we have a token for the method */
  10199.  
  10200.         assert(fncSym->sdFnc.sdfMDtoken);
  10201.     }
  10202.  
  10203.     /* Mark the code generator allocator */
  10204.  
  10205.     cmpAllocCGen.nraMark(&allocMark);
  10206.  
  10207.     /* Set a trap for any errors */
  10208.  
  10209.     setErrorTrap(this);
  10210.     begErrorTrap
  10211.     {
  10212.         parserState     save;
  10213.  
  10214.         SymDef          owner = fncSym->sdParent;
  10215.  
  10216.         bool            hadGoto;
  10217.  
  10218.         bool            baseCT;
  10219.         bool            thisCT;
  10220.  
  10221.         unsigned        usrLclCnt;
  10222.  
  10223. #if 0
  10224.         if  (!strcmp(fncSym->sdSpelling(), "<method name>") &&
  10225.              !strcmp( owner->sdSpelling(), "<class  name>"))
  10226.         {
  10227.              forceDebugBreak();
  10228.         }
  10229. #endif
  10230.  
  10231.         /* Tell everyone which method we're compiling */
  10232.  
  10233.         cmpCurFncSym = fncSym;
  10234.  
  10235.         /* Prepare scoping information for the function */
  10236.  
  10237.         cmpCurScp    = NULL;
  10238.         cmpCurCls    = NULL;
  10239.         cmpCurNS     = owner;
  10240.  
  10241.         /* Is this a class member? */
  10242.  
  10243.         if  (cmpCurNS->sdSymKind == SYM_CLASS)
  10244.         {
  10245.             /* It's a class member -- note its management status */
  10246.  
  10247.             cmpManagedMode = owner->sdIsManaged;
  10248.  
  10249.             /* Now update the class/namespace scope values */
  10250.  
  10251.             cmpCurCls = cmpCurNS;
  10252.  
  10253.             do
  10254.             {
  10255.                 cmpCurNS  = cmpCurNS->sdParent;
  10256.             }
  10257.             while (cmpCurNS->sdSymKind == SYM_CLASS);
  10258.         }
  10259.         else
  10260.             cmpManagedMode = false;
  10261.  
  10262.         assert(cmpCurNS && cmpCurNS->sdSymKind == SYM_NAMESPACE);
  10263.  
  10264.         /* Is this a function with a compiler-supplied body? */
  10265.  
  10266.         if  (fncSym->sdIsImplicit)
  10267.         {
  10268.             char    *       fnBody;
  10269.  
  10270.             /* Is this a method of an instance of a generic type ? */
  10271.  
  10272.             if  (fncSym->sdFnc.sdfInstance)
  10273.             {
  10274.                 Tree            stub;
  10275.  
  10276.                 assert(fncSym->sdFnc.sdfGenSym);
  10277.  
  10278.                 /* Create a fake method body */
  10279.  
  10280.                 stub = cmpCreateExprNode(NULL, TN_INST_STUB, cmpTypeVoid, NULL, NULL);
  10281.                 stub->tnFlags |= TNF_NOT_USER;
  10282.  
  10283.                 /* Create a block to hold the stub, the IL generator does the rest */
  10284.  
  10285.                 body = cmpCreateExprNode(NULL, TN_BLOCK, cmpTypeVoid);
  10286.  
  10287.                 body->tnBlock.tnBlkDecl = NULL;
  10288.                 body->tnBlock.tnBlkStmt = cmpCreateExprNode(NULL, TN_LIST, cmpTypeVoid, stub, NULL);
  10289.  
  10290.                 /* Clear all the flags the parser would otherwise set */
  10291.  
  10292.                 labelList = NULL;
  10293.  
  10294.                 usrLclCnt = 0;
  10295.  
  10296.                 hadGoto   = false;
  10297.                 baseCT    = fncSym->sdFnc.sdfCtor;
  10298.                 thisCT    = fncSym->sdFnc.sdfCtor;
  10299.  
  10300.                 goto GOT_FNB;
  10301.             }
  10302.  
  10303.             /* This is a compiler-defined function, create a body for it */
  10304.  
  10305.             assert(owner && owner->sdSymKind == SYM_CLASS);
  10306.  
  10307.             /* There is no real source code for this function */
  10308.  
  10309.             cmpCurFncSrcBeg = 0;
  10310.  
  10311.             {
  10312.                 assert(fncSym->sdFnc.sdfCtor);
  10313.  
  10314. //              printf("gen ctor %08X for '%s'\n", fncSym, fncSym->sdParent->sdSpelling());
  10315.  
  10316.                 /* Create the body for the compiler-declared ctor */
  10317.  
  10318.                 if  (owner->sdType->tdClass.tdcValueType || fncSym->sdIsStatic)
  10319.                     fnBody = "ctor() {              }\x1A";
  10320.                 else
  10321.                     fnBody = "ctor() { baseclass(); }\x1A";
  10322.             }
  10323.  
  10324.             /* Read from the supplied function definition */
  10325.  
  10326.             cmpScanner->scanString(fnBody, &cmpAllocPerm);
  10327.         }
  10328.         else
  10329.         {
  10330.             /* Make sure the function has been properly marked */
  10331.  
  10332.             assert(fncSym->sdIsDefined);
  10333.  
  10334.             /* Start reading from the symbol's definition text */
  10335.  
  10336.             cmpParser->parsePrepText(&srcDesc->dlDef, srcDesc->dlComp, save);
  10337.  
  10338.             /* Remember where the function body starts */
  10339.  
  10340.             cmpCurFncSrcBeg = ourScanner->scanGetTokenLno();
  10341.  
  10342.             if  (fncSym->sdFnc.sdfEntryPt)
  10343.             {
  10344.                 /* Did we already have an entry point? */
  10345.  
  10346.                 if  (cmpFnSymMain)
  10347.                     cmpErrorQSS(ERRmulEntry, cmpFnSymMain, fncSym);
  10348.  
  10349.                 cmpFnSymMain = fncSym;
  10350.                 isMain       = true;
  10351.             }
  10352.         }
  10353.  
  10354.         /* Skip to the function's body (it always starts with "{") */
  10355.  
  10356.         while (ourScanner->scanTok.tok != tkLCurly)
  10357.         {
  10358.             assert(ourScanner->scanTok.tok != tkEOF);
  10359.  
  10360.             if  (ourScanner->scan() == tkColon && fncSym->sdFnc.sdfCtor)
  10361.             {
  10362.                 /* Presumably we have a base class ctor call */
  10363.  
  10364.                 break;
  10365.             }
  10366.         }
  10367.  
  10368.         /* Is there a definition record for the symbol? */
  10369.  
  10370.         if  (srcDesc)
  10371.         {
  10372.             cmpBindUseList(srcDesc->dlUses);
  10373.             cmpCurComp   = srcDesc->dlComp;
  10374.         }
  10375.         else
  10376.         {
  10377.  
  10378.             {
  10379.                 assert(fncSym->sdIsImplicit);
  10380.                 assert(fncSym->sdSrcDefList);
  10381.  
  10382.                 cmpBindUseList(fncSym->sdSrcDefList->dlUses);
  10383.                 cmpCurComp   = fncSym->sdSrcDefList->dlComp;
  10384.             }
  10385.         }
  10386.  
  10387.         /* Parse the body of the function */
  10388.  
  10389.         body = cmpParser->parseFuncBody(fncSym, &labelList,
  10390.                                                 &usrLclCnt,
  10391.                                                 &hadGoto,
  10392.                                                 &baseCT,
  10393.                                                 &thisCT);
  10394.  
  10395.         if  (body)
  10396.         {
  10397.             SymDef          fnScp;
  10398.             mdSignature     fnSig;
  10399.  
  10400.         GOT_FNB:
  10401.  
  10402. #ifdef  DEBUG
  10403. #ifdef  SHOW_CODE_OF_THIS_FNC
  10404.             cmpConfig.ccDispCode = !strcmp(fncSym->sdSpelling(), SHOW_CODE_OF_THIS_FNC);
  10405. #endif
  10406. #endif
  10407.  
  10408.             /* Note the end source line# of the function (for debug info purposes) */
  10409.  
  10410.             if  (body && body->tnOper == TN_BLOCK)
  10411.                 cmpCurFncSrcEnd = body->tnBlock.tnBlkSrcEnd;
  10412.             else
  10413.                 cmpCurFncSrcEnd = ourScanner->scanGetTokenLno();
  10414.  
  10415.             if  (cmpConfig.ccLineNums || cmpConfig.ccGenDebug)
  10416.             {
  10417.                 if  (cmpSymWriter->OpenMethod(fncSym->sdFnc.sdfMDtoken))
  10418.                     cmpGenFatal(ERRdebugInfo);
  10419.             }
  10420.  
  10421.             /* Can/should there be a call to the base class ctor? */
  10422.  
  10423.             cmpBaseCTcall =
  10424.             cmpBaseCTisOK = false;
  10425.  
  10426.             cmpThisCTcall = thisCT;
  10427.  
  10428.             if  (fncSym->sdFnc.sdfCtor)
  10429.             {
  10430.                 TypDef          ownerTyp = owner->sdType;
  10431.  
  10432.                 assert(owner->sdSymKind == SYM_CLASS);
  10433.  
  10434.                 if  (ownerTyp->tdClass.tdcBase && !ownerTyp->tdClass.tdcValueType)
  10435.                 {
  10436.                     cmpBaseCTcall = !baseCT;
  10437.                     cmpBaseCTisOK = true;
  10438.                 }
  10439.             }
  10440.  
  10441.             /* Prepare the IL generator for the function */
  10442.  
  10443. #ifdef  OLD_IL
  10444.             if  (!cmpConfig.ccOILgen)
  10445. #endif
  10446.             {
  10447.                 cmpILgen->genFuncBeg(cmpGlobalST, fncSym, usrLclCnt);
  10448.  
  10449.                 /* Make sure metadata has been generated for the containing class */
  10450.  
  10451.                 if  (fncSym->sdIsMember)
  10452.                 {
  10453.                     assert(owner && owner->sdSymKind == SYM_CLASS);
  10454.  
  10455.                     cmpGenClsMetadata(owner);
  10456.                 }
  10457.             }
  10458.  
  10459.             /* Did the function define any labels? */
  10460.  
  10461.             if  (labelList)
  10462.             {
  10463.                 Tree            label;
  10464.  
  10465.                 /* Create the label scope */
  10466.  
  10467.                 cmpLabScp = labelScope = cmpGlobalST->stDeclareLcl(NULL,
  10468.                                                                    SYM_SCOPE,
  10469.                                                                    NS_HIDE,
  10470.                                                                    NULL,
  10471.                                                                    &cmpAllocCGen);
  10472.  
  10473.                 /* Declare all the labels and create IL entries for them */
  10474.  
  10475.                 for (label = labelList;;)
  10476.                 {
  10477.                     Tree            labx;
  10478.                     Ident           name;
  10479.  
  10480.                     assert(label->tnOper == TN_LABEL);
  10481.                     labx = label->tnOp.tnOp1;
  10482.                     assert(labx);
  10483.                     assert(labx->tnOper == TN_NAME);
  10484.  
  10485.                     name = labx->tnName.tnNameId;
  10486.  
  10487.                     /* Make sure this is not a redefinition */
  10488.  
  10489.                     if  (cmpGlobalST->stLookupLabSym(name, labelScope))
  10490.                     {
  10491.                         cmpError(ERRlabRedef, name);
  10492.                         label->tnOp.tnOp1 = NULL;
  10493.                     }
  10494.                     else
  10495.                     {
  10496.                         SymDef          labSym;
  10497.  
  10498.                         /* Declare a label symbol */
  10499.  
  10500.                         labSym = cmpGlobalST->stDeclareLab(name,
  10501.                                                            labelScope,
  10502.                                                            &cmpAllocCGen);
  10503.  
  10504.                         /* Store the symbol in the label node */
  10505.  
  10506.                         labx->tnOper            = TN_LCL_SYM;
  10507.                         labx->tnLclSym.tnLclSym = labSym;
  10508.  
  10509.                         /* Create the IL label for the symbol */
  10510.  
  10511.                         labSym->sdLabel.sdlILlab = cmpILgen->genFwdLabGet();
  10512.                     }
  10513.  
  10514.                     label = label->tnOp.tnOp2;
  10515.                     if  (label == NULL)
  10516.                         break;
  10517.                     if  (label->tnOper == TN_LIST)
  10518.                     {
  10519.                         label = label->tnOp.tnOp2;
  10520.                         if  (label == NULL)
  10521.                             break;
  10522.                     }
  10523.                 }
  10524.             }
  10525.  
  10526.             /* Generate IL for the function */
  10527.  
  10528.             fnScp = cmpGenFNbodyBeg(fncSym, body, hadGoto, usrLclCnt);
  10529.  
  10530.             /* Did we have any errors? */
  10531.  
  10532.             if  (cmpErrorCount)
  10533.             {
  10534.                 /* Tell the IL generetaor to wrap up, no code is needed */
  10535.  
  10536.                 fnRVA = cmpILgen->genFuncEnd(0, true);
  10537.             }
  10538. #ifdef  OLD_IL
  10539.             else if (cmpConfig.ccOILgen)
  10540.             {
  10541.                 fnRVA = 0;
  10542.             }
  10543. #endif
  10544.             else
  10545.             {
  10546.                 /* Generate a signature for local variables  */
  10547.  
  10548.                 fnSig = cmpGenLocalSig(fnScp, cmpILgen->genGetLclCnt());
  10549.  
  10550.                 /* Finish up codegen and get the function's RVA */
  10551.  
  10552.                 fnRVA = cmpILgen->genFuncEnd(fnSig, false);
  10553.             }
  10554.  
  10555.             /* Finish up any book-keeping in the code generator */
  10556.  
  10557.             cmpGenFNbodyEnd();
  10558.  
  10559.             /* If we've successfully generated code for the function ... */
  10560.  
  10561.             if  (fnRVA)
  10562.             {
  10563.                 unsigned        flags = miManaged|miIL;
  10564.  
  10565.                 if  (fncSym->sdFnc.sdfExclusive)
  10566.                     flags |= miSynchronized;
  10567.  
  10568.                 /* Set the RVA for the function's metadata definition */
  10569.  
  10570.                 cycleCounterPause();
  10571.                 if  (cmpWmde->SetRVA(fncSym->sdFnc.sdfMDtoken, fnRVA))
  10572.                     cmpFatal(ERRmetadata);
  10573.                 if  (cmpWmde->SetMethodImplFlags(fncSym->sdFnc.sdfMDtoken, flags))
  10574.                     cmpFatal(ERRmetadata);
  10575.                 cycleCounterResume();
  10576.  
  10577.                 cmpFncCntComp++;
  10578.  
  10579.                 /* Is this the main entry point? */
  10580.  
  10581.                 if  (isMain)
  10582.                 {
  10583.                     cmpTokenMain = fncSym->sdFnc.sdfMDtoken;
  10584.  
  10585.                     if  (cmpConfig.ccGenDebug)
  10586.                     {
  10587.                         if (cmpSymWriter->SetUserEntryPoint(fncSym->sdFnc.sdfMDtoken))
  10588.                             cmpGenFatal(ERRdebugInfo);
  10589.                     }
  10590.                 }
  10591.  
  10592.                 /* Are we generating line# info? */
  10593.  
  10594.                 if  (cmpConfig.ccLineNums || cmpConfig.ccGenDebug)
  10595.                 {
  10596.                     size_t          lineCnt = cmpILgen->genLineNumOutput(NULL,
  10597.                                                                          NULL);
  10598.  
  10599.                     /* Fixup lexical scope start/end offsets for debug info */
  10600.  
  10601.                     if  (cmpConfig.ccGenDebug)
  10602.                         cmpFixupScopes(fnScp);
  10603.  
  10604.                     if  (lineCnt && srcDesc)
  10605.                     {
  10606.                         void    *       srcDoc;
  10607.                         unsigned*       lineTab;
  10608.                         unsigned*       offsTab;
  10609.  
  10610.                         assert(cmpSymWriter);
  10611.  
  10612.                         /* Make sure we have a token for the source file */
  10613.  
  10614.                         srcDoc = cmpSrcFileDocument(srcDesc->dlComp);
  10615.  
  10616.                         /* Allocate and fill in the line# table */
  10617.  
  10618.                         lineTab = (unsigned*)cmpAllocCGen.nraAlloc(lineCnt * sizeof(*lineTab));
  10619.                         offsTab = (unsigned*)cmpAllocCGen.nraAlloc(lineCnt * sizeof(*offsTab));
  10620.  
  10621.                         cmpILgen->genLineNumOutput(offsTab, lineTab);
  10622.  
  10623.                         /* Attach the line# table to the method */
  10624.  
  10625.                         if  (cmpSymWriter->DefineSequencePoints(srcDoc,
  10626.                                                                 lineCnt,
  10627.                                                                 offsTab,
  10628.                                                                 lineTab))
  10629.                         {
  10630.                             cmpGenFatal(ERRdebugInfo);
  10631.                         }
  10632.                     }
  10633.                 }
  10634.             }
  10635.  
  10636.             if  (cmpConfig.ccLineNums || cmpConfig.ccGenDebug)
  10637.             {
  10638.                 if  (cmpSymWriter->CloseMethod())
  10639.                     cmpGenFatal(ERRdebugInfo);
  10640.             }
  10641.         }
  10642.  
  10643.         cmpThisSym = NULL;
  10644.  
  10645.         if  (!fncSym->sdIsImplicit)
  10646.         {
  10647.             /* We're done reading source text from the definition */
  10648.  
  10649.             cmpParser->parseDoneText(save);
  10650.         }
  10651.  
  10652.         /* End of the error trap's "normal" block */
  10653.  
  10654.         endErrorTrap(this);
  10655.     }
  10656.     chkErrorTrap(fltErrorTrap(this, _exception_code(), NULL)) // _exception_info()))
  10657.     {
  10658.         /* Begin the error trap's cleanup block */
  10659.  
  10660.         hndErrorTrap(this);
  10661.  
  10662.         /* Remember that something horrible has happened */
  10663.  
  10664.         error = true;
  10665.     }
  10666.  
  10667.     /* Did we have any label definitions? */
  10668.  
  10669.     if  (labelList)
  10670.     {
  10671.         Tree            label;
  10672.  
  10673.         for (label = labelList;;)
  10674.         {
  10675.             Tree            labx;
  10676.  
  10677.             assert(label->tnOper == TN_LABEL);
  10678.             labx = label->tnOp.tnOp1;
  10679.  
  10680.             if  (labx)
  10681.             {
  10682.                 assert(labx->tnOper == TN_LCL_SYM);
  10683.  
  10684.                 cmpGlobalST->stRemoveSym(labx->tnLclSym.tnLclSym);
  10685.             }
  10686.  
  10687.             label = label->tnOp.tnOp2;
  10688.             if  (label == NULL)
  10689.                 break;
  10690.             if  (label->tnOper == TN_LIST)
  10691.             {
  10692.                 label = label->tnOp.tnOp2;
  10693.                 if  (label == NULL)
  10694.                     break;
  10695.             }
  10696.         }
  10697.     }
  10698.  
  10699.     /* Release any memory we've allocated during code generation */
  10700.  
  10701.     cmpAllocCGen.nraRlsm(&allocMark);
  10702.  
  10703. #ifdef  __SMC__
  10704. //  printf("End compile '%s'\n", cmpGlobalST->stTypeName(fncSym->sdType, fncSym, NULL, NULL, true));
  10705. #endif
  10706.  
  10707.     /* Raise alarm if things are in bad shape */
  10708.  
  10709.     if  (error)
  10710.         jmpErrorTrap(this);
  10711.  
  10712.     return;
  10713. }
  10714.  
  10715. /*****************************************************************************
  10716.  *
  10717.  *  Bring the given symbol to "compiled" state (along with its children, if
  10718.  *  "recurse" is true). If "onlySyn" is non-NULL we only do this for that
  10719.  *  one symbol (and if we find it we return true).
  10720.  */
  10721.  
  10722. bool                compiler::cmpCompSym(SymDef     sym,
  10723.                                          SymDef onlySym, bool recurse)
  10724. {
  10725.     SymDef          child;
  10726.  
  10727. //  if  (sym->sdName) printf("Compiling '%s'\n", sym->sdSpelling());
  10728.  
  10729.     if  (onlySym && onlySym != sym && sym->sdHasScope())
  10730.     {
  10731.         /* Look inside this scope for the desired symbol */
  10732.  
  10733.         for (child = sym->sdScope.sdScope.sdsChildList;
  10734.              child;
  10735.              child = child->sdNextInScope)
  10736.         {
  10737.             if  (cmpCompSym(child, onlySym, true))
  10738.                 return  true;
  10739.         }
  10740.  
  10741.         return  false;
  10742.     }
  10743.  
  10744.     /* No need to compile classes imported from metadata */
  10745.  
  10746.     if  (sym->sdIsImport && sym->sdSymKind == SYM_CLASS)
  10747.         return  false;
  10748.  
  10749.     /* We need to bring this symbol to compiled state */
  10750.  
  10751.     if  (sym->sdCompileState < CS_COMPILED)
  10752.     {
  10753.         /* What kind of a symbol do we have? */
  10754.  
  10755. #ifdef  DEBUG
  10756.         if  (cmpConfig.ccVerbose >= 2)
  10757.             if  (sym != cmpGlobalNS)
  10758.                 printf("Compiling '%s'\n", cmpGlobalST->stTypeName(sym->sdType, sym, NULL, NULL, true));
  10759. #endif
  10760.  
  10761.         switch (sym->sdSymKind)
  10762.         {
  10763.             DefList         defs;
  10764.             bool            defd;
  10765.  
  10766.         case SYM_NAMESPACE:
  10767.         case SYM_COMPUNIT:
  10768.         case SYM_TYPEDEF:
  10769.         case SYM_ENUMVAL:
  10770.         case SYM_ENUM:
  10771.             break;
  10772.  
  10773.         case SYM_VAR:
  10774.         case SYM_FNC:
  10775.  
  10776.             do
  10777.             {
  10778.  
  10779.                 /* We only expect file-scope symbols here */
  10780.  
  10781.                 assert(sym->sdParent == cmpGlobalNS);
  10782.  
  10783.                 /* Look for a definition of the symbol */
  10784.  
  10785.                 defd = false;
  10786.  
  10787.                 for (defs = sym->sdSrcDefList; defs; defs = defs->dlNext)
  10788.                 {
  10789.                     if  (defs->dlHasDef)
  10790.                     {
  10791.                         defd = true;
  10792.  
  10793.                         if  (sym->sdSymKind == SYM_VAR)
  10794.                             cmpCompVar(sym, defs);
  10795.                         else
  10796.                             cmpCompFnc(sym, defs);
  10797.                     }
  10798.                 }
  10799.  
  10800.                 /* Space for unmanaged global vars must be allocated if no def */
  10801.  
  10802.                 if  (!defd && sym->sdSymKind  == SYM_VAR
  10803.                            && sym->sdIsImport == false)
  10804.                 {
  10805.                     SymDef          owner = sym->sdParent;
  10806.  
  10807.                     if  (owner->sdSymKind != SYM_CLASS || !owner->sdIsManaged)
  10808.                         cmpAllocGlobVar(sym);
  10809.                 }
  10810.  
  10811.                 /* For functions, make sure we process all overloads */
  10812.  
  10813.                 if  (sym->sdSymKind != SYM_FNC)
  10814.                     break;
  10815.  
  10816.                 sym = sym->sdFnc.sdfNextOvl;
  10817.             }
  10818.             while (sym);
  10819.  
  10820.             return  true;
  10821.  
  10822.         case SYM_CLASS:
  10823.             cmpCompClass(sym);
  10824.             break;
  10825.  
  10826.         default:
  10827.             NO_WAY(!"unexpected symbol");
  10828.         }
  10829.     }
  10830.  
  10831.     /* Process the children if the caller so desires */
  10832.  
  10833.     if  (recurse && sym->sdSymKind == SYM_NAMESPACE)
  10834.     {
  10835.         for (child = sym->sdScope.sdScope.sdsChildList;
  10836.              child;
  10837.              child = child->sdNextInScope)
  10838.         {
  10839.             cmpCompSym(child, NULL, true);
  10840.         }
  10841.     }
  10842.  
  10843.     return  true;
  10844. }
  10845.  
  10846. /*****************************************************************************
  10847.  *
  10848.  *  Binds a qualified name and returns the symbol it corresponds to, or NULL
  10849.  *  if there was an error. When 'notLast' is true, the very last name is not
  10850.  *  bound, and the caller will be the one to bind it.
  10851.  */
  10852.  
  10853. SymDef              compiler::cmpBindQualName(QualName qual, bool notLast)
  10854. {
  10855.     SymDef          scope;
  10856.     unsigned        namex;
  10857.     unsigned        namec = qual->qnCount - (int)notLast;
  10858.  
  10859.     SymTab          stab  = cmpGlobalST;
  10860.  
  10861.     /* Bind all names in the sequence (except maybe for the last one) */
  10862.  
  10863.     assert((int)namec > 0);
  10864.  
  10865.     for (scope = NULL, namex = 0; namex < namec; namex++)
  10866.     {
  10867.         Ident           name = qual->qnTable[namex];
  10868.  
  10869.         /* Is this the first name or not? */
  10870.  
  10871.         if  (scope)
  10872.         {
  10873.             SymDef          sym;
  10874.  
  10875.             switch(scope->sdSymKind)
  10876.             {
  10877.             case SYM_NAMESPACE:
  10878.                 sym = stab->stLookupNspSym(name, NS_NORM, scope);
  10879.                 if  (!sym)
  10880.                 {
  10881.                     cmpError(ERRundefNspm, scope, name);
  10882.                     return NULL;
  10883.                 }
  10884.                 break;
  10885.  
  10886.             case SYM_CLASS:
  10887.                 sym = stab->stLookupClsSym(name, scope);
  10888.                 if  (!sym)
  10889.                 {
  10890.                     cmpError(ERRnoSuchMem, scope, name);
  10891.                     return NULL;
  10892.                 }
  10893.                 break;
  10894.  
  10895.             default:
  10896.                 cmpError(ERRnoMems, scope);
  10897.                 return NULL;
  10898.             }
  10899.  
  10900.             scope = sym;
  10901.         }
  10902.         else
  10903.         {
  10904.             /* This is the initial name, perform a "normal" lookup */
  10905.  
  10906. //          scope = stab->stLookupSym(name, (name_space)(NS_TYPE|NS_NORM));
  10907.             scope = stab->stLookupSym(name, NS_TYPE);
  10908.             if  (!scope)
  10909.             {
  10910.                 cmpError(ERRundefName, name);
  10911.                 return NULL;
  10912.             }
  10913.         }
  10914.     }
  10915.  
  10916.     return  scope;
  10917. }
  10918.  
  10919. /*****************************************************************************
  10920.  *
  10921.  *  We're declaring a symbol with a "using" list - make sure all the "using"
  10922.  *  clauses for the symbol have been bound (and report any errors that may
  10923.  *  result from the binding).
  10924.  */
  10925.  
  10926. void                compiler::cmpBindUseList(UseList useList)
  10927. {
  10928.     SymDef          saveScp;
  10929.     SymDef          saveCls;
  10930.     SymDef          saveNS;
  10931.  
  10932.     UseList         bsect;
  10933.     UseList         esect;
  10934.     UseList         outer;
  10935.     UseList         inner;
  10936.  
  10937.     assert(useList);
  10938.     assert(useList->ulAnchor);
  10939.  
  10940.     /* If the section is already bound, we're done */
  10941.  
  10942.     if  (useList->ulBound)
  10943.     {
  10944.         cmpCurUses = useList;
  10945.         return;
  10946.     }
  10947.  
  10948.     /* Find the end of this "using" section */
  10949.  
  10950.     bsect = esect = useList->ulNext;
  10951.     if  (!esect)
  10952.         goto EXIT;
  10953.  
  10954.     /* Look for the end of the section (i.e. the next anchor) */
  10955.  
  10956.     while (esect->ulAnchor == false)
  10957.     {
  10958.         assert(useList->ulBound == false);
  10959.  
  10960.         esect = esect->ulNext;
  10961.         if  (!esect)
  10962.             goto BIND;
  10963.     }
  10964.  
  10965.     /* We've run into the next section - has that one been bound yet? */
  10966.  
  10967.     if  (!esect->ulBound)
  10968.         cmpBindUseList(esect);
  10969.  
  10970. BIND:
  10971.  
  10972. //  printf("binduselist('%s' .. '%s')\n",       useList->ul.ulSym->sdSpelling(),
  10973. //                                        esect ? esect->ul.ulSym->sdSpelling() : "<END>");
  10974.  
  10975.     /* Nothing to do if the section is empty */
  10976.  
  10977.     if  (bsect == esect)
  10978.         goto EXIT;
  10979.  
  10980.     /*
  10981.         The rule is that the "using" clauses for a given scope are bound
  10982.         and go into effect in parallel. We do this by setting the "using"
  10983.         list just above the section we're binding and only after all of
  10984.         the clauses have been processed do we make them take effect.
  10985.  
  10986.         First save the current scoping state and switch to the scope that
  10987.         the "using" clauses are found in.
  10988.      */
  10989.  
  10990.     saveNS     = cmpCurNS;
  10991.     saveCls    = cmpCurCls;
  10992.     saveScp    = cmpCurScp;
  10993.  
  10994.     cmpCurUses = esect;
  10995.     cmpCurScp  = NULL;
  10996.     cmpCurCls  = NULL;
  10997.     cmpCurNS   = esect ? esect->ul.ulSym : cmpGlobalNS;
  10998.  
  10999.     if  (cmpCurNS->sdSymKind == SYM_CLASS)
  11000.     {
  11001.         cmpCurCls = cmpCurNS;
  11002.         cmpCurNS  = cmpCurNS->sdParent;
  11003.     }
  11004.  
  11005.     for (outer = bsect; outer != esect; outer = outer->ulNext)
  11006.     {
  11007.         SymDef          sym;
  11008.  
  11009.         /* Bind this "using" clause */
  11010.  
  11011.         assert(outer->ulAnchor == false);
  11012.  
  11013.         if  (outer->ulBound)
  11014.         {
  11015.             /* This must be the pre-bound entry we add on the outside */
  11016.  
  11017.             assert(outer->ul.ulSym == cmpNmSpcSystem);
  11018.             continue;
  11019.         }
  11020.  
  11021.         sym = cmpBindQualName(outer->ul.ulName, false);
  11022.         if  (!sym)
  11023.             goto SAVE;
  11024.  
  11025.         /* Check for a duplicate */
  11026.  
  11027.         for (inner = bsect; inner != outer; inner = inner->ulNext)
  11028.         {
  11029.             assert(inner->ulAnchor == false);
  11030.             assert(inner->ulBound  == true);
  11031.  
  11032.             if  (inner->ul.ulSym == sym &&
  11033.                  inner->ulAll    == outer->ulAll)
  11034.             {
  11035.                 /* This is a duplicate, just ignore it */
  11036.  
  11037.                 goto SAVE;
  11038.             }
  11039.         }
  11040.  
  11041.         /* Make sure the symbol is kosher */
  11042.  
  11043.         if  (outer->ulAll)
  11044.         {
  11045.             /* The symbol better be a namespace */
  11046.  
  11047.             if  (sym->sdSymKind != SYM_NAMESPACE)
  11048.             {
  11049.                     cmpError(ERRnoNSnm, outer->ul.ulName);
  11050.  
  11051.                 sym = NULL;
  11052.                 goto SAVE;
  11053.             }
  11054.  
  11055.             /* Make sure any external members of the namespace are imported */
  11056.  
  11057.             if  (sym->sdIsImport)
  11058.             {
  11059.                 // UNDONE: How do we find all the members of the namespace?
  11060.             }
  11061.         }
  11062.  
  11063.     SAVE:
  11064.  
  11065.         outer->ulBound  = true;
  11066.         outer->ul.ulSym = sym;
  11067.     }
  11068.  
  11069.     /* Don't forget to restore the original scoping values */
  11070.  
  11071.     cmpCurNS  = saveNS;
  11072.     cmpCurCls = saveCls;
  11073.  
  11074. EXIT:
  11075.  
  11076.     /* Mark the section as bound and set the current "using" state */
  11077.  
  11078.     cmpCurUses = useList; useList->ulBound = true;
  11079. }
  11080.  
  11081. /*****************************************************************************
  11082.  *
  11083.  *  Find a constructor in the given class that can be called with the given
  11084.  *  argument list.
  11085.  */
  11086.  
  11087. SymDef              compiler::cmpFindCtor(TypDef        clsTyp,
  11088.                                           bool          chkArgs,
  11089.                                           Tree          args)
  11090. {
  11091.     SymDef          clsSym;
  11092.     SymDef          ctfSym;
  11093.     SymDef          ovlSym;
  11094.  
  11095.     assert(clsTyp);
  11096.  
  11097.     clsSym = clsTyp->tdClass.tdcSymbol;
  11098.  
  11099.     /* Find the constructor member */
  11100.  
  11101.     ctfSym = cmpGlobalST->stLookupOper(OVOP_CTOR_INST, clsSym);
  11102.     if  (!ctfSym)
  11103.         return ctfSym;
  11104.  
  11105.     /* Every class has to have a constructor (even if added by the compiler) */
  11106.  
  11107.     assert(ctfSym);
  11108.     assert(ctfSym->sdFnc.sdfCtor);
  11109.  
  11110.     if  (!chkArgs)
  11111.         return ctfSym;
  11112.  
  11113.     /* Look for a matching constructor based on the supplied arguments */
  11114.  
  11115.     ovlSym = cmpFindOvlMatch(ctfSym, args, NULL);
  11116.     if  (!ovlSym)
  11117.     {
  11118.         cmpErrorXtp(ERRnoCtorMatch, ctfSym, args);
  11119.         return NULL;
  11120.     }
  11121.  
  11122.     return ovlSym;
  11123. }
  11124.  
  11125. /*****************************************************************************
  11126.  *
  11127.  *  Create a 'new' expression that will allocate an instance of the given
  11128.  *  class type and pass the specified set of arguments to its constructor.
  11129.  */
  11130.  
  11131. Tree                compiler::cmpCallCtor(TypDef type, Tree args)
  11132. {
  11133.     SymDef          fsym;
  11134.     Tree            call;
  11135.  
  11136.     assert(type->tdTypeKind == TYP_CLASS);
  11137.  
  11138.     /* Make sure the class is fully defined */
  11139.  
  11140.     cmpDeclSym(type->tdClass.tdcSymbol);
  11141.  
  11142.     /* Delegates must be created in a certain way */
  11143.  
  11144.     if  (type->tdClass.tdcFlavor == STF_DELEGATE)
  11145.     {
  11146.         Tree            func;
  11147.         Tree            inst;
  11148.  
  11149.         SymDef          fsym;
  11150.         TypDef          dlgt;
  11151.  
  11152.         /* There should be only one argument */
  11153.  
  11154.         if  (args == NULL || args->tnOp.tnOp2)
  11155.         {
  11156.     BAD_DLG_ARG:
  11157.  
  11158.             cmpError(ERRdlgCTarg);
  11159.             return cmpCreateErrNode();
  11160.         }
  11161.  
  11162.         assert(args->tnOper == TN_LIST);
  11163.  
  11164.         func = args->tnOp.tnOp1;
  11165.         if  (func->tnOper != TN_FNC_PTR)
  11166.         {
  11167.             if  (func->tnOper != TN_ADDROF)
  11168.                 goto BAD_DLG_ARG;
  11169.             func = func->tnOp.tnOp1;
  11170.             if  (func->tnOper != TN_FNC_SYM)
  11171.                 goto BAD_DLG_ARG;
  11172.  
  11173. //          func->tnFncSym.tnFncObj = cmpThisRef();
  11174.         }
  11175.  
  11176.         assert(func->tnFncSym.tnFncArgs == NULL);
  11177.  
  11178.         /* Find a member function that matches the delegate */
  11179.  
  11180.         fsym = func->tnFncSym.tnFncSym;
  11181.         dlgt = cmpGlobalST->stDlgSignature(type);
  11182.  
  11183.         do
  11184.         {
  11185.             assert(fsym && fsym->sdSymKind == SYM_FNC);
  11186.  
  11187.             /* Does this method match the desired signature? */
  11188.  
  11189.             if  (symTab::stMatchTypes(fsym->sdType, dlgt))
  11190.             {
  11191.                 func->tnFncSym.tnFncSym = fsym;
  11192.                 goto MAKE_DLG;
  11193.             }
  11194.  
  11195.             fsym = fsym->sdFnc.sdfNextOvl;
  11196.         }
  11197.         while (fsym);
  11198.  
  11199.         cmpErrorAtp(ERRdlgNoMFN, func->tnFncSym.tnFncSym->sdParent,
  11200.                                  func->tnFncSym.tnFncSym->sdName,
  11201.                                  dlgt);
  11202.  
  11203.     MAKE_DLG:
  11204.  
  11205.         /* We'll move the instance pointer from the method node */
  11206.  
  11207.         inst = func->tnFncSym.tnFncObj;
  11208.                func->tnFncSym.tnFncObj = NULL;
  11209.  
  11210.         if  (inst)
  11211.         {
  11212.             // Absurd hack: bash the type to avoid context warnings
  11213.  
  11214.             assert(inst->tnVtyp == TYP_REF); inst->tnType = cmpObjectRef();
  11215.         }
  11216.         else
  11217.         {
  11218.             inst = cmpCreateExprNode(NULL, TN_NULL, cmpObjectRef());
  11219.         }
  11220.  
  11221.         /* Wrap the method address in an explicit "addrof" node */
  11222.  
  11223.         args->tnOp.tnOp1 = cmpCreateExprNode(NULL,
  11224.                                              TN_ADDROF,
  11225. //                                           cmpGlobalST->stNewRefType(TYP_PTR, func->tnType),
  11226.                                              cmpTypeInt,
  11227.                                              func,
  11228.                                              NULL);
  11229.  
  11230.         /* Add the instance to the front of the list */
  11231.  
  11232.         args = cmpCreateExprNode(NULL, TN_LIST, cmpTypeVoid, inst, args);
  11233.     }
  11234.  
  11235.     /* Create the expression "new.ctor(args)" */
  11236.  
  11237.     fsym = cmpFindCtor(type, false);
  11238.     if  (!fsym)
  11239.         return  NULL;
  11240.  
  11241.     call = cmpCreateExprNode(NULL, TN_FNC_SYM, fsym->sdType);
  11242.  
  11243.     call->tnFncSym.tnFncObj  = NULL;
  11244.     call->tnFncSym.tnFncSym  = fsym;
  11245.     call->tnFncSym.tnFncArgs = args;
  11246.  
  11247.     /* Special case: method pointer wrappers */
  11248.  
  11249.     if  (type->tdClass.tdcFnPtrWrap)
  11250.     {
  11251.         /* See if there is one method pointer argument */
  11252.  
  11253.         if  (args && args->tnOp.tnOp2 == NULL
  11254.                   && args->tnOp.tnOp1->tnOper == TN_FNC_PTR)
  11255.         {
  11256.             printf("WARNING: wrapping method pointers into delegates NYI\n");
  11257.             goto BOUND;
  11258.         }
  11259.     }
  11260.  
  11261.     call = cmpCheckFuncCall(call);
  11262.  
  11263.     if  (call->tnOper == TN_ERROR)
  11264.         return  call;
  11265.  
  11266. BOUND:
  11267.  
  11268.     /* Is this a managed value type constructor? */
  11269.  
  11270.     if  (type->tdClass.tdcFlavor == STF_STRUCT && type->tdIsManaged)
  11271.     {
  11272.         call->tnVtyp = TYP_CLASS;
  11273.         call->tnType = type;
  11274.     }
  11275.     else
  11276.     {
  11277.         call->tnType = type->tdClass.tdcRefTyp;
  11278.         call->tnVtyp = call->tnType->tdTypeKindGet();
  11279.     }
  11280.  
  11281.     return  cmpCreateExprNode(NULL, TN_NEW, call->tnType, call, NULL);
  11282. }
  11283.  
  11284. /*****************************************************************************
  11285.  *
  11286.  *  Parse a type specification and make sure it refers to a class/interface.
  11287.  */
  11288.  
  11289. TypDef              compiler::cmpGetClassSpec(bool needIntf)
  11290. {
  11291.     declMods        mods;
  11292.     TypDef          clsTyp;
  11293.  
  11294.     clearDeclMods(&mods);
  11295.  
  11296.     clsTyp = cmpParser->parseTypeSpec(&mods, true);
  11297.  
  11298.     if  (clsTyp)
  11299.     {
  11300.         SymDef          clsSym;
  11301.  
  11302.         // UNDONE: need to make sure no modifiers were present
  11303.  
  11304.         if  (clsTyp->tdTypeKind != TYP_CLASS)
  11305.         {
  11306.             if  (clsTyp->tdTypeKind != TYP_REF)
  11307.             {
  11308.                 cmpError(ERRnoClassName);
  11309.                 return  NULL;
  11310.             }
  11311.  
  11312.             clsTyp = clsTyp->tdRef.tdrBase; assert(clsTyp->tdTypeKind == TYP_CLASS);
  11313.         }
  11314.  
  11315.         /* Get hold of the class symbol and make sure it's the right flavor */
  11316.  
  11317.         clsSym = clsTyp->tdClass.tdcSymbol;
  11318.  
  11319.         if  (clsSym->sdClass.sdcFlavor == STF_INTF)
  11320.         {
  11321.             if  (needIntf == false)
  11322.                 cmpError(ERRintfBase, clsSym);
  11323.         }
  11324.         else
  11325.         {
  11326.             if  (needIntf != false)
  11327.                 cmpError(ERRinclCls , clsSym);
  11328.         }
  11329.     }
  11330.  
  11331.     return  clsTyp;
  11332. }
  11333.  
  11334. /*****************************************************************************
  11335.  *
  11336.  *  Return the identifier that corresponds to the name of the given property.
  11337.  */
  11338.  
  11339. Ident               compiler::cmpPropertyName(Ident name, bool getter)
  11340. {
  11341.     Scanner         ourScanner = cmpScanner;
  11342.  
  11343.     char    *       propName;
  11344.  
  11345.     ourScanner->scanErrNameBeg();
  11346.     propName = ourScanner->scanErrNameStrBeg();
  11347.     ourScanner->scanErrNameStrAdd(getter ? "get_" : "set_");
  11348.     ourScanner->scanErrNameStrAdd(name->idSpelling());
  11349.     ourScanner->scanErrNameStrEnd();
  11350.  
  11351.     /* Find or declare the member in the secret class */
  11352.  
  11353.     return  cmpGlobalHT->hashString(propName);
  11354. }
  11355.  
  11356. /*****************************************************************************
  11357.  *
  11358.  *  Process a property declaration - the data member part has already been
  11359.  *  parsed.
  11360.  */
  11361.  
  11362. void                compiler::cmpDeclProperty(SymDef    memSym,
  11363.                                               declMods  memMod, DefList memDef)
  11364. {
  11365.     SymTab          ourSymTab  = cmpGlobalST;
  11366.     Parser          ourParser  = cmpParser;
  11367.     Scanner         ourScanner = cmpScanner;
  11368.  
  11369.     bool            isAbstract = memSym->sdIsAbstract;
  11370.  
  11371.     SymDef          clsSym     = memSym->sdParent;
  11372.     TypDef          memType    = memSym->sdType;
  11373.     Ident           memName    = memSym->sdName;
  11374.     ArgDscRec       mfnArgs;
  11375.  
  11376.     bool            accList;
  11377.     unsigned        accPass;
  11378.  
  11379.     assert(memSym->sdSymKind == SYM_PROP);
  11380.  
  11381.     /* Is the property marked as "transient" ? */
  11382.  
  11383.     if  (memMod.dmMod & DM_TRANSIENT)
  11384.         memSym->sdIsTransient = true;
  11385.  
  11386.     /* Do we have an explicit list of accessors ? */
  11387.  
  11388.     accList = false;
  11389.     if  (ourScanner->scanTok.tok == tkLCurly)
  11390.     {
  11391.         accList = true;
  11392.     }
  11393.     else
  11394.     {
  11395.         assert(ourScanner->scanTok.tok == tkSColon && isAbstract);
  11396.     }
  11397.  
  11398.     /* Is this an indexed property ? */
  11399.  
  11400.     if  (memType->tdTypeKind == TYP_FNC)
  11401.     {
  11402.         mfnArgs = memType->tdFnc.tdfArgs;
  11403.         memType = memType->tdFnc.tdfRett;
  11404.     }
  11405.     else
  11406.     {
  11407. #if MGDDATA
  11408.         mfnArgs = new ArgDscRec;
  11409. #else
  11410.         memset(&mfnArgs, 0, sizeof(mfnArgs));
  11411. #endif
  11412.     }
  11413.  
  11414.     // UNDONE: check that the member's type is acceptable
  11415.  
  11416.     if  (accList)
  11417.         ourScanner->scan();
  11418.  
  11419.     for (accPass = 0; ; accPass++)
  11420.     {
  11421.         bool            getter;
  11422.         ovlOpFlavors    fnOper;
  11423.         tokens          tokNam;
  11424.         declMods        mfnMod;
  11425.  
  11426.         TypDef          mfnType;
  11427.         SymDef          mfnSym;
  11428.  
  11429.         /* If we don't have an explicit list, just make it up */
  11430.  
  11431.         if  (!accList)
  11432.         {
  11433.             clearDeclMods(&mfnMod);
  11434.  
  11435.             if  (accPass)
  11436.                 goto PSET;
  11437.             else
  11438.                 goto PGET;
  11439.         }
  11440.  
  11441.         /* Parse any leading modifiers */
  11442.  
  11443.         ourParser->parseDeclMods(ACL_DEFAULT, &mfnMod);
  11444.  
  11445.         if  (ourScanner->scanTok.tok != tkID)
  11446.         {
  11447.         BAD_PROP:
  11448.             UNIMPL("valid property name not found, now what?");
  11449.         }
  11450.  
  11451.         if      (ourScanner->scanTok.id.tokIdent == cmpIdentGet)
  11452.         {
  11453.         PGET:
  11454.             getter = true;
  11455.             fnOper = OVOP_PROP_GET;
  11456.             tokNam = OPNM_PROP_GET;
  11457.  
  11458.             if  (memSym->sdProp.sdpGetMeth)
  11459.                 cmpError(ERRdupProp, ourScanner->scanTok.id.tokIdent);
  11460.         }
  11461.         else if (ourScanner->scanTok.id.tokIdent == cmpIdentSet)
  11462.         {
  11463.         PSET:
  11464.             getter = false;
  11465.             fnOper = OVOP_PROP_SET;
  11466.             tokNam = OPNM_PROP_SET;
  11467.  
  11468.             if  (memSym->sdProp.sdpSetMeth)
  11469.                 cmpError(ERRdupProp, ourScanner->scanTok.id.tokIdent);
  11470.         }
  11471.         else
  11472.             goto BAD_PROP;
  11473.  
  11474.         // UNDONE: Check the modifiers to make sure nothing wierd is in there ....
  11475.  
  11476.         /* Invent a function type for the property */
  11477.  
  11478.         if  (getter)
  11479.         {
  11480.             /* The return type is the property type */
  11481.  
  11482.             mfnType = ourSymTab->stNewFncType(mfnArgs, memType);
  11483.         }
  11484.         else
  11485.         {
  11486.             ArgDscRec       memArgs;
  11487.  
  11488.             /* Append an argument with the property type to the arg list */
  11489.  
  11490.             if  (mfnArgs.adArgs)
  11491.             {
  11492.                 memArgs = mfnArgs;
  11493.                 ourSymTab->stAddArgList(memArgs, memType, cmpGlobalHT->hashString("value"));
  11494.                 mfnType = ourSymTab->stNewFncType(memArgs, cmpTypeVoid);
  11495.             }
  11496.             else
  11497.             {
  11498. #if     defined(__IL__) && !defined(_MSC_VER)
  11499.                 ourParser->parseArgListNew(memArgs, 1, true, memType, A"value", NULL);
  11500. #else
  11501.                 ourParser->parseArgListNew(memArgs, 1, true, memType,  "value", NULL);
  11502. #endif
  11503.                 mfnType = ourSymTab->stNewFncType(memArgs, cmpTypeVoid);
  11504.             }
  11505.         }
  11506.  
  11507.         /* Set any modifiers that may be appropriate */
  11508.  
  11509.         if  (isAbstract)
  11510.             mfnMod.dmMod |= DM_ABSTRACT;
  11511.  
  11512.         mfnMod.dmAcc = (mfnMod.dmAcc == ACL_DEFAULT) ? memSym->sdAccessLevel
  11513.                                                      : (accessLevels)mfnMod.dmAcc;
  11514.  
  11515.         /* Declare a method for this property */
  11516.  
  11517.         mfnSym = cmpDeclFuncMem(clsSym, mfnMod, mfnType, cmpPropertyName(memName, getter));
  11518.  
  11519.         if  (!mfnSym)
  11520.             goto ERR_ACC;
  11521.  
  11522.         /* Record the fact that this is a property accessor */
  11523.  
  11524.         mfnSym->sdFnc.sdfProperty = true;
  11525.  
  11526.         /* Inherit 'static'/'sealed'/'virtual' from the property data member */
  11527.  
  11528.         mfnSym->sdIsStatic       = memSym->sdIsStatic;
  11529.         mfnSym->sdIsSealed       = memSym->sdIsSealed;
  11530.         mfnSym->sdFnc.sdfVirtual = memSym->sdIsVirtProp;
  11531.  
  11532.         /* Record whether the accessor is supposed to overload the base */
  11533.  
  11534.         if  (memMod.dmMod & DM_OVERLOAD)
  11535.             mfnSym->sdFnc.sdfOverload = true;
  11536.  
  11537.         /* Record the method in the data property symbol */
  11538.  
  11539.         if  (getter)
  11540.             memSym->sdProp.sdpGetMeth = mfnSym;
  11541.         else
  11542.             memSym->sdProp.sdpSetMeth = mfnSym;
  11543.  
  11544.     ERR_ACC:
  11545.  
  11546.         /* Is there a function body ? */
  11547.  
  11548.         if  (accList && ourScanner->scan() == tkLCurly)
  11549.         {
  11550.             scanPosTP       defFpos;
  11551.             unsigned        defLine;
  11552.  
  11553.             if  (isAbstract)
  11554.                 cmpError(ERRabsPFbody, memSym);
  11555.  
  11556.             /* Figure out where the body starts */
  11557.  
  11558.             defFpos = ourScanner->scanGetTokenPos(&defLine);
  11559.  
  11560.             /* Swallow the method body */
  11561.  
  11562.             ourScanner->scanSkipText(tkLCurly, tkRCurly);
  11563.  
  11564.             if  (ourScanner->scanTok.tok == tkRCurly)
  11565.                 ourScanner->scan();
  11566.  
  11567.             if  (!isAbstract && mfnSym)
  11568.             {
  11569.                 ExtList         mfnDef;
  11570.  
  11571.                 /* Record the location of the body for later */
  11572.  
  11573.                 mfnDef = ourSymTab->stRecordMemSrcDef(memName,
  11574.                                                       NULL,
  11575.                                                       memDef->dlComp,
  11576.                                                       memDef->dlUses,
  11577.                                                       defFpos,
  11578.                                                       defLine);
  11579.                 mfnSym->sdIsDefined = true;
  11580.                 mfnDef->dlHasDef    = true;
  11581.                 mfnDef->mlSym       = mfnSym;
  11582.  
  11583.                 /* Add the property method to the member list of the class */
  11584.  
  11585.                 cmpRecordMemDef(clsSym, mfnDef);
  11586.             }
  11587.         }
  11588.         else
  11589.         {
  11590.             /* No body given for this property accessor */
  11591.  
  11592.             if  (ourScanner->scanTok.tok != tkSColon)
  11593.             {
  11594.                 cmpError(ERRnoSemic);
  11595.                 UNIMPL("resync");
  11596.             }
  11597.  
  11598.             // UNDONE: Remember that there is a property get/set
  11599.  
  11600.             if  (!accList)
  11601.             {
  11602.                 if  (accPass)
  11603.                     break;
  11604.                 else
  11605.                     continue;
  11606.             }
  11607.  
  11608.             ourScanner->scan();
  11609.         }
  11610.  
  11611.         if  (ourScanner->scanTok.tok == tkSColon)
  11612.             ourScanner->scan();
  11613.  
  11614.         if  (ourScanner->scanTok.tok == tkRCurly)
  11615.             break;
  11616.     }
  11617. }
  11618.  
  11619. /*****************************************************************************
  11620.  *
  11621.  *  Recursively look for a get/set property corresponding to the given data
  11622.  *  member within the class and its bases/interfaces. If a property with a
  11623.  *  matching name is found, we set *found to true (this way the caller can
  11624.  *  detect the case where a property with a matching name exists but the
  11625.  *  arguments don't match any of its accessors).
  11626.  */
  11627.  
  11628. SymDef              compiler::cmpFindPropertyFN(SymDef  clsSym,
  11629.                                                 Ident   propName,
  11630.                                                 Tree    args,
  11631.                                                 bool    getter,
  11632.                                                 bool  * found)
  11633. {
  11634.     SymDef          memSym;
  11635.     TypDef          clsTyp;
  11636.  
  11637.     /* Check the current class for a matching property */
  11638.  
  11639.     memSym = cmpGlobalST->stLookupClsSym(propName, clsSym);
  11640.     if  (memSym)
  11641.     {
  11642.         if  (memSym->sdSymKind != SYM_PROP)
  11643.         {
  11644.             /* A matching non-property member exists in the class, bail */
  11645.  
  11646.             return  NULL;
  11647.         }
  11648.  
  11649.         do
  11650.         {
  11651.             SymDef          propSym;
  11652.  
  11653.             propSym = getter ? memSym->sdProp.sdpGetMeth
  11654.                              : memSym->sdProp.sdpSetMeth;
  11655.  
  11656.             if  (propSym)
  11657.             {
  11658.                 /*
  11659.                     Tricky situation: as indexed properties can be overloaded,
  11660.                     the method symbol pointed to from the property symbol may
  11661.                     not be the beginning of the overload list.
  11662.                  */
  11663.  
  11664.                 propSym = cmpGlobalST->stLookupClsSym(propSym->sdName, clsSym);
  11665.  
  11666.                 assert(propSym);
  11667.  
  11668.                 if  (propSym->sdFnc.sdfNextOvl || propSym->sdFnc.sdfBaseOvl)
  11669.                 {
  11670.                     *found = true;
  11671.                     propSym = cmpFindOvlMatch(propSym, args, NULL);     // should not use NULL
  11672.                 }
  11673.  
  11674.                 return  propSym;
  11675.             }
  11676.  
  11677.             memSym = memSym->sdProp.sdpNextOvl;
  11678.         }
  11679.         while (memSym);
  11680.     }
  11681.  
  11682.     clsTyp = clsSym->sdType;
  11683.  
  11684.     /* Is there a base class? */
  11685.  
  11686.     if  (clsTyp->tdClass.tdcBase)
  11687.     {
  11688.         /* Look in the base and bail if that triggers an error */
  11689.  
  11690.         memSym = cmpFindPropertyFN(clsTyp->tdClass.tdcBase->tdClass.tdcSymbol, propName, args, getter, found);
  11691.         if  (memSym)
  11692.             return  memSym;
  11693.     }
  11694.  
  11695.     /* Does the class include any interfaces? */
  11696.  
  11697.     if  (clsTyp->tdClass.tdcIntf)
  11698.     {
  11699.         TypList         ifl = clsTyp->tdClass.tdcIntf;
  11700.  
  11701.         memSym = NULL;
  11702.  
  11703.         do
  11704.         {
  11705.             SymDef          tmpSym;
  11706.             SymDef          tmpScp;
  11707.  
  11708.             /* Look in the interface and bail if that triggers an error */
  11709.  
  11710.             tmpScp = ifl->tlType->tdClass.tdcSymbol;
  11711.             tmpSym = cmpFindPropertyFN(tmpScp, propName, args, getter, found);
  11712.             if  (tmpSym == cmpGlobalST->stErrSymbol || found)
  11713.                 return  tmpSym;
  11714.  
  11715.             if  (tmpSym)
  11716.             {
  11717.                 /* We have a match, do we already have a different match? */
  11718.  
  11719.                 if  (memSym && memSym != tmpSym)
  11720.                 {
  11721.                     cmpError(ERRambigMem, propName, clsSym, tmpScp);
  11722.                     return  cmpGlobalST->stErrSymbol;
  11723.                 }
  11724.  
  11725.                 /* This is the first match, record it and continue */
  11726.  
  11727.                 memSym = tmpSym;
  11728.                 clsSym = tmpScp;
  11729.             }
  11730.  
  11731.             ifl = ifl->tlNext;
  11732.         }
  11733.         while (ifl);
  11734.     }
  11735.  
  11736.     return  NULL;
  11737. }
  11738.  
  11739. /*****************************************************************************
  11740.  *
  11741.  *  Add an entry to the given "symbol extra info" list.
  11742.  */
  11743.  
  11744. SymXinfo            compiler::cmpAddXtraInfo(SymXinfo  infoList, Linkage linkSpec)
  11745. {
  11746. #if MGDDATA
  11747.     SymXinfoLnk     entry = new SymXinfoLnk;
  11748. #else
  11749.     SymXinfoLnk     entry =    (SymXinfoLnk)cmpAllocPerm.nraAlloc(sizeof(*entry));
  11750. #endif
  11751.  
  11752.     entry->xiKind = XI_LINKAGE;
  11753.     entry->xiNext = infoList;
  11754.  
  11755.     copyLinkDesc(entry->xiLink, linkSpec);
  11756.  
  11757.     return  entry;
  11758. }
  11759.  
  11760. SymXinfo            compiler::cmpAddXtraInfo(SymXinfo infoList, AtComment atcDesc)
  11761. {
  11762. #if MGDDATA
  11763.     SymXinfoAtc     entry = new SymXinfoAtc;
  11764. #else
  11765.     SymXinfoAtc     entry =    (SymXinfoAtc)cmpAllocPerm.nraAlloc(sizeof(*entry));
  11766. #endif
  11767.  
  11768.     entry->xiKind    = XI_ATCOMMENT;
  11769.     entry->xiNext    = infoList;
  11770.     entry->xiAtcInfo = atcDesc;
  11771.  
  11772.     return  entry;
  11773. }
  11774.  
  11775. SymXinfo            compiler::cmpAddXtraInfo(SymXinfo infoList, MarshalInfo marshal)
  11776. {
  11777. #if MGDDATA
  11778.     SymXinfoCOM     entry = new SymXinfoCOM;
  11779. #else
  11780.     SymXinfoCOM     entry =    (SymXinfoCOM)cmpAllocPerm.nraAlloc(sizeof(*entry));
  11781. #endif
  11782.  
  11783.     entry->xiKind    = XI_MARSHAL;
  11784.     entry->xiCOMinfo = marshal;
  11785.     entry->xiNext    = infoList;
  11786.  
  11787.     return  entry;
  11788. }
  11789.  
  11790. SymXinfo            compiler::cmpAddXtraInfo(SymXinfo infoList, SymDef     sym,
  11791.                                                                 xinfoKinds kind)
  11792. {
  11793. #if MGDDATA
  11794.     SymXinfoSym     entry = new SymXinfoSym;
  11795. #else
  11796.     SymXinfoSym     entry =    (SymXinfoSym)cmpAllocPerm.nraAlloc(sizeof(*entry));
  11797. #endif
  11798.  
  11799.     entry->xiKind    = kind;
  11800.     entry->xiSymInfo = sym;
  11801.     entry->xiNext    = infoList;
  11802.  
  11803.     return  entry;
  11804. }
  11805.  
  11806. SymXinfo            compiler::cmpAddXtraInfo(SymXinfo   infoList, SecurityInfo info)
  11807. {
  11808. #if MGDDATA
  11809.     SymXinfoSec     entry = new SymXinfoSec;
  11810. #else
  11811.     SymXinfoSec     entry =    (SymXinfoSec)cmpAllocPerm.nraAlloc(sizeof(*entry));
  11812. #endif
  11813.  
  11814.     entry->xiKind    = XI_SECURITY;
  11815.     entry->xiSecInfo = info;
  11816.     entry->xiNext    = infoList;
  11817.  
  11818.     return  entry;
  11819. }
  11820.  
  11821. SymXinfo            compiler::cmpAddXtraInfo(SymXinfo        infoList,
  11822.                                              SymDef          attrCtor,
  11823.                                              unsigned        attrMask,
  11824.                                              size_t          attrSize,
  11825.                                              genericBuff     attrAddr)
  11826. {
  11827.     SymXinfoAttr    entry;
  11828.  
  11829.     /* Are duplicates of this attribute allowed ? */
  11830.  
  11831.     if  (attrCtor->sdParent->sdClass.sdcAttrDupOK == false &&
  11832.          attrCtor->sdParent->sdClass.sdcAttribute != false)
  11833.     {
  11834.         SymXinfo        chkList;
  11835.  
  11836.         /* Linear search -- pretty lame, isn't it? */
  11837.  
  11838.         for (chkList = infoList; chkList; chkList = chkList->xiNext)
  11839.         {
  11840.             if  (chkList->xiKind == XI_ATTRIBUTE)
  11841.             {
  11842.                 SymXinfoAttr    entry = (SymXinfoAttr)chkList;
  11843.  
  11844.                 if  (entry->xiAttrCtor->sdParent == attrCtor->sdParent)
  11845.                     cmpError(ERRcustAttrDup, attrCtor->sdParent);
  11846.  
  11847.                 break;
  11848.             }
  11849.         }
  11850.     }
  11851.  
  11852. #if MGDDATA
  11853.     entry = new SymXinfoAttr;
  11854. #else
  11855.     entry =    (SymXinfoAttr)cmpAllocPerm.nraAlloc(sizeof(*entry));
  11856. #endif
  11857.  
  11858.     entry->xiKind     = XI_ATTRIBUTE;
  11859.     entry->xiAttrCtor = attrCtor;
  11860.     entry->xiAttrMask = attrMask;
  11861.     entry->xiAttrSize = attrSize;
  11862.     entry->xiAttrAddr = attrAddr;
  11863.     entry->xiNext     = infoList;
  11864.  
  11865.     return  entry;
  11866. }
  11867.  
  11868. /*****************************************************************************
  11869.  *
  11870.  *  Look for a specific entry in the given "extra info" list.
  11871.  */
  11872.  
  11873. SymXinfo            compiler::cmpFindXtraInfo(SymXinfo      infoList,
  11874.                                               xinfoKinds    infoKind)
  11875. {
  11876.     while   (infoList)
  11877.     {
  11878.         if  (infoList->xiKind == infoKind)
  11879.             break;
  11880.  
  11881.         infoList = infoList->xiNext;
  11882.     }
  11883.  
  11884.     return  infoList;
  11885. }
  11886.  
  11887. /*****************************************************************************
  11888.  *
  11889.  *  Recursively fixes up the start/end offsets of debug info lexical scopes
  11890.  *  defined within the given scope.
  11891.  *
  11892.  *  Also emits parameters as we're walking down the tree.
  11893.  */
  11894.  
  11895. void                compiler::cmpFixupScopes(SymDef scope)
  11896. {
  11897.     SymDef          child;
  11898.  
  11899.     assert(scope->sdSymKind == SYM_SCOPE);
  11900.  
  11901.     if  (scope->sdScope.sdSWscopeId)
  11902.     {
  11903.         int             startOffset;
  11904.         int             endOffset;
  11905.  
  11906.         startOffset = cmpILgen->genCodeAddr(scope->sdScope.sdBegBlkAddr,
  11907.                                             scope->sdScope.sdBegBlkOffs);
  11908.           endOffset = cmpILgen->genCodeAddr(scope->sdScope.sdEndBlkAddr,
  11909.                                             scope->sdScope.sdEndBlkOffs);
  11910.  
  11911.         if (cmpSymWriter->SetScopeRange(scope->sdScope.sdSWscopeId,
  11912.                                         startOffset,
  11913.                                         endOffset))
  11914.         {
  11915.             cmpGenFatal(ERRdebugInfo);
  11916.         }
  11917.     }
  11918.  
  11919.     for (child = scope->sdScope.sdScope.sdsChildList;
  11920.          child;
  11921.          child = child->sdNextInScope)
  11922.     {
  11923.         if  (child->sdSymKind == SYM_SCOPE)
  11924.             cmpFixupScopes(child);
  11925.     }
  11926. }
  11927.  
  11928. /*****************************************************************************/
  11929. /*****************************************************************************
  11930.  *
  11931.  *  Store a length field in a custom attribute blob; return the size stored.
  11932.  */
  11933.  
  11934. size_t              compiler::cmpStoreMDlen(size_t len, BYTE *dest)
  11935. {
  11936.     if  (len <= 0x7F)
  11937.     {
  11938.         if  (dest)
  11939.             *dest = len;
  11940.  
  11941.         return 1;
  11942.     }
  11943.  
  11944.     if  (len <= 0x3FFF)
  11945.     {
  11946.         if  (dest)
  11947.         {
  11948.             dest[0] = (len >> 8) | 0x80;
  11949.             dest[1] =  len & 0xFF;
  11950.         }
  11951.  
  11952.         return 2;
  11953.     }
  11954.  
  11955.     assert(len <= 0x1FFFFFFF);
  11956.  
  11957.     if  (dest)
  11958.     {
  11959.         dest[0] = (len >> 24) | 0xC0;
  11960.         dest[1] = (len >> 16) & 0xFF;
  11961.         dest[2] = (len >> 8)  & 0xFF;
  11962.         dest[3] =  len & 0xFF;
  11963.     }
  11964.  
  11965.     return  4;
  11966. }
  11967.  
  11968. /*****************************************************************************
  11969.  *
  11970.  *  Bind a custom attribute thingie, i.e. create the serialized blob value and
  11971.  *  return the constructor that is to be called. The caller supplies the class
  11972.  *  for the attribute and the argument list specified by the gizmo.
  11973.  */
  11974.  
  11975. SymDef              compiler::cmpBindAttribute(SymDef           clsSym,
  11976.                                                Tree             argList,
  11977.                                                unsigned         tgtMask,
  11978.                                            OUT unsigned     REF useMask,
  11979.                                            OUT genericBuff  REF blobAddr,
  11980.                                            OUT size_t       REF blobSize)
  11981. {
  11982.     SymDef          ctrSym;
  11983.     Tree            callExpr;
  11984.  
  11985.     genericBuff     blob;
  11986.  
  11987.     size_t          size;
  11988.     Tree            argl;
  11989.     unsigned        argn;
  11990.  
  11991.     unsigned        arg1 = 0;
  11992.  
  11993.     assert(clsSym && clsSym->sdSymKind == SYM_CLASS);
  11994.  
  11995.     if  (argList)
  11996.         argList = cmpBindExpr(argList);
  11997.  
  11998.     callExpr = cmpCallCtor(clsSym->sdType, argList);
  11999.     if  (!callExpr)
  12000.     {
  12001.         cmpErrorXtp(ERRnoCtorMatch, clsSym, argList);
  12002.         return  NULL;
  12003.     }
  12004.  
  12005.     if  (callExpr->tnVtyp == TYP_UNDEF)
  12006.         return  NULL;
  12007.  
  12008.     /* Get hold of the constructor symbol and the bound argument list */
  12009.  
  12010.     assert(callExpr->tnOper == TN_NEW);
  12011.  
  12012.     assert(callExpr->tnOp.tnOp1 != NULL);
  12013.     assert(callExpr->tnOp.tnOp2 == NULL);
  12014.  
  12015.     callExpr = callExpr->tnOp.tnOp1;
  12016.  
  12017.     assert(callExpr->tnOper == TN_FNC_SYM);
  12018.     assert(callExpr->tnFncSym.tnFncObj == NULL);
  12019.  
  12020.     ctrSym  = callExpr->tnFncSym.tnFncSym;
  12021.     argList = callExpr->tnFncSym.tnFncArgs;
  12022.  
  12023.     /* Make sure all the arguments are constants, compute the blob size */
  12024.  
  12025.     size = 2 * sizeof(short);   // version# prefix, 0 count suffix
  12026.     argl = argList;
  12027.     argn = 0;
  12028.  
  12029.     while (++argn, argl)
  12030.     {
  12031.         Tree            argx;
  12032.  
  12033.         assert(argl->tnOper == TN_LIST);
  12034.  
  12035.         /* Get hold of the next argument and see what type it is */
  12036.  
  12037.         argx = argl->tnOp.tnOp1;
  12038.  
  12039.         switch (argx->tnOper)
  12040.         {
  12041.         case TN_CNS_INT:
  12042.         case TN_CNS_LNG:
  12043.         case TN_CNS_FLT:
  12044.         case TN_CNS_DBL:
  12045.             size += cmpGetTypeSize(argx->tnType);
  12046.  
  12047.             if  (argn == 1)
  12048.                 arg1 = argx->tnIntCon.tnIconVal;
  12049.  
  12050.             break;
  12051.  
  12052.         case TN_NULL:
  12053.             size += sizeof(void *);
  12054.             break;
  12055.  
  12056.         case TN_CNS_STR:
  12057.             if  (argx->tnStrCon.tnSconLen)
  12058.                 size += argx->tnStrCon.tnSconLen + cmpStoreMDlen(argx->tnStrCon.tnSconLen);
  12059.             else
  12060.                 size += 1;
  12061.             break;
  12062.  
  12063.         default:
  12064.             cmpGenError(ERRnonCnsAA, argn);
  12065.             break;
  12066.         }
  12067.  
  12068.         /* Continue walking the argument list */
  12069.  
  12070.         argl  = argl->tnOp.tnOp2;
  12071.     }
  12072.  
  12073.     /* Find the "System::Attribute" class */
  12074.  
  12075.     if  (!cmpAttrClsSym)
  12076.     {
  12077.         Ident           tname;
  12078.         SymDef          tsym;
  12079.  
  12080.         tname = cmpGlobalHT->hashString("Attribute");
  12081.         tsym  = cmpGlobalST->stLookupNspSym(tname, NS_NORM, cmpNmSpcSystem);
  12082.  
  12083.         if  (!tsym || tsym->sdSymKind         != SYM_CLASS
  12084.                    || tsym->sdClass.sdcFlavor != STF_CLASS)
  12085.         {
  12086.             cmpGenFatal(ERRbltinTp, "System::Attribute");
  12087.         }
  12088.  
  12089.         cmpAttrClsSym = tsym;
  12090.     }
  12091.  
  12092.     if  (!cmpAuseClsSym)
  12093.     {
  12094.         Ident           tname;
  12095.         SymDef          tsym;
  12096.  
  12097.         tname = cmpGlobalHT->hashString("AttributeUsageAttribute");
  12098.         tsym  = cmpGlobalST->stLookupNspSym(tname, NS_NORM, cmpNmSpcSystem);
  12099.  
  12100.         if  (!tsym || tsym->sdSymKind         != SYM_CLASS
  12101.                    || tsym->sdClass.sdcFlavor != STF_CLASS)
  12102.         {
  12103.             cmpGenFatal(ERRbltinTp, "System::AttributeUsageAttribute");
  12104.         }
  12105.         else
  12106.             cmpAuseClsSym = tsym;
  12107.     }
  12108.  
  12109.     /* Make sure the attribute isn't misused */
  12110.  
  12111.     if  (!clsSym->sdClass.sdcAttribute)
  12112.     {
  12113.         TypDef          clsBase = clsSym->sdType->tdClass.tdcBase;
  12114.  
  12115.         /* The new thing: inheriting from System::Attribute */
  12116.  
  12117.         if  (clsBase && clsBase->tdClass.tdcSymbol == cmpAttrClsSym)
  12118.         {
  12119.             clsSym->sdClass.sdcAttribute = true;
  12120.         }
  12121.         else
  12122.         {
  12123.             printf("WARNING: attached '%s' which isn't marked as a custom attribute!\n", cmpGlobalST->stTypeName(NULL, clsSym, NULL, NULL, true));
  12124.         }
  12125.     }
  12126.  
  12127.     if  (clsSym->sdClass.sdcAttribute)
  12128.     {
  12129.         SymXinfo        infoList;
  12130.  
  12131.         assert(tgtMask);
  12132.  
  12133.         /* Find the use mask of the attribute and check it */
  12134.  
  12135.         for (infoList = clsSym->sdClass.sdcExtraInfo;
  12136.              infoList;
  12137.              infoList = infoList->xiNext)
  12138.         {
  12139.             if  (infoList->xiKind == XI_ATTRIBUTE)
  12140.             {
  12141.                 SymXinfoAttr    entry = (SymXinfoAttr)infoList;
  12142.  
  12143.                 if  (!(tgtMask & entry->xiAttrMask))
  12144.                     cmpError(ERRcustAttrPlc);
  12145.  
  12146.                 break;
  12147.             }
  12148.         }
  12149.     }
  12150.  
  12151.     /* Is this a "System::Attribute" attribute ? */
  12152.  
  12153.     useMask = 0;
  12154.  
  12155.     if  (clsSym == cmpAttrClsSym ||
  12156.          clsSym == cmpAuseClsSym)
  12157.     {
  12158.         if  (arg1 == 0)
  12159.             cmpError(ERRcustAttrMsk);
  12160.  
  12161.         useMask = arg1;
  12162.     }
  12163.  
  12164.     /* Allocate space for the blob */
  12165.  
  12166. #if MGDDATA
  12167.     blob = new managed char [size];
  12168. #else
  12169.     blob = (genericBuff)cmpAllocPerm.nraAlloc(roundUp(size));
  12170. #endif
  12171.  
  12172.     /* Tell the caller about the blob */
  12173.  
  12174.     blobAddr = blob;
  12175.     blobSize = size;
  12176.  
  12177.     /* Store the signature to get the blob started */
  12178.  
  12179.     unsigned short      ver = 1;
  12180.  
  12181.     memcpy(blob, &ver, sizeof(ver));
  12182.            blob   +=   sizeof(ver);
  12183.  
  12184.     /* Record the argument values */
  12185.  
  12186.     argl = argList;
  12187.  
  12188.     while (argl)
  12189.     {
  12190.         __int32         ival;
  12191.         __int64         lval;
  12192.         float           fval;
  12193.         double          dval;
  12194.  
  12195.         Tree            argx;
  12196.  
  12197.         void    *       valp;
  12198.         size_t          vals;
  12199.  
  12200.         assert(argl->tnOper == TN_LIST);
  12201.  
  12202.         /* Get hold of the next argument and see what type it is */
  12203.  
  12204.         argx = argl->tnOp.tnOp1;
  12205.  
  12206.         switch (argx->tnOper)
  12207.         {
  12208.         case TN_CNS_INT: ival = argx->tnIntCon.tnIconVal; valp = (BYTE*)&ival; goto INTRINS;
  12209.         case TN_CNS_LNG: lval = argx->tnLngCon.tnLconVal; valp = (BYTE*)&lval; goto INTRINS;
  12210.         case TN_CNS_FLT: fval = argx->tnFltCon.tnFconVal; valp = (BYTE*)&fval; goto INTRINS;
  12211.         case TN_CNS_DBL: dval = argx->tnDblCon.tnDconVal; valp = (BYTE*)&dval; goto INTRINS;
  12212.         case TN_NULL:    ival =                        0; valp = (BYTE*)&ival; goto INTRINS;
  12213.  
  12214.         INTRINS:
  12215.             vals  = cmpGetTypeSize(argx->tnType);
  12216.             break;
  12217.  
  12218.         case TN_CNS_STR:
  12219.             valp  = argx->tnStrCon.tnSconVal;
  12220.             vals  = argx->tnStrCon.tnSconLen;
  12221.  
  12222.             if  (vals)
  12223.             {
  12224.                 blob += cmpStoreMDlen(vals, blob);
  12225.             }
  12226.             else
  12227.             {
  12228.                 valp = &ival; ival = 0xFF;
  12229.                 vals = 1;
  12230.             }
  12231.             break;
  12232.  
  12233.         default:
  12234.             break;
  12235.         }
  12236.  
  12237.         memcpy(blob, valp, vals);
  12238.                blob   +=   vals;
  12239.  
  12240.         /* Continue walking the argument list */
  12241.  
  12242.         argl = argl->tnOp.tnOp2;
  12243.     }
  12244.  
  12245.     /* Store the signature to get the blob started */
  12246.  
  12247.     static
  12248.     short       cnt = 0;
  12249.  
  12250.     memcpy(blob, &cnt, sizeof(cnt));
  12251.            blob   +=   sizeof(cnt);
  12252.  
  12253.     /* Make sure the predicted size turns out to be accurate */
  12254.  
  12255.     assert(blob == blobAddr + blobSize);
  12256.  
  12257.     return  ctrSym;
  12258. }
  12259.  
  12260. /*****************************************************************************/
  12261.