Thread overview
[dmd-internals] dmd test suite coverage
Sep 03, 2010
Walter Bright
Sep 06, 2010
Don Clugston
Sep 06, 2010
Walter Bright
Sep 06, 2010
Don Clugston
Sep 07, 2010
Walter Bright
September 03, 2010
I built dmd with coverage analysis (gcov on linux) and ran the test suite. This is one of the result files - there are definitely gaps in the suite. Anyone want to give these a go?
-----------------------------------------------------------------
        -:    0:Source:parse.c
        -:    0:Graph:parse.gcno
        -:    0:Data:parse.gcda
        -:    0:Runs:10817
        -:    0:Programs:1
        -:    1:
        -:    2:// Compiler implementation of the D programming language
        -:    3:// Copyright (c) 1999-2010 by Digital Mars
        -:    4:// All Rights Reserved
        -:    5:// written by Walter Bright
        -:    6:// http://www.digitalmars.com
        -:    7:// License for redistribution is by either the Artistic
License
        -:    8:// in artistic.txt, or the GNU General Public License in
gnu.txt.
        -:    9:// See the included readme.txt for details.
        -:   10:
        -:   11:// This is the D parser
        -:   12:
        -:   13:#include <stdio.h>
        -:   14:#include <assert.h>
        -:   15:
        -:   16:#include "rmem.h"
        -:   17:#include "lexer.h"
        -:   18:#include "parse.h"
        -:   19:#include "init.h"
        -:   20:#include "attrib.h"
        -:   21:#include "cond.h"
        -:   22:#include "mtype.h"
        -:   23:#include "template.h"
        -:   24:#include "staticassert.h"
        -:   25:#include "expression.h"
        -:   26:#include "statement.h"
        -:   27:#include "module.h"
        -:   28:#include "dsymbol.h"
        -:   29:#include "import.h"
        -:   30:#include "declaration.h"
        -:   31:#include "aggregate.h"
        -:   32:#include "enum.h"
        -:   33:#include "id.h"
        -:   34:#include "version.h"
        -:   35:#include "aliasthis.h"
        -:   36:
        -:   37:// How multiple declarations are parsed.
        -:   38:// If 1, treat as C.
        -:   39:// If 0, treat:
        -:   40://      int *p, i;
        -:   41:// as:
        -:   42://      int* p;
        -:   43://      int* i;
        -:   44:#define CDECLSYNTAX     0
        -:   45:
        -:   46:// Support C cast syntax:
        -:   47://      (type)(expression)
        -:   48:#define CCASTSYNTAX     1
        -:   49:
        -:   50:// Support postfix C array declarations, such as
        -:   51://      int a[3][4];
        -:   52:#define CARRAYDECL      1
        -:   53:
        -:   54:// Support D1 inout
        -:   55:#define D1INOUT         0
        -:   56:
   253642:   57:Parser::Parser(Module *module, unsigned char *base,
unsigned length, int doDocComment)
   253642:   58:    : Lexer(module, base, 0, length, doDocComment, 0)
        -:   59:{
        -:   60:    //printf("Parser::Parser()\n");
   253642:   61:    md = NULL;
   253642:   62:    linkage = LINKd;
   253642:   63:    endloc = 0;
   253642:   64:    inBrackets = 0;
        -:   65:    //nextToken();              // start up the scanner
   253642:   66:}
        -:   67:
   239264:   68:Dsymbols *Parser::parseModule()
        -:   69:{
        -:   70:    Dsymbols *decldefs;
        -:   71:
        -:   72:    // ModuleDeclation leads off
   239264:   73:    if (token.value == TOKmodule)
        -:   74:    {
   234313:   75:        unsigned char *comment = token.blockComment;
   234313:   76:        bool safe = FALSE;
        -:   77:
   234313:   78:        nextToken();
        -:   79:#if 0 && DMDV2
        -:   80:        if (token.value == TOKlparen)
        -:   81:        {
        -:   82:            nextToken();
        -:   83:            if (token.value != TOKidentifier)
        -:   84:            {   error("module (system) identifier
expected");
        -:   85:                goto Lerr;
        -:   86:            }
        -:   87:            Identifier *id = token.ident;
        -:   88:
        -:   89:            if (id == Id::system)
        -:   90:                safe = TRUE;
        -:   91:            else
        -:   92:                error("(safe) expected, not %s",
id->toChars());
        -:   93:            nextToken();
        -:   94:            check(TOKrparen);
        -:   95:        }
        -:   96:#endif
        -:   97:
   234313:   98:        if (token.value != TOKidentifier)
    #####:   99:        {   error("Identifier expected following module");
    #####:  100:            goto Lerr;
        -:  101:        }
        -:  102:        else
        -:  103:        {
   234313:  104:            Array *a = NULL;
        -:  105:            Identifier *id;
        -:  106:
   234313:  107:            id = token.ident;
   883376:  108:            while (nextToken() == TOKdot)
        -:  109:            {
   414750:  110:                if (!a)
   226382:  111:                    a = new Array();
   414750:  112:                a->push(id);
   414750:  113:                nextToken();
   414750:  114:                if (token.value != TOKidentifier)
    #####:  115:                {   error("Identifier expected following
package");
    #####:  116:                    goto Lerr;
        -:  117:                }
   414750:  118:                id = token.ident;
        -:  119:            }
        -:  120:
   234313:  121:            md = new ModuleDeclaration(a, id, safe);
        -:  122:
   234313:  123:            if (token.value != TOKsemicolon)
    #####:  124:                error("';' expected following module
declaration instead of %s", token.toChars());
   234313:  125:            nextToken();
   234313:  126:            addComment(mod, comment);
        -:  127:        }
        -:  128:    }
        -:  129:
   239264:  130:    decldefs = parseDeclDefs(0);
   239264:  131:    if (token.value != TOKeof)
    #####:  132:    {   error("unrecognized declaration");
    #####:  133:        goto Lerr;
        -:  134:    }
   239264:  135:    return decldefs;
        -:  136:
    #####:  137:Lerr:
    #####:  138:    while (token.value != TOKsemicolon && token.value !=
TOKeof)
    #####:  139:        nextToken();
    #####:  140:    nextToken();
    #####:  141:    return new Dsymbols();
        -:  142:}
        -:  143:
 10551692:  144:Dsymbols *Parser::parseDeclDefs(int once)
        -:  145:{   Dsymbol *s;
        -:  146:    Dsymbols *decldefs;
        -:  147:    Dsymbols *a;
        -:  148:    Dsymbols *aelse;
        -:  149:    enum PROT prot;
        -:  150:    StorageClass stc;
        -:  151:    StorageClass storageClass;
        -:  152:    Condition *condition;
        -:  153:    unsigned char *comment;
        -:  154:
        -:  155:    //printf("Parser::parseDeclDefs()\n");
 10551692:  156:    decldefs = new Dsymbols();
 32897322:  157:    do
        -:  158:    {
 38282754:  159:        comment = token.blockComment;
 38282754:  160:        storageClass = STCundefined;
 38282754:  161:        switch (token.value)
        -:  162:        {
        -:  163:            case TOKenum:
        -:  164:            {   /* Determine if this is a manifest
constant declaration,
        -:  165:                 * or a conventional enum.
        -:  166:                 */
  4487003:  167:                Token *t = peek(&token);
  4716218:  168:                if (t->value == TOKlcurly || t->value ==
TOKcolon)
   229215:  169:                    s = parseEnum();
  4257788:  170:                else if (t->value != TOKidentifier)
   466816:  171:                    goto Ldeclaration;
        -:  172:                else
        -:  173:                {
  3790972:  174:                    t = peek(t);
  3790972:  175:                    if (t->value == TOKlcurly ||
t->value == TOKcolon ||
        -:  176:                        t->value == TOKsemicolon)
    87489:  177:                        s = parseEnum();
        -:  178:                    else
        -:  179:                        goto Ldeclaration;
        -:  180:                }
   316704:  181:                break;
        -:  182:            }
        -:  183:
        -:  184:            case TOKstruct:
        -:  185:            case TOKunion:
        -:  186:            case TOKclass:
        -:  187:            case TOKinterface:
  1074674:  188:                s = parseAggregate();
  1074674:  189:                break;
        -:  190:
        -:  191:            case TOKimport:
   683760:  192:                s = parseImport(decldefs, 0);
   683760:  193:                break;
        -:  194:
        -:  195:            case TOKtemplate:
   861570:  196:                s = (Dsymbol *)parseTemplateDeclaration(0);
   861570:  197:                break;
        -:  198:
        -:  199:            case TOKmixin:
   161369:  200:            {   Loc loc = this->loc;
   161369:  201:                switch (peekNext())
        -:  202:                {
        -:  203:                    case TOKlparen:
        -:  204:                    {   // mixin(string)
    53380:  205:                        nextToken();
    53380:  206:                        check(TOKlparen, "mixin");
    53380:  207:                        Expression *e = parseAssignExp();
    53380:  208:                        check(TOKrparen);
    53380:  209:                        check(TOKsemicolon);
    53380:  210:                        s = new CompileDeclaration(loc, e);
    53380:  211:                        break;
        -:  212:                    }
        -:  213:                    case TOKtemplate:
        -:  214:                        // mixin template
       64:  215:                        nextToken();
       64:  216:                        s = (Dsymbol
*)parseTemplateDeclaration(1);
       64:  217:                        break;
        -:  218:
        -:  219:                    default:
   107925:  220:                        s = parseMixin();
        -:  221:                        break;
        -:  222:                }
   161369:  223:                break;
        -:  224:            }
        -:  225:
        -:  226:            case BASIC_TYPES:
        -:  227:            case TOKalias:
        -:  228:            case TOKtypedef:
        -:  229:            case TOKidentifier:
        -:  230:            case TOKtypeof:
        -:  231:            case TOKdot:
 20647635:  232:            Ldeclaration:
 20647635:  233:                a = parseDeclarations(STCundefined);
 20647635:  234:                decldefs->append(a);
 20647635:  235:                continue;
        -:  236:
        -:  237:            case TOKthis:
   444134:  238:                s = parseCtor();
   444134:  239:                break;
        -:  240:
        -:  241:#if 0 // dead end, use this(this){} instead
        -:  242:            case TOKassign:
        -:  243:                s = parsePostBlit();
        -:  244:                break;
        -:  245:#endif
        -:  246:            case TOKtilde:
    40559:  247:                s = parseDtor();
    40559:  248:                break;
        -:  249:
        -:  250:            case TOKinvariant:
        -:  251:            {   Token *t;
     4385:  252:                t = peek(&token);
     4385:  253:                if (t->value == TOKlparen)
        -:  254:                {
     4128:  255:                    if (peek(t)->value == TOKrparen)
        -:  256:                        // invariant() forms start of
class invariant
     4128:  257:                        s = parseInvariant();
        -:  258:                    else
        -:  259:                        // invariant(type)
    #####:  260:                        goto Ldeclaration;
        -:  261:                }
        -:  262:                else
        -:  263:                {
      257:  264:                    stc = STCimmutable;
      257:  265:                    goto Lstc;
        -:  266:                }
     4128:  267:                break;
        -:  268:            }
        -:  269:
        -:  270:            case TOKunittest:
  1854795:  271:                s = parseUnitTest();
  1854795:  272:                break;
        -:  273:
        -:  274:            case TOKnew:
      195:  275:                s = parseNew();
      195:  276:                break;
        -:  277:
        -:  278:            case TOKdelete:
      194:  279:                s = parseDelete();
      194:  280:                break;
        -:  281:
        -:  282:            case TOKeof:
        -:  283:            case TOKrcurly:
  5385432:  284:                return decldefs;
        -:  285:
        -:  286:            case TOKstatic:
  1409839:  287:                nextToken();
  1409839:  288:                if (token.value == TOKthis)
     4476:  289:                    s = parseStaticCtor();
  1405363:  290:                else if (token.value == TOKtilde)
      398:  291:                    s = parseStaticDtor();
  1404965:  292:                else if (token.value == TOKassert)
   146186:  293:                    s = parseStaticAssert();
  1258779:  294:                else if (token.value == TOKif)
   982206:  295:                {   condition = parseStaticIfCondition();
   982206:  296:                    a = parseBlock();
   982206:  297:                    aelse = NULL;
   982206:  298:                    if (token.value == TOKelse)
   798030:  299:                    {   nextToken();
   798030:  300:                        aelse = parseBlock();
        -:  301:                    }
   982206:  302:                    s = new
StaticIfDeclaration(condition, a, aelse);
   982206:  303:                    break;
        -:  304:                }
   276573:  305:                else if (token.value == TOKimport)
        -:  306:                {
    #####:  307:                    s = parseImport(decldefs, 1);
        -:  308:                }
        -:  309:                else
   276573:  310:                {   stc = STCstatic;
   276573:  311:                    goto Lstc2;
        -:  312:                }
   151060:  313:                break;
        -:  314:
        -:  315:            case TOKconst:
   120355:  316:                if (peekNext() == TOKlparen)
    59120:  317:                    goto Ldeclaration;
    61235:  318:                stc = STCconst;
    61235:  319:                goto Lstc;
        -:  320:
        -:  321:            case TOKimmutable:
   137755:  322:                if (peekNext() == TOKlparen)
    39739:  323:                    goto Ldeclaration;
    98016:  324:                stc = STCimmutable;
    98016:  325:                goto Lstc;
        -:  326:
        -:  327:            case TOKshared:
    67183:  328:            {   TOK next = peekNext();
    67183:  329:                if (next == TOKlparen)
       64:  330:                    goto Ldeclaration;
    67119:  331:                if (next == TOKstatic)
    27622:  332:                {   TOK next2 = peekNext2();
    27622:  333:                    if (next2 == TOKthis)
    27622:  334:                    {   s = parseSharedStaticCtor();
    27622:  335:                        break;
        -:  336:                    }
    #####:  337:                    if (next2 == TOKtilde)
    #####:  338:                    {   s = parseSharedStaticDtor();
    #####:  339:                        break;
        -:  340:                    }
        -:  341:                }
    39497:  342:                stc = STCshared;
    39497:  343:                goto Lstc;
        -:  344:            }
        -:  345:
        -:  346:            case TOKwild:
       64:  347:                if (peekNext() == TOKlparen)
       64:  348:                    goto Ldeclaration;
    #####:  349:                stc = STCwild;
    #####:  350:                goto Lstc;
        -:  351:
    51725:  352:            case TOKfinal:        stc = STCfinal;
goto Lstc;
    52106:  353:            case TOKauto:         stc = STCauto;
goto Lstc;
      387:  354:            case TOKscope:        stc = STCscope;
goto Lstc;
   232281:  355:            case TOKoverride:     stc = STCoverride;
goto Lstc;
    44064:  356:            case TOKabstract:     stc = STCabstract;
goto Lstc;
      131:  357:            case TOKsynchronized: stc = STCsynchronized;
goto Lstc;
    91798:  358:            case TOKdeprecated:   stc = STCdeprecated;
goto Lstc;
        -:  359:#if DMDV2
    28557:  360:            case TOKnothrow:      stc = STCnothrow;
goto Lstc;
   358146:  361:            case TOKpure:         stc = STCpure;
goto Lstc;
    87332:  362:            case TOKref:          stc = STCref;
goto Lstc;
      330:  363:            case TOKtls:          stc = STCtls;
goto Lstc;
    34447:  364:            case TOKgshared:      stc = STCgshared;
goto Lstc;
        -:  365:            //case TOKmanifest:   stc = STCmanifest;
goto Lstc;
   738076:  366:            case TOKat:           stc =
parseAttribute(); goto Lstc;
        -:  367:#endif
        -:  368:
  2542626:  369:            Lstc:
  2542626:  370:                if (storageClass & stc)
    #####:  371:                    error("redundant storage class %s",
Token::toChars(token.value));
  2542626:  372:                composeStorageClass(storageClass | stc);
  2542626:  373:                nextToken();
  2819199:  374:            Lstc2:
  2819199:  375:                storageClass |= stc;
  2819199:  376:                switch (token.value)
        -:  377:                {
        -:  378:                    case TOKconst:
        -:  379:                    case TOKinvariant:
        -:  380:                    case TOKimmutable:
        -:  381:                    case TOKshared:
        -:  382:                    case TOKwild:
        -:  383:                        // If followed by a (, it is not
a storage class
    94386:  384:                        if (peek(&token)->value ==
TOKlparen)
    36820:  385:                            break;
    57566:  386:                        if (token.value == TOKconst)
     1222:  387:                            stc = STCconst;
    56344:  388:                        else if (token.value == TOKshared)
    53313:  389:                            stc = STCshared;
     3031:  390:                        else if (token.value == TOKwild)
    #####:  391:                            stc = STCwild;
        -:  392:                        else
     3031:  393:                            stc = STCimmutable;
    57566:  394:                        goto Lstc;
    #####:  395:                    case TOKfinal:        stc =
STCfinal;        goto Lstc;
    27279:  396:                    case TOKauto:         stc =
STCauto;         goto Lstc;
    #####:  397:                    case TOKscope:        stc =
STCscope;        goto Lstc;
     3031:  398:                    case TOKoverride:     stc =
STCoverride;     goto Lstc;
    #####:  399:                    case TOKabstract:     stc =
STCabstract;     goto Lstc;
        1:  400:                    case TOKsynchronized: stc =
STCsynchronized; goto Lstc;
       64:  401:                    case TOKdeprecated:   stc =
STCdeprecated;   goto Lstc;
   282017:  402:                    case TOKnothrow:      stc =
STCnothrow;      goto Lstc;
    30310:  403:                    case TOKpure:         stc =
STCpure;         goto Lstc;
    84942:  404:                    case TOKref:          stc =
STCref;          goto Lstc;
     6216:  405:                    case TOKtls:          stc =
STCtls;          goto Lstc;
    18349:  406:                    case TOKgshared:      stc =
STCgshared;      goto Lstc;
        -:  407:                    //case TOKmanifest:   stc =
STCmanifest;     goto Lstc;
    29425:  408:                    case TOKat:           stc =
parseAttribute(); goto Lstc;
        -:  409:                    default:
        -:  410:                        break;
        -:  411:                }
        -:  412:
        -:  413:                /* Look for auto initializers:
        -:  414:                 *      storage_class identifier =
initializer;
        -:  415:                 */
  2279999:  416:                if (token.value == TOKidentifier &&
        -:  417:                    peek(&token)->value == TOKassign)
        -:  418:                {
    24025:  419:                    a =
parseAutoDeclarations(storageClass, comment);
    24025:  420:                    decldefs->append(a);
    24025:  421:                    continue;
        -:  422:                }
        -:  423:
        -:  424:                /* Look for return type inference for
template functions.
        -:  425:                 */
        -:  426:                Token *tk;
  2255974:  427:                if (token.value == TOKidentifier &&
        -:  428:                    (tk = peek(&token))->value ==
TOKlparen &&
        -:  429:                    skipParens(tk, &tk) &&
        -:  430:                    (peek(tk)->value == TOKlparen ||
        -:  431:                     peek(tk)->value == TOKlcurly)
        -:  432:                   )
        -:  433:                {
    76289:  434:                    a = parseDeclarations(storageClass);
    76289:  435:                    decldefs->append(a);
    76289:  436:                    continue;
        -:  437:                }
  2179685:  438:                a = parseBlock();
  2179685:  439:                s = new
StorageClassDeclaration(storageClass, a);
  2179685:  440:                break;
        -:  441:
        -:  442:            case TOKextern:
   678352:  443:                if (peek(&token)->value != TOKlparen)
    85041:  444:                {   stc = STCextern;
    85041:  445:                    goto Lstc;
        -:  446:                }
        -:  447:            {
   593311:  448:                enum LINK linksave = linkage;
   593311:  449:                linkage = parseLinkage();
   593311:  450:                a = parseBlock();
   593311:  451:                s = new LinkDeclaration(linkage, a);
   593311:  452:                linkage = linksave;
   593311:  453:                break;
        -:  454:            }
  1122645:  455:            case TOKprivate:    prot = PROTprivate;
goto Lprot;
    18442:  456:            case TOKpackage:    prot = PROTpackage;
goto Lprot;
     1672:  457:            case TOKprotected:  prot = PROTprotected;
goto Lprot;
   342030:  458:            case TOKpublic:     prot = PROTpublic;
goto Lprot;
    #####:  459:            case TOKexport:     prot = PROTexport;
goto Lprot;
        -:  460:
  1484789:  461:            Lprot:
  1484789:  462:                nextToken();
  1484789:  463:                switch (token.value)
        -:  464:                {
        -:  465:                    case TOKprivate:
        -:  466:                    case TOKpackage:
        -:  467:                    case TOKprotected:
        -:  468:                    case TOKpublic:
        -:  469:                    case TOKexport:
    #####:  470:                        error("redundant protection
attribute");
        -:  471:                        break;
        -:  472:                }
  1484789:  473:                a = parseBlock();
  1484789:  474:                s = new ProtDeclaration(prot, a);
  1484789:  475:                break;
        -:  476:
        -:  477:            case TOKalign:
        -:  478:            {   unsigned n;
        -:  479:
    13452:  480:                s = NULL;
    13452:  481:                nextToken();
    13452:  482:                if (token.value == TOKlparen)
        -:  483:                {
    13452:  484:                    nextToken();
    13452:  485:                    if (token.value == TOKint32v)
    13452:  486:                        n = (unsigned)token.uns64value;
        -:  487:                    else
    #####:  488:                    {   error("integer expected, not
%s", token.toChars());
    #####:  489:                        n = 1;
        -:  490:                    }
    13452:  491:                    nextToken();
    13452:  492:                    check(TOKrparen);
        -:  493:                }
        -:  494:                else
    #####:  495:                    n = global.structalign;
// default
        -:  496:
    13452:  497:                a = parseBlock();
    13452:  498:                s = new AlignDeclaration(n, a);
    13452:  499:                break;
        -:  500:            }
        -:  501:
        -:  502:            case TOKpragma:
        -:  503:            {   Identifier *ident;
    13505:  504:                Expressions *args = NULL;
        -:  505:
    13505:  506:                nextToken();
    13505:  507:                check(TOKlparen);
    13505:  508:                if (token.value != TOKidentifier)
    #####:  509:                {   error("pragma(identifier expected");
    #####:  510:                    goto Lerror;
        -:  511:                }
    13505:  512:                ident = token.ident;
    13505:  513:                nextToken();
    13505:  514:                if (token.value == TOKcomma &&
peekNext() != TOKrparen)
    13505:  515:                    args = parseArguments();    //
pragma(identifier, args...)
        -:  516:                else
    #####:  517:                    check(TOKrparen);           //
pragma(identifier)
        -:  518:
    13505:  519:                if (token.value == TOKsemicolon)
    13505:  520:                    a = NULL;
        -:  521:                else
    #####:  522:                    a = parseBlock();
    13505:  523:                s = new PragmaDeclaration(loc, ident,
args, a);
    13505:  524:                break;
        -:  525:            }
        -:  526:
        -:  527:            case TOKdebug:
    18445:  528:                nextToken();
    18445:  529:                if (token.value == TOKassign)
        -:  530:                {
      128:  531:                    nextToken();
      128:  532:                    if (token.value == TOKidentifier)
       64:  533:                        s = new DebugSymbol(loc,
token.ident);
       64:  534:                    else if (token.value == TOKint32v)
       64:  535:                        s = new DebugSymbol(loc,
(unsigned)token.uns64value);
        -:  536:                    else
    #####:  537:                    {   error("identifier or integer
expected, not %s", token.toChars());
    #####:  538:                        s = NULL;
        -:  539:                    }
      128:  540:                    nextToken();
      128:  541:                    if (token.value != TOKsemicolon)
    #####:  542:                        error("semicolon expected");
      128:  543:                    nextToken();
      128:  544:                    break;
        -:  545:                }
        -:  546:
    18317:  547:                condition = parseDebugCondition();
    18317:  548:                goto Lcondition;
        -:  549:
        -:  550:            case TOKversion:
  1209847:  551:                nextToken();
  1209847:  552:                if (token.value == TOKassign)
        -:  553:                {
    36653:  554:                    nextToken();
    36653:  555:                    if (token.value == TOKidentifier)
    36588:  556:                        s = new VersionSymbol(loc,
token.ident);
       65:  557:                    else if (token.value == TOKint32v)
       65:  558:                        s = new VersionSymbol(loc,
(unsigned)token.uns64value);
        -:  559:                    else
    #####:  560:                    {   error("identifier or integer
expected, not %s", token.toChars());
    #####:  561:                        s = NULL;
        -:  562:                    }
    36653:  563:                    nextToken();
    36653:  564:                    if (token.value != TOKsemicolon)
    #####:  565:                        error("semicolon expected");
    36653:  566:                    nextToken();
    36653:  567:                    break;
        -:  568:                }
  1173194:  569:                condition = parseVersionCondition();
        -:  570:                goto Lcondition;
        -:  571:
  1191511:  572:            Lcondition:
  1191511:  573:                a = parseBlock();
  1191511:  574:                aelse = NULL;
  1191511:  575:                if (token.value == TOKelse)
   530030:  576:                {   nextToken();
   530030:  577:                    aelse = parseBlock();
        -:  578:                }
  1191511:  579:                s = new
ConditionalDeclaration(condition, a, aelse);
  1191511:  580:                break;
        -:  581:
        -:  582:            case TOKsemicolon:          // empty declaration
        -:  583:                //error("empty declaration");
    33369:  584:                nextToken();
    33369:  585:                continue;
        -:  586:
        -:  587:            default:
    #####:  588:                error("Declaration expected, not
'%s'",token.toChars());
    #####:  589:            Lerror:
    #####:  590:                while (token.value != TOKsemicolon &&
token.value != TOKeof)
    #####:  591:                    nextToken();
    #####:  592:                nextToken();
    #####:  593:                s = NULL;
    #####:  594:                continue;
        -:  595:        }
 12116004:  596:        if (s)
 11432244:  597:        {   decldefs->push(s);
 11432244:  598:            addComment(s, comment);
        -:  599:        }
        -:  600:    } while (!once);
  5166260:  601:    return decldefs;
        -:  602:}
        -:  603:
        -:  604:/*********************************************
        -:  605: * Give error on conflicting storage classes.
        -:  606: */
        -:  607:
        -:  608:#if DMDV2
 26033501:  609:void Parser::composeStorageClass(StorageClass stc)
        -:  610:{
 26033501:  611:    StorageClass u = stc;
 26033501:  612:    u &= STCconst | STCimmutable | STCmanifest;
 26033501:  613:    if (u & (u - 1))
    #####:  614:        error("conflicting storage class %s",
Token::toChars(token.value));
 26033501:  615:    u = stc;
 26033501:  616:    u &= STCgshared | STCshared | STCtls;
 26033501:  617:    if (u & (u - 1))
    #####:  618:        error("conflicting storage class %s",
Token::toChars(token.value));
 26033501:  619:    u = stc;
 26033501:  620:    u &= STCsafe | STCsystem | STCtrusted;
 26033501:  621:    if (u & (u - 1))
    #####:  622:        error("conflicting attribute @%s", token.toChars());
 26033501:  623:}
        -:  624:#endif
        -:  625:
        -:  626:/***********************************************
        -:  627: * Parse storage class, lexer is on '@'
        -:  628: */
        -:  629:
        -:  630:#if DMDV2
   913308:  631:StorageClass Parser::parseAttribute()
        -:  632:{
   913308:  633:    nextToken();
   913308:  634:    StorageClass stc = 0;
   913308:  635:    if (token.value != TOKidentifier)
        -:  636:    {
    #####:  637:        error("identifier expected after @, not %s",
token.toChars());
        -:  638:    }
   913308:  639:    else if (token.ident == Id::property)
   815059:  640:        stc = STCproperty;
    98249:  641:    else if (token.ident == Id::safe)
    51527:  642:        stc = STCsafe;
    46722:  643:    else if (token.ident == Id::trusted)
    24248:  644:        stc = STCtrusted;
    22474:  645:    else if (token.ident == Id::system)
    19315:  646:        stc = STCsystem;
     3159:  647:    else if (token.ident == Id::disable)
     3159:  648:        stc = STCdisable;
        -:  649:    else
    #####:  650:        error("valid attribute identifiers are
@property, @safe, @trusted, @system, @disable not @%s", token.toChars());
   913308:  651:    return stc;
        -:  652:}
        -:  653:#endif
        -:  654:
        -:  655:/***********************************************
        -:  656: * Parse const/immutable/shared/inout/nothrow/pure postfix
        -:  657: */
        -:  658:
 12354068:  659:StorageClass Parser::parsePostfix()
        -:  660:{
 12354068:  661:    StorageClass stc = 0;
        -:  662:
   410306:  663:    while (1)
        -:  664:    {
 12764374:  665:        switch (token.value)
        -:  666:        {
   181510:  667:            case TOKconst:              stc |=
STCconst;                break;
        -:  668:            case TOKinvariant:
    #####:  669:                if (!global.params.useDeprecated)
    #####:  670:                    error("use of 'invariant' rather
than 'immutable' is deprecated");
     3479:  671:            case TOKimmutable:          stc |=
STCimmutable;            break;
    15347:  672:            case TOKshared:             stc |=
STCshared;               break;
    #####:  673:            case TOKwild:               stc |=
STCwild;                 break;
    30502:  674:            case TOKnothrow:            stc |=
STCnothrow;              break;
    33661:  675:            case TOKpure:               stc |=
STCpure;                 break;
   145807:  676:            case TOKat:                 stc |=
parseAttribute();        break;
        -:  677:
        -:  678:            default:
 12354068:  679:                composeStorageClass(stc);
 12354068:  680:                return stc;
        -:  681:        }
   410306:  682:        nextToken();
        -:  683:    }
        -:  684:}
        -:  685:
        -:  686:/********************************************
        -:  687: * Parse declarations after an align, protection, or
extern decl.
        -:  688: */
        -:  689:
  7794489:  690:Dsymbols *Parser::parseBlock()
        -:  691:{
  7794489:  692:    Dsymbols *a = NULL;
        -:  693:    Dsymbol *s;
        -:  694:
        -:  695:    //printf("parseBlock()\n");
  7794489:  696:    switch (token.value)
        -:  697:    {
        -:  698:        case TOKsemicolon:
    #####:  699:            error("declaration expected following
attribute, not ';'");
    #####:  700:            nextToken();
    #####:  701:            break;
        -:  702:
        -:  703:        case TOKeof:
    #####:  704:            error("declaration expected following
attribute, not EOF");
    #####:  705:            break;
        -:  706:
        -:  707:        case TOKlcurly:
  2406369:  708:            nextToken();
  2406369:  709:            a = parseDeclDefs(0);
  2406369:  710:            if (token.value != TOKrcurly)
        -:  711:            {   /* { */
    #####:  712:                error("matching '}' expected, not %s",
token.toChars());
        -:  713:            }
        -:  714:            else
  2406369:  715:                nextToken();
  2406369:  716:            break;
        -:  717:
        -:  718:        case TOKcolon:
   221860:  719:            nextToken();
        -:  720:#if 0
        -:  721:            a = NULL;
        -:  722:#else
   221860:  723:            a = parseDeclDefs(0);       // grab
declarations up to closing curly bracket
        -:  724:#endif
   221860:  725:            break;
        -:  726:
        -:  727:        default:
  5166260:  728:            a = parseDeclDefs(1);
        -:  729:            break;
        -:  730:    }
  7794489:  731:    return a;
        -:  732:}
        -:  733:
        -:  734:/**********************************
        -:  735: * Parse a static assertion.
        -:  736: */
        -:  737:
  2026561:  738:StaticAssert *Parser::parseStaticAssert()
        -:  739:{
  2026561:  740:    Loc loc = this->loc;
        -:  741:    Expression *exp;
  2026561:  742:    Expression *msg = NULL;
        -:  743:
        -:  744:    //printf("parseStaticAssert()\n");
  2026561:  745:    nextToken();
  2026561:  746:    check(TOKlparen);
  2026561:  747:    exp = parseAssignExp();
  2026561:  748:    if (token.value == TOKcomma)
   127522:  749:    {   nextToken();
   127522:  750:        msg = parseAssignExp();
        -:  751:    }
  2026561:  752:    check(TOKrparen);
  2026561:  753:    check(TOKsemicolon);
  2026561:  754:    return new StaticAssert(loc, exp, msg);
        -:  755:}
        -:  756:
        -:  757:/***********************************
        -:  758: * Parse typeof(expression).
        -:  759: * Current token is on the 'typeof'.
        -:  760: */
        -:  761:
        -:  762:#if DMDV2
  1298443:  763:TypeQualified *Parser::parseTypeof()
        -:  764:{   TypeQualified *t;
  1298443:  765:    Loc loc = this->loc;
        -:  766:
  1298443:  767:    nextToken();
  1298443:  768:    check(TOKlparen);
  1298443:  769:    if (token.value == TOKreturn)       // typeof(return)
        -:  770:    {
   155421:  771:        nextToken();
   155421:  772:        t = new TypeReturn(loc);
        -:  773:    }
        -:  774:    else
  1143022:  775:    {   Expression *exp = parseExpression();    //
typeof(expression)
  1143022:  776:        t = new TypeTypeof(loc, exp);
        -:  777:    }
  1298443:  778:    check(TOKrparen);
  1298443:  779:    return t;
        -:  780:}
        -:  781:#endif
        -:  782:
        -:  783:/***********************************
        -:  784: * Parse extern (linkage)
        -:  785: * The parser is on the 'extern' token.
        -:  786: */
        -:  787:
   611817:  788:enum LINK Parser::parseLinkage()
        -:  789:{
   611817:  790:    enum LINK link = LINKdefault;
   611817:  791:    nextToken();
   611817:  792:    assert(token.value == TOKlparen);
   611817:  793:    nextToken();
   611817:  794:    if (token.value == TOKidentifier)
   611817:  795:    {   Identifier *id = token.ident;
        -:  796:
   611817:  797:        nextToken();
   611817:  798:        if (id == Id::Windows)
     8205:  799:            link = LINKwindows;
   603612:  800:        else if (id == Id::Pascal)
       68:  801:            link = LINKpascal;
   603544:  802:        else if (id == Id::D)
   245067:  803:            link = LINKd;
   358477:  804:        else if (id == Id::C)
        -:  805:        {
   358413:  806:            link = LINKc;
   358413:  807:            if (token.value == TOKplusplus)
      141:  808:            {   link = LINKcpp;
      141:  809:                nextToken();
        -:  810:            }
        -:  811:        }
       64:  812:        else if (id == Id::System)
        -:  813:        {
        -:  814:#if _WIN32
        -:  815:            link = LINKwindows;
        -:  816:#else
       64:  817:            link = LINKc;
        -:  818:#endif
        -:  819:        }
        -:  820:        else
        -:  821:        {
    #####:  822:            error("valid linkage identifiers are D, C,
C++, Pascal, Windows, System");
    #####:  823:            link = LINKd;
        -:  824:        }
        -:  825:    }
        -:  826:    else
        -:  827:    {
    #####:  828:        link = LINKd;           // default
        -:  829:    }
   611817:  830:    check(TOKrparen);
   611817:  831:    return link;
        -:  832:}
        -:  833:
        -:  834:/**************************************
        -:  835: * Parse a debug conditional
        -:  836: */
        -:  837:
   956249:  838:Condition *Parser::parseDebugCondition()
        -:  839:{
        -:  840:    Condition *c;
        -:  841:
   956249:  842:    if (token.value == TOKlparen)
        -:  843:    {
   931340:  844:        nextToken();
   931340:  845:        unsigned level = 1;
   931340:  846:        Identifier *id = NULL;
        -:  847:
   931340:  848:        if (token.value == TOKidentifier)
   930804:  849:            id = token.ident;
      536:  850:        else if (token.value == TOKint32v)
      536:  851:            level = (unsigned)token.uns64value;
        -:  852:        else
    #####:  853:            error("identifier or integer expected, not
%s", token.toChars());
   931340:  854:        nextToken();
   931340:  855:        check(TOKrparen);
   931340:  856:        c = new DebugCondition(mod, level, id);
        -:  857:    }
        -:  858:    else
    24909:  859:        c = new DebugCondition(mod, 1, NULL);
   956249:  860:    return c;
        -:  861:
        -:  862:}
        -:  863:
        -:  864:/**************************************
        -:  865: * Parse a version conditional
        -:  866: */
        -:  867:
  1565873:  868:Condition *Parser::parseVersionCondition()
        -:  869:{
        -:  870:    Condition *c;
  1565873:  871:    unsigned level = 1;
  1565873:  872:    Identifier *id = NULL;
        -:  873:
  1565873:  874:    if (token.value == TOKlparen)
        -:  875:    {
  1565873:  876:        nextToken();
  1565873:  877:        if (token.value == TOKidentifier)
  1521692:  878:            id = token.ident;
    44181:  879:        else if (token.value == TOKint32v)
      130:  880:            level = (unsigned)token.uns64value;
        -:  881:#if DMDV2
        -:  882:        /* Allow:
        -:  883:         *    version (unittest)
        -:  884:         * even though unittest is a keyword
        -:  885:         */
    44051:  886:        else if (token.value == TOKunittest)
    44051:  887:            id = Lexer::idPool(Token::toChars(TOKunittest));
        -:  888:#endif
        -:  889:        else
    #####:  890:            error("identifier or integer expected, not
%s", token.toChars());
  1565873:  891:        nextToken();
  1565873:  892:        check(TOKrparen);
        -:  893:
        -:  894:    }
        -:  895:    else
    #####:  896:       error("(condition) expected following version");
  1565873:  897:    c = new VersionCondition(mod, level, id);
  1565873:  898:    return c;
        -:  899:
        -:  900:}
        -:  901:
        -:  902:/***********************************************
        -:  903: *      static if (expression)
        -:  904: *          body
        -:  905: *      else
        -:  906: *          body
        -:  907: */
        -:  908:
  1841244:  909:Condition *Parser::parseStaticIfCondition()
        -:  910:{   Expression *exp;
        -:  911:    Condition *condition;
        -:  912:    Array *aif;
        -:  913:    Array *aelse;
  1841244:  914:    Loc loc = this->loc;
        -:  915:
  1841244:  916:    nextToken();
  1841244:  917:    if (token.value == TOKlparen)
        -:  918:    {
  1841244:  919:        nextToken();
  1841244:  920:        exp = parseAssignExp();
  1841244:  921:        check(TOKrparen);
        -:  922:    }
        -:  923:    else
    #####:  924:    {   error("(expression) expected following static if");
    #####:  925:        exp = NULL;
        -:  926:    }
  1841244:  927:    condition = new StaticIfCondition(loc, exp);
  1841244:  928:    return condition;
        -:  929:}
        -:  930:
        -:  931:
        -:  932:/*****************************************
        -:  933: * Parse a constructor definition:
        -:  934: *      this(parameters) { body }
        -:  935: * or postblit:
        -:  936: *      this(this) { body }
        -:  937: * or constructor template:
        -:  938: *      this(templateparameters)(parameters) { body }
        -:  939: * Current token is 'this'.
        -:  940: */
        -:  941:
   444134:  942:Dsymbol *Parser::parseCtor()
        -:  943:{
   444134:  944:    Loc loc = this->loc;
        -:  945:
   444134:  946:    nextToken();
   444134:  947:    if (token.value == TOKlparen && peek(&token)->value
== TOKthis)
        -:  948:    {   // this(this) { ... }
    31546:  949:        nextToken();
    31546:  950:        nextToken();
    31546:  951:        check(TOKrparen);
    31546:  952:        PostBlitDeclaration *f = new
PostBlitDeclaration(loc, 0);
    31546:  953:        parseContracts(f);
    31546:  954:        return f;
        -:  955:    }
        -:  956:
        -:  957:    /* Look ahead to see if:
        -:  958:     *   this(...)(...)
        -:  959:     * which is a constructor template
        -:  960:     */
   412588:  961:    TemplateParameters *tpl = NULL;
   412588:  962:    if (token.value == TOKlparen &&
peekPastParen(&token)->value == TOKlparen)
    29023:  963:    {   tpl = parseTemplateParameterList();
        -:  964:
        -:  965:        int varargs;
    29023:  966:        Parameters *parameters = parseParameters(&varargs);
    29023:  967:        StorageClass stc = parsePostfix();
        -:  968:
    29023:  969:        Expression *constraint = tpl ? parseConstraint()
: NULL;
        -:  970:
    29023:  971:        CtorDeclaration *f = new CtorDeclaration(loc, 0,
parameters, varargs, stc);
    29023:  972:        parseContracts(f);
        -:  973:
        -:  974:        // Wrap a template around it
    29023:  975:        Dsymbols *decldefs = new Dsymbols();
    29023:  976:        decldefs->push(f);
        -:  977:        TemplateDeclaration *tempdecl =
    29023:  978:            new TemplateDeclaration(loc, f->ident, tpl,
constraint, decldefs, 0);
    29023:  979:        return tempdecl;
        -:  980:    }
        -:  981:
        -:  982:    /* Just a regular constructor
        -:  983:     */
        -:  984:    int varargs;
   383565:  985:    Parameters *parameters = parseParameters(&varargs);
   383565:  986:    StorageClass stc = parsePostfix();
   383565:  987:    CtorDeclaration *f = new CtorDeclaration(loc, 0,
parameters, varargs, stc);
   383565:  988:    parseContracts(f);
   383565:  989:    return f;
        -:  990:}
        -:  991:
        -:  992:/*****************************************
        -:  993: * Parse a postblit definition:
        -:  994: *      =this() { body }
        -:  995: * Current token is '='.
        -:  996: */
        -:  997:
    #####:  998:PostBlitDeclaration *Parser::parsePostBlit()
        -:  999:{
    #####: 1000:    Loc loc = this->loc;
        -: 1001:
    #####: 1002:    nextToken();
    #####: 1003:    check(TOKthis);
    #####: 1004:    check(TOKlparen);
    #####: 1005:    check(TOKrparen);
        -: 1006:
    #####: 1007:    PostBlitDeclaration *f = new
PostBlitDeclaration(loc, 0);
    #####: 1008:    parseContracts(f);
    #####: 1009:    return f;
        -: 1010:}
        -: 1011:
        -: 1012:/*****************************************
        -: 1013: * Parse a destructor definition:
        -: 1014: *      ~this() { body }
        -: 1015: * Current token is '~'.
        -: 1016: */
        -: 1017:
    40559: 1018:DtorDeclaration *Parser::parseDtor()
        -: 1019:{
        -: 1020:    DtorDeclaration *f;
    40559: 1021:    Loc loc = this->loc;
        -: 1022:
    40559: 1023:    nextToken();
    40559: 1024:    check(TOKthis);
    40559: 1025:    check(TOKlparen);
    40559: 1026:    check(TOKrparen);
        -: 1027:
    40559: 1028:    f = new DtorDeclaration(loc, 0);
    40559: 1029:    parseContracts(f);
    40559: 1030:    return f;
        -: 1031:}
        -: 1032:
        -: 1033:/*****************************************
        -: 1034: * Parse a static constructor definition:
        -: 1035: *      static this() { body }
        -: 1036: * Current token is 'this'.
        -: 1037: */
        -: 1038:
     4476: 1039:StaticCtorDeclaration *Parser::parseStaticCtor()
        -: 1040:{
     4476: 1041:    Loc loc = this->loc;
        -: 1042:
     4476: 1043:    nextToken();
     4476: 1044:    check(TOKlparen);
     4476: 1045:    check(TOKrparen);
        -: 1046:
     4476: 1047:    StaticCtorDeclaration *f = new
StaticCtorDeclaration(loc, 0);
     4476: 1048:    parseContracts(f);
     4476: 1049:    return f;
        -: 1050:}
        -: 1051:
        -: 1052:/*****************************************
        -: 1053: * Parse a shared static constructor definition:
        -: 1054: *      shared static this() { body }
        -: 1055: * Current token is 'shared'.
        -: 1056: */
        -: 1057:
    27622: 1058:SharedStaticCtorDeclaration *Parser::parseSharedStaticCtor()
        -: 1059:{
    27622: 1060:    Loc loc = this->loc;
        -: 1061:
    27622: 1062:    nextToken();
    27622: 1063:    nextToken();
    27622: 1064:    nextToken();
    27622: 1065:    check(TOKlparen);
    27622: 1066:    check(TOKrparen);
        -: 1067:
    27622: 1068:    SharedStaticCtorDeclaration *f = new
SharedStaticCtorDeclaration(loc, 0);
    27622: 1069:    parseContracts(f);
    27622: 1070:    return f;
        -: 1071:}
        -: 1072:
        -: 1073:/*****************************************
        -: 1074: * Parse a static destructor definition:
        -: 1075: *      static ~this() { body }
        -: 1076: * Current token is '~'.
        -: 1077: */
        -: 1078:
      398: 1079:StaticDtorDeclaration *Parser::parseStaticDtor()
        -: 1080:{
      398: 1081:    Loc loc = this->loc;
        -: 1082:
      398: 1083:    nextToken();
      398: 1084:    check(TOKthis);
      398: 1085:    check(TOKlparen);
      398: 1086:    check(TOKrparen);
        -: 1087:
      398: 1088:    StaticDtorDeclaration *f = new
StaticDtorDeclaration(loc, 0);
      398: 1089:    parseContracts(f);
      398: 1090:    return f;
        -: 1091:}
        -: 1092:
        -: 1093:/*****************************************
        -: 1094: * Parse a shared static destructor definition:
        -: 1095: *      shared static ~this() { body }
        -: 1096: * Current token is 'shared'.
        -: 1097: */
        -: 1098:
    #####: 1099:SharedStaticDtorDeclaration *Parser::parseSharedStaticDtor()
        -: 1100:{
    #####: 1101:    Loc loc = this->loc;
        -: 1102:
    #####: 1103:    nextToken();
    #####: 1104:    nextToken();
    #####: 1105:    nextToken();
    #####: 1106:    check(TOKthis);
    #####: 1107:    check(TOKlparen);
    #####: 1108:    check(TOKrparen);
        -: 1109:
    #####: 1110:    SharedStaticDtorDeclaration *f = new
SharedStaticDtorDeclaration(loc, 0);
    #####: 1111:    parseContracts(f);
    #####: 1112:    return f;
        -: 1113:}
        -: 1114:
        -: 1115:/*****************************************
        -: 1116: * Parse an invariant definition:
        -: 1117: *      invariant() { body }
        -: 1118: * Current token is 'invariant'.
        -: 1119: */
        -: 1120:
     4128: 1121:InvariantDeclaration *Parser::parseInvariant()
        -: 1122:{
        -: 1123:    InvariantDeclaration *f;
     4128: 1124:    Loc loc = this->loc;
        -: 1125:
     4128: 1126:    nextToken();
     4128: 1127:    if (token.value == TOKlparen)       // optional ()
        -: 1128:    {
     4128: 1129:        nextToken();
     4128: 1130:        check(TOKrparen);
        -: 1131:    }
        -: 1132:
     4128: 1133:    f = new InvariantDeclaration(loc, 0);
     4128: 1134:    f->fbody = parseStatement(PScurly);
     4128: 1135:    return f;
        -: 1136:}
        -: 1137:
        -: 1138:/*****************************************
        -: 1139: * Parse a unittest definition:
        -: 1140: *      unittest { body }
        -: 1141: * Current token is 'unittest'.
        -: 1142: */
        -: 1143:
  1854795: 1144:UnitTestDeclaration *Parser::parseUnitTest()
        -: 1145:{
        -: 1146:    UnitTestDeclaration *f;
        -: 1147:    Statement *body;
  1854795: 1148:    Loc loc = this->loc;
        -: 1149:
  1854795: 1150:    nextToken();
        -: 1151:
  1854795: 1152:    body = parseStatement(PScurly);
        -: 1153:
  1854795: 1154:    f = new UnitTestDeclaration(loc, this->loc);
  1854795: 1155:    f->fbody = body;
  1854795: 1156:    return f;
        -: 1157:}
        -: 1158:
        -: 1159:/*****************************************
        -: 1160: * Parse a new definition:
        -: 1161: *      new(arguments) { body }
        -: 1162: * Current token is 'new'.
        -: 1163: */
        -: 1164:
      195: 1165:NewDeclaration *Parser::parseNew()
        -: 1166:{
        -: 1167:    NewDeclaration *f;
        -: 1168:    Parameters *arguments;
        -: 1169:    int varargs;
      195: 1170:    Loc loc = this->loc;
        -: 1171:
      195: 1172:    nextToken();
      195: 1173:    arguments = parseParameters(&varargs);
      195: 1174:    f = new NewDeclaration(loc, 0, arguments, varargs);
      195: 1175:    parseContracts(f);
      195: 1176:    return f;
        -: 1177:}
        -: 1178:
        -: 1179:/*****************************************
        -: 1180: * Parse a delete definition:
        -: 1181: *      delete(arguments) { body }
        -: 1182: * Current token is 'delete'.
        -: 1183: */
        -: 1184:
      194: 1185:DeleteDeclaration *Parser::parseDelete()
        -: 1186:{
        -: 1187:    DeleteDeclaration *f;
        -: 1188:    Parameters *arguments;
        -: 1189:    int varargs;
      194: 1190:    Loc loc = this->loc;
        -: 1191:
      194: 1192:    nextToken();
      194: 1193:    arguments = parseParameters(&varargs);
      194: 1194:    if (varargs)
    #####: 1195:        error("... not allowed in delete function
parameter list");
      194: 1196:    f = new DeleteDeclaration(loc, 0, arguments);
      194: 1197:    parseContracts(f);
      194: 1198:    return f;
        -: 1199:}
        -: 1200:
        -: 1201:/**********************************************
        -: 1202: * Parse parameter list.
        -: 1203: */
        -: 1204:
 12354457: 1205:Parameters *Parser::parseParameters(int *pvarargs)
        -: 1206:{
 12354457: 1207:    Parameters *arguments = new Parameters();
 12354457: 1208:    int varargs = 0;
 12354457: 1209:    int hasdefault = 0;
        -: 1210:
 12354457: 1211:    check(TOKlparen);
  5732638: 1212:    while (1)
        -: 1213:    {   Type *tb;
 18087095: 1214:        Identifier *ai = NULL;
        -: 1215:        Type *at;
        -: 1216:        Parameter *a;
 18087095: 1217:        StorageClass storageClass = 0;
        -: 1218:        StorageClass stc;
        -: 1219:        Expression *ae;
        -: 1220:
  3023408: 1221:        for (;1; nextToken())
        -: 1222:        {
 21110503: 1223:            switch (token.value)
        -: 1224:            {
        -: 1225:                case TOKrparen:
  2945501: 1226:                    break;
        -: 1227:
        -: 1228:                case TOKdotdotdot:
   183136: 1229:                    varargs = 1;
   183136: 1230:                    nextToken();
   183136: 1231:                    break;
        -: 1232:
        -: 1233:                case TOKconst:
   225396: 1234:                    if (peek(&token)->value == TOKlparen)
   164121: 1235:                        goto Ldefault;
    61275: 1236:                    stc = STCconst;
    61275: 1237:                    goto L2;
        -: 1238:
        -: 1239:                case TOKinvariant:
        -: 1240:                case TOKimmutable:
    27776: 1241:                    if (peek(&token)->value == TOKlparen)
    27631: 1242:                        goto Ldefault;
      145: 1243:                    stc = STCimmutable;
      145: 1244:                    goto L2;
        -: 1245:
        -: 1246:                case TOKshared:
    10832: 1247:                    if (peek(&token)->value == TOKlparen)
    #####: 1248:                        goto Ldefault;
    10832: 1249:                    stc = STCshared;
    10832: 1250:                    goto L2;
        -: 1251:
        -: 1252:                case TOKwild:
      192: 1253:                    if (peek(&token)->value == TOKlparen)
       64: 1254:                        goto Ldefault;
      128: 1255:                    stc = STCwild;
      128: 1256:                    goto L2;
        -: 1257:
  2151073: 1258:                case TOKin:        stc = STCin;
goto L2;
    76851: 1259:                case TOKout:       stc = STCout;
goto L2;
        -: 1260:#if D1INOUT
        -: 1261:                case TOKinout:
        -: 1262:#endif
   590268: 1263:                case TOKref:       stc = STCref;
goto L2;
    42865: 1264:                case TOKlazy:      stc = STClazy;
goto L2;
    83833: 1265:                case TOKscope:     stc = STCscope;
goto L2;
    #####: 1266:                case TOKfinal:     stc = STCfinal;
goto L2;
     6138: 1267:                case TOKauto:      stc = STCauto;
goto L2;
  3023408: 1268:                L2:
  3023408: 1269:                    if (storageClass & stc ||
        -: 1270:                        (storageClass & STCin && stc &
(STCconst | STCscope)) ||
        -: 1271:                        (stc & STCin && storageClass &
(STCconst | STCscope))
        -: 1272:                       )
    #####: 1273:                        error("redundant storage class
%s", Token::toChars(token.value));
  3023408: 1274:                    storageClass |= stc;
  3023408: 1275:                    composeStorageClass(storageClass);
        -: 1276:                    continue;
        -: 1277:
        -: 1278:#if 0
        -: 1279:                case TOKstatic:    stc =
STCstatic;             goto L2;
        -: 1280:                case TOKauto:   storageClass =
STCauto;         goto L4;
        -: 1281:                case TOKalias:  storageClass =
STCalias;        goto L4;
        -: 1282:                L4:
        -: 1283:                    nextToken();
        -: 1284:                    if (token.value == TOKidentifier)
        -: 1285:                    {   ai = token.ident;
        -: 1286:                        nextToken();
        -: 1287:                    }
        -: 1288:                    else
        -: 1289:                        ai = NULL;
        -: 1290:                    at = NULL;          // no type
        -: 1291:                    ae = NULL;          // no default
argument
        -: 1292:                    if (token.value == TOKassign)
// = defaultArg
        -: 1293:                    {   nextToken();
        -: 1294:                        ae = parseDefaultInitExp();
        -: 1295:                        hasdefault = 1;
        -: 1296:                    }
        -: 1297:                    else
        -: 1298:                    {   if (hasdefault)
        -: 1299:                            error("default argument
expected for alias %s",
        -: 1300:                                    ai ? ai->toChars() :
"");
        -: 1301:                    }
        -: 1302:                    goto L3;
        -: 1303:#endif
        -: 1304:
        -: 1305:                default:
 14958458: 1306:                Ldefault:
 14958458: 1307:                    stc = storageClass & (STCin | STCout
| STCref | STClazy);
 14958458: 1308:                    if (stc & (stc - 1))        // if
stc is not a power of 2
    #####: 1309:                        error("incompatible parameter
storage classes");
 14958458: 1310:                    if ((storageClass & (STCconst |
STCout)) == (STCconst | STCout))
    #####: 1311:                        error("out cannot be const");
 14958458: 1312:                    if ((storageClass & (STCimmutable |
STCout)) == (STCimmutable | STCout))
    #####: 1313:                        error("out cannot be immutable");
 14958458: 1314:                    if ((storageClass & STCscope) &&
        -: 1315:                        (storageClass & (STCref | STCout)))
    #####: 1316:                        error("scope cannot be ref or out");
 14958458: 1317:                    at = parseType(&ai);
 14958458: 1318:                    ae = NULL;
 14958458: 1319:                    if (token.value == TOKassign)
// = defaultArg
   386478: 1320:                    {   nextToken();
   386478: 1321:                        ae = parseDefaultInitExp();
   386478: 1322:                        hasdefault = 1;
        -: 1323:                    }
        -: 1324:                    else
 14571980: 1325:                    {   if (hasdefault)
        -: 1326:                            error("default argument
expected for %s",
    #####: 1327:                                    ai ? ai->toChars() :
at->toChars());
        -: 1328:                    }
 14958458: 1329:                    if (token.value == TOKdotdotdot)
        -: 1330:                    {   /* This is:
        -: 1331:                         *      at ai ...
        -: 1332:                         */
        -: 1333:
    20714: 1334:                        if (storageClass & (STCout |
STCref))
    #####: 1335:                            error("variadic argument
cannot be out or ref");
    20714: 1336:                        varargs = 2;
    20714: 1337:                        a = new Parameter(storageClass,
at, ai, ae);
    20714: 1338:                        arguments->push(a);
    20714: 1339:                        nextToken();
    20714: 1340:                        break;
        -: 1341:                    }
 14937744: 1342:                L3:
 14937744: 1343:                    a = new Parameter(storageClass, at,
ai, ae);
 14937744: 1344:                    arguments->push(a);
 14937744: 1345:                    if (token.value == TOKcomma)
  5732638: 1346:                    {   nextToken();
  5732638: 1347:                        goto L1;
        -: 1348:                    }
        -: 1349:                    break;
        -: 1350:            }
        -: 1351:            break;
        -: 1352:        }
        -: 1353:        break;
        -: 1354:
  5732638: 1355:    L1: ;
        -: 1356:    }
 12354457: 1357:    check(TOKrparen);
 12354457: 1358:    *pvarargs = varargs;
 12354457: 1359:    return arguments;
        -: 1360:}
        -: 1361:
        -: 1362:
        -: 1363:/*************************************
        -: 1364: */
        -: 1365:
   371780: 1366:EnumDeclaration *Parser::parseEnum()
        -: 1367:{   EnumDeclaration *e;
        -: 1368:    Identifier *id;
        -: 1369:    Type *memtype;
   371780: 1370:    Loc loc = this->loc;
        -: 1371:
        -: 1372:    //printf("Parser::parseEnum()\n");
   371780: 1373:    nextToken();
   371780: 1374:    if (token.value == TOKidentifier)
   133216: 1375:    {   id = token.ident;
   133216: 1376:        nextToken();
        -: 1377:    }
        -: 1378:    else
   238564: 1379:        id = NULL;
        -: 1380:
   371780: 1381:    if (token.value == TOKcolon)
        -: 1382:    {
    64329: 1383:        nextToken();
    64329: 1384:        memtype = parseBasicType();
    64329: 1385:        memtype = parseDeclarator(memtype, NULL, NULL);
        -: 1386:    }
        -: 1387:    else
   307451: 1388:        memtype = NULL;
        -: 1389:
   371780: 1390:    e = new EnumDeclaration(loc, id, memtype);
   371844: 1391:    if (token.value == TOKsemicolon && id)
       64: 1392:        nextToken();
   371716: 1393:    else if (token.value == TOKlcurly)
        -: 1394:    {
        -: 1395:        //printf("enum definition\n");
   371716: 1396:        e->members = new Dsymbols();
   371716: 1397:        nextToken();
   371716: 1398:        unsigned char *comment = token.blockComment;
  3340072: 1399:        while (token.value != TOKrcurly)
        -: 1400:        {
        -: 1401:            /* Can take the following forms:
        -: 1402:             *  1. ident
        -: 1403:             *  2. ident = value
        -: 1404:             *  3. type ident = value
        -: 1405:             */
        -: 1406:
  2596640: 1407:            loc = this->loc;
        -: 1408:
  2596640: 1409:            Type *type = NULL;
        -: 1410:            Identifier *ident;
  2596640: 1411:            Token *tp = peek(&token);
  5193215: 1412:            if (token.value == TOKidentifier &&
        -: 1413:                (tp->value == TOKassign || tp->value ==
TOKcomma || tp->value == TOKrcurly))
        -: 1414:            {
  2596575: 1415:                ident = token.ident;
  2596575: 1416:                type = NULL;
  2596575: 1417:                nextToken();
        -: 1418:            }
        -: 1419:            else
        -: 1420:            {
       65: 1421:                type = parseType(&ident, NULL);
       65: 1422:                if (id || memtype)
    #####: 1423:                    error("type only allowed if
anonymous enum and no enum type");
        -: 1424:            }
        -: 1425:
        -: 1426:            Expression *value;
  2596640: 1427:            if (token.value == TOKassign)
        -: 1428:            {
  1008784: 1429:                nextToken();
  1008784: 1430:                value = parseAssignExp();
        -: 1431:            }
        -: 1432:            else
  1587856: 1433:            {   value = NULL;
  1587856: 1434:                if (type)
    #####: 1435:                    error("if type, there must be an
initializer");
        -: 1436:            }
        -: 1437:
  2596640: 1438:            EnumMember *em = new EnumMember(loc, ident,
value, type);
  2596640: 1439:            e->members->push(em);
        -: 1440:
  2596640: 1441:            if (token.value == TOKrcurly)
        -: 1442:                ;
        -: 1443:            else
  2494723: 1444:            {   addComment(em, comment);
  2494723: 1445:                comment = NULL;
  2494723: 1446:                check(TOKcomma);
        -: 1447:            }
  2596640: 1448:            addComment(em, comment);
  2596640: 1449:            comment = token.blockComment;
        -: 1450:        }
   371716: 1451:        nextToken();
        -: 1452:    }
        -: 1453:    else
    #####: 1454:        error("enum declaration is invalid");
        -: 1455:
        -: 1456:    //printf("-parseEnum() %s\n", e->toChars());
   371780: 1457:    return e;
        -: 1458:}
        -: 1459:
        -: 1460:/********************************
        -: 1461: * Parse struct, union, interface, class.
        -: 1462: */
        -: 1463:
  1640958: 1464:Dsymbol *Parser::parseAggregate()
  1640958: 1465:{   AggregateDeclaration *a = NULL;
  1640958: 1466:    int anon = 0;
        -: 1467:    enum TOK tok;
        -: 1468:    Identifier *id;
  1640958: 1469:    TemplateParameters *tpl = NULL;
  1640958: 1470:    Expression *constraint = NULL;
        -: 1471:
        -: 1472:    //printf("Parser::parseAggregate()\n");
  1640958: 1473:    tok = token.value;
  1640958: 1474:    nextToken();
  1640958: 1475:    if (token.value != TOKidentifier)
    43250: 1476:    {   id = NULL;
        -: 1477:    }
        -: 1478:    else
  1597708: 1479:    {   id = token.ident;
  1597708: 1480:        nextToken();
        -: 1481:
  1597708: 1482:        if (token.value == TOKlparen)
        -: 1483:        {   // Class template declaration.
        -: 1484:
        -: 1485:            // Gather template parameter list
   201961: 1486:            tpl = parseTemplateParameterList();
   201961: 1487:            constraint = parseConstraint();
        -: 1488:        }
        -: 1489:    }
        -: 1490:
  1640958: 1491:    Loc loc = this->loc;
  1640958: 1492:    switch (tok)
        -: 1493:    {   case TOKclass:
        -: 1494:        case TOKinterface:
        -: 1495:        {
   599577: 1496:            if (!id)
    #####: 1497:                error("anonymous classes not allowed");
        -: 1498:
        -: 1499:            // Collect base class(es)
   599577: 1500:            BaseClasses *baseclasses = NULL;
   599577: 1501:            if (token.value == TOKcolon)
        -: 1502:            {
   320476: 1503:                nextToken();
   320476: 1504:                baseclasses = parseBaseClasses();
        -: 1505:
   320476: 1506:                if (token.value != TOKlcurly)
    #####: 1507:                    error("members expected");
        -: 1508:            }
        -: 1509:
   599577: 1510:            if (tok == TOKclass)
   390952: 1511:                a = new ClassDeclaration(loc, id,
baseclasses);
        -: 1512:            else
   208625: 1513:                a = new InterfaceDeclaration(loc, id,
baseclasses);
   599577: 1514:            break;
        -: 1515:        }
        -: 1516:
        -: 1517:        case TOKstruct:
   959784: 1518:            if (id)
   953658: 1519:                a = new StructDeclaration(loc, id);
        -: 1520:            else
     6126: 1521:                anon = 1;
   959784: 1522:            break;
        -: 1523:
        -: 1524:        case TOKunion:
    81597: 1525:            if (id)
    44473: 1526:                a = new UnionDeclaration(loc, id);
        -: 1527:            else
    37124: 1528:                anon = 2;
    81597: 1529:            break;
        -: 1530:
        -: 1531:        default:
    #####: 1532:            assert(0);
        -: 1533:            break;
        -: 1534:    }
  1641087: 1535:    if (a && token.value == TOKsemicolon)
      129: 1536:    {   nextToken();
        -: 1537:    }
  1640829: 1538:    else if (token.value == TOKlcurly)
        -: 1539:    {
        -: 1540:        //printf("aggregate definition\n");
  1640829: 1541:        nextToken();
  1640829: 1542:        Dsymbols *decl = parseDeclDefs(0);
  1640829: 1543:        if (token.value != TOKrcurly)
    #####: 1544:            error("} expected following member
declarations in aggregate");
  1640829: 1545:        nextToken();
  1640829: 1546:        if (anon)
        -: 1547:        {
        -: 1548:            /* Anonymous structs/unions are more like
attributes.
        -: 1549:             */
    43250: 1550:            return new AnonDeclaration(loc, anon - 1, decl);
        -: 1551:        }
        -: 1552:        else
  1597579: 1553:            a->members = decl;
        -: 1554:    }
        -: 1555:    else
        -: 1556:    {
    #####: 1557:        error("{ } expected following aggregate
declaration");
    #####: 1558:        a = new StructDeclaration(loc, NULL);
        -: 1559:    }
        -: 1560:
  1597708: 1561:    if (tpl)
        -: 1562:    {   // Wrap a template around the aggregate declaration
        -: 1563:
   201961: 1564:        Dsymbols *decldefs = new Dsymbols();
   201961: 1565:        decldefs->push(a);
        -: 1566:        TemplateDeclaration *tempdecl =
   201961: 1567:                new TemplateDeclaration(loc, id, tpl,
constraint, decldefs, 0);
   201961: 1568:        return tempdecl;
        -: 1569:    }
        -: 1570:
  1395747: 1571:    return a;
        -: 1572:}
        -: 1573:
        -: 1574:/*******************************************
        -: 1575: */
        -: 1576:
   323895: 1577:BaseClasses *Parser::parseBaseClasses()
        -: 1578:{
   323895: 1579:    BaseClasses *baseclasses = new BaseClasses();
        -: 1580:
    55456: 1581:    for (; 1; nextToken())
        -: 1582:    {
   379351: 1583:        enum PROT protection = PROTpublic;
   379351: 1584:        switch (token.value)
        -: 1585:        {
        -: 1586:            case TOKprivate:
    #####: 1587:                protection = PROTprivate;
    #####: 1588:                nextToken();
    #####: 1589:                break;
        -: 1590:            case TOKpackage:
    #####: 1591:                protection = PROTpackage;
    #####: 1592:                nextToken();
    #####: 1593:                break;
        -: 1594:            case TOKprotected:
    #####: 1595:                protection = PROTprotected;
    #####: 1596:                nextToken();
    #####: 1597:                break;
        -: 1598:            case TOKpublic:
       64: 1599:                protection = PROTpublic;
       64: 1600:                nextToken();
        -: 1601:                break;
        -: 1602:        }
   379351: 1603:        if (token.value == TOKidentifier)
        -: 1604:        {
   379351: 1605:            BaseClass *b = new
BaseClass(parseBasicType(), protection);
   379351: 1606:            baseclasses->push(b);
   379351: 1607:            if (token.value != TOKcomma)
   323895: 1608:                break;
        -: 1609:        }
        -: 1610:        else
        -: 1611:        {
    #####: 1612:            error("base classes expected instead of %s",
token.toChars());
    #####: 1613:            return NULL;
        -: 1614:        }
        -: 1615:    }
   323895: 1616:    return baseclasses;
        -: 1617:}
        -: 1618:
        -: 1619:/**************************************
        -: 1620: * Parse constraint.
        -: 1621: * Constraint is of the form:
        -: 1622: *      if ( ConstraintExpression )
        -: 1623: */
        -: 1624:
        -: 1625:#if DMDV2
  2639918: 1626:Expression *Parser::parseConstraint()
  2639918: 1627:{   Expression *e = NULL;
        -: 1628:
  2639918: 1629:    if (token.value == TOKif)
        -: 1630:    {
   924732: 1631:        nextToken();    // skip over 'if'
   924732: 1632:        check(TOKlparen);
   924732: 1633:        e = parseExpression();
   924732: 1634:        check(TOKrparen);
        -: 1635:    }
  2639918: 1636:    return e;
        -: 1637:}
        -: 1638:#endif
        -: 1639:
        -: 1640:/**************************************
        -: 1641: * Parse a TemplateDeclaration.
        -: 1642: */
        -: 1643:
   861634: 1644:TemplateDeclaration
*Parser::parseTemplateDeclaration(int ismixin)
        -: 1645:{
        -: 1646:    TemplateDeclaration *tempdecl;
        -: 1647:    Identifier *id;
        -: 1648:    TemplateParameters *tpl;
        -: 1649:    Dsymbols *decldefs;
   861634: 1650:    Expression *constraint = NULL;
   861634: 1651:    Loc loc = this->loc;
        -: 1652:
   861634: 1653:    nextToken();
   861634: 1654:    if (token.value != TOKidentifier)
    #####: 1655:    {   error("TemplateIdentifier expected following
template");
    #####: 1656:        goto Lerr;
        -: 1657:    }
   861634: 1658:    id = token.ident;
   861634: 1659:    nextToken();
   861634: 1660:    tpl = parseTemplateParameterList();
   861634: 1661:    if (!tpl)
    #####: 1662:        goto Lerr;
        -: 1663:
   861634: 1664:    constraint = parseConstraint();
        -: 1665:
   861634: 1666:    if (token.value != TOKlcurly)
    #####: 1667:    {   error("members of template declaration expected");
    #####: 1668:        goto Lerr;
        -: 1669:    }
        -: 1670:    else
        -: 1671:    {
   861634: 1672:        nextToken();
   861634: 1673:        decldefs = parseDeclDefs(0);
   861634: 1674:        if (token.value != TOKrcurly)
    #####: 1675:        {   error("template member expected");
    #####: 1676:            goto Lerr;
        -: 1677:        }
   861634: 1678:        nextToken();
        -: 1679:    }
        -: 1680:
   861634: 1681:    tempdecl = new TemplateDeclaration(loc, id, tpl,
constraint, decldefs, ismixin);
   861634: 1682:    return tempdecl;
        -: 1683:
    #####: 1684:Lerr:
    #####: 1685:    return NULL;
        -: 1686:}
        -: 1687:
        -: 1688:/******************************************
        -: 1689: * Parse template parameter list.
        -: 1690: * Input:
        -: 1691: *      flag    0: parsing "( list )"
        -: 1692: *              1: parsing non-empty "list )"
        -: 1693: */
        -: 1694:
  2667645: 1695:TemplateParameters
*Parser::parseTemplateParameterList(int flag)
        -: 1696:{
  2667645: 1697:    TemplateParameters *tpl = new TemplateParameters();
        -: 1698:
  2667645: 1699:    if (!flag && token.value != TOKlparen)
    #####: 1700:    {   error("parenthesized TemplateParameterList
expected following TemplateIdentifier");
    #####: 1701:        goto Lerr;
        -: 1702:    }
  2667645: 1703:    nextToken();
        -: 1704:
        -: 1705:    // Get array of TemplateParameters
  2667645: 1706:    if (flag || token.value != TOKrparen)
  2471139: 1707:    {   int isvariadic = 0;
        -: 1708:
  6407739: 1709:        while (token.value != TOKrparen)
        -: 1710:        {   TemplateParameter *tp;
  3936536: 1711:            Identifier *tp_ident = NULL;
  3936536: 1712:            Type *tp_spectype = NULL;
  3936536: 1713:            Type *tp_valtype = NULL;
  3936536: 1714:            Type *tp_defaulttype = NULL;
  3936536: 1715:            Expression *tp_specvalue = NULL;
  3936536: 1716:            Expression *tp_defaultvalue = NULL;
        -: 1717:            Token *t;
        -: 1718:
        -: 1719:            // Get TemplateParameter
        -: 1720:
        -: 1721:            // First, look ahead to see if it is a
TypeParameter or a ValueParameter
  3936536: 1722:            t = peek(&token);
  3936536: 1723:            if (token.value == TOKalias)
        -: 1724:            {   // AliasParameter
   379063: 1725:                nextToken();
   379063: 1726:                Type *spectype = NULL;
   379063: 1727:                if (isDeclaration(&token, 2,
TOKreserved, NULL))
        -: 1728:                {
       64: 1729:                    spectype = parseType(&tp_ident);
        -: 1730:                }
        -: 1731:                else
        -: 1732:                {
   378999: 1733:                    if (token.value != TOKidentifier)
    #####: 1734:                    {   error("identifier expected for
template alias parameter");
    #####: 1735:                        goto Lerr;
        -: 1736:                    }
   378999: 1737:                    tp_ident = token.ident;
   378999: 1738:                    nextToken();
        -: 1739:                }
   379063: 1740:                Object *spec = NULL;
   379063: 1741:                if (token.value == TOKcolon)    // : Type
        -: 1742:                {
    #####: 1743:                    nextToken();
    #####: 1744:                    if (isDeclaration(&token, 0,
TOKreserved, NULL))
    #####: 1745:                        spec = parseType();
        -: 1746:                    else
    #####: 1747:                        spec = parseCondExp();
        -: 1748:                }
   379063: 1749:                Object *def = NULL;
   379063: 1750:                if (token.value == TOKassign)   // = Type
        -: 1751:                {
   172968: 1752:                    nextToken();
   172968: 1753:                    if (isDeclaration(&token, 0,
TOKreserved, NULL))
     3159: 1754:                        def = parseType();
        -: 1755:                    else
   169809: 1756:                        def = parseCondExp();
        -: 1757:                }
   379063: 1758:                tp = new TemplateAliasParameter(loc,
tp_ident, spectype, spec, def);
        -: 1759:            }
  6147910: 1760:            else if (t->value == TOKcolon || t->value ==
TOKassign ||
        -: 1761:                     t->value == TOKcomma || t->value ==
TOKrparen)
        -: 1762:            {   // TypeParameter
  2590437: 1763:                if (token.value != TOKidentifier)
    #####: 1764:                {   error("identifier expected for
template type parameter");
    #####: 1765:                    goto Lerr;
        -: 1766:                }
  2590437: 1767:                tp_ident = token.ident;
  2590437: 1768:                nextToken();
  2590437: 1769:                if (token.value == TOKcolon)    // : Type
        -: 1770:                {
    58829: 1771:                    nextToken();
    58829: 1772:                    tp_spectype = parseType();
        -: 1773:                }
  2590437: 1774:                if (token.value == TOKassign)   // = Type
        -: 1775:                {
    39086: 1776:                    nextToken();
    39086: 1777:                    tp_defaulttype = parseType();
        -: 1778:                }
  2590437: 1779:                tp = new TemplateTypeParameter(loc,
tp_ident, tp_spectype, tp_defaulttype);
        -: 1780:            }
  1478795: 1781:            else if (token.value == TOKidentifier &&
t->value == TOKdotdotdot)
        -: 1782:            {   // ident...
   511759: 1783:                if (isvariadic)
    #####: 1784:                    error("variadic template parameter
must be last");
   511759: 1785:                isvariadic = 1;
   511759: 1786:                tp_ident = token.ident;
   511759: 1787:                nextToken();
   511759: 1788:                nextToken();
   511759: 1789:                tp = new TemplateTupleParameter(loc,
tp_ident);
        -: 1790:            }
        -: 1791:#if DMDV2
   455277: 1792:            else if (token.value == TOKthis)
        -: 1793:            {   // ThisParameter
       64: 1794:                nextToken();
       64: 1795:                if (token.value != TOKidentifier)
    #####: 1796:                {   error("identifier expected for
template this parameter");
    #####: 1797:                    goto Lerr;
        -: 1798:                }
       64: 1799:                tp_ident = token.ident;
       64: 1800:                nextToken();
       64: 1801:                if (token.value == TOKcolon)    // : Type
        -: 1802:                {
    #####: 1803:                    nextToken();
    #####: 1804:                    tp_spectype = parseType();
        -: 1805:                }
       64: 1806:                if (token.value == TOKassign)   // = Type
        -: 1807:                {
    #####: 1808:                    nextToken();
    #####: 1809:                    tp_defaulttype = parseType();
        -: 1810:                }
       64: 1811:                tp = new TemplateThisParameter(loc,
tp_ident, tp_spectype, tp_defaulttype);
        -: 1812:            }
        -: 1813:#endif
        -: 1814:            else
        -: 1815:            {   // ValueParameter
   455213: 1816:                tp_valtype = parseType(&tp_ident);
   455213: 1817:                if (!tp_ident)
        -: 1818:                {
    #####: 1819:                    error("identifier expected for
template value parameter");
    #####: 1820:                    tp_ident = new Identifier("error",
TOKidentifier);
        -: 1821:                }
   455213: 1822:                if (token.value == TOKcolon)    // :
CondExpression
        -: 1823:                {
     7214: 1824:                    nextToken();
     7214: 1825:                    tp_specvalue = parseCondExp();
        -: 1826:                }
   455213: 1827:                if (token.value == TOKassign)   // =
CondExpression
        -: 1828:                {
   139184: 1829:                    nextToken();
   139184: 1830:                    tp_defaultvalue = parseDefaultInitExp();
        -: 1831:                }
   455213: 1832:                tp = new TemplateValueParameter(loc,
tp_ident, tp_valtype, tp_specvalue, tp_defaultvalue);
        -: 1833:            }
  3936536: 1834:            tpl->push(tp);
  3936536: 1835:            if (token.value != TOKcomma)
  2471075: 1836:                break;
  1465461: 1837:            nextToken();
        -: 1838:        }
        -: 1839:    }
  2667645: 1840:    check(TOKrparen);
  2667645: 1841:Lerr:
  2667645: 1842:    return tpl;
        -: 1843:}
        -: 1844:
        -: 1845:/******************************************
        -: 1846: * Parse template mixin.
        -: 1847: *      mixin Foo;
        -: 1848: *      mixin Foo!(args);
        -: 1849: *      mixin a.b.c!(args).Foo!(args);
        -: 1850: *      mixin Foo!(args) identifier;
        -: 1851: *      mixin typeof(expr).identifier!(args);
        -: 1852: */
        -: 1853:
   130102: 1854:Dsymbol *Parser::parseMixin()
        -: 1855:{
        -: 1856:    TemplateMixin *tm;
        -: 1857:    Identifier *id;
        -: 1858:    Type *tqual;
        -: 1859:    Objects *tiargs;
        -: 1860:    Array *idents;
        -: 1861:
        -: 1862:    //printf("parseMixin()\n");
   130102: 1863:    nextToken();
   130102: 1864:    tqual = NULL;
   130102: 1865:    if (token.value == TOKdot)
        -: 1866:    {
        1: 1867:        id = Id::empty;
        -: 1868:    }
        -: 1869:    else
        -: 1870:    {
   130101: 1871:        if (token.value == TOKtypeof)
        -: 1872:        {
       64: 1873:            tqual = parseTypeof();
       64: 1874:            check(TOKdot);
        -: 1875:        }
   130101: 1876:        if (token.value != TOKidentifier)
        -: 1877:        {
    #####: 1878:            error("identifier expected, not %s",
token.toChars());
    #####: 1879:            id = Id::empty;
        -: 1880:        }
        -: 1881:        else
   130101: 1882:            id = token.ident;
   130101: 1883:        nextToken();
        -: 1884:    }
        -: 1885:
   130102: 1886:    idents = new Array();
       65: 1887:    while (1)
        -: 1888:    {
   130167: 1889:        tiargs = NULL;
   130167: 1890:        if (token.value == TOKnot)
        -: 1891:        {
    18870: 1892:            nextToken();
    18870: 1893:            if (token.value == TOKlparen)
    18870: 1894:                tiargs = parseTemplateArgumentList();
        -: 1895:            else
    #####: 1896:                tiargs = parseTemplateArgument();
        -: 1897:        }
        -: 1898:
   130167: 1899:        if (token.value != TOKdot)
   130102: 1900:            break;
        -: 1901:
       65: 1902:        if (tiargs)
    #####: 1903:        {   TemplateInstance *tempinst = new
TemplateInstance(loc, id);
    #####: 1904:            tempinst->tiargs = tiargs;
    #####: 1905:            id = (Identifier *)tempinst;
    #####: 1906:            tiargs = NULL;
        -: 1907:        }
       65: 1908:        idents->push(id);
        -: 1909:
       65: 1910:        nextToken();
       65: 1911:        if (token.value != TOKidentifier)
    #####: 1912:        {   error("identifier expected following '.'
instead of '%s'", token.toChars());
    #####: 1913:            break;
        -: 1914:        }
       65: 1915:        id = token.ident;
       65: 1916:        nextToken();
        -: 1917:    }
   130102: 1918:    idents->push(id);
        -: 1919:
   130102: 1920:    if (token.value == TOKidentifier)
        -: 1921:    {
    23394: 1922:        id = token.ident;
    23394: 1923:        nextToken();
        -: 1924:    }
        -: 1925:    else
   106708: 1926:        id = NULL;
        -: 1927:
   130102: 1928:    tm = new TemplateMixin(loc, id, tqual, idents, tiargs);
   130102: 1929:    if (token.value != TOKsemicolon)
    #####: 1930:        error("';' expected after mixin");
   130102: 1931:    nextToken();
        -: 1932:
   130102: 1933:    return tm;
        -: 1934:}
        -: 1935:
        -: 1936:/******************************************
        -: 1937: * Parse template argument list.
        -: 1938: * Input:
        -: 1939: *      current token is opening '('
        -: 1940: * Output:
        -: 1941: *      current token is one after closing ')'
        -: 1942: */
        -: 1943:
  6614044: 1944:Objects *Parser::parseTemplateArgumentList()
        -: 1945:{
        -: 1946:    //printf("Parser::parseTemplateArgumentList()\n");
  6614044: 1947:    if (token.value != TOKlparen && token.value !=
TOKlcurly)
    #####: 1948:    {   error("!(TemplateArgumentList) expected
following TemplateIdentifier");
    #####: 1949:        return new Objects();
        -: 1950:    }
  6614044: 1951:    return parseTemplateArgumentList2();
        -: 1952:}
        -: 1953:
  6819378: 1954:Objects *Parser::parseTemplateArgumentList2()
        -: 1955:{
        -: 1956:    //printf("Parser::parseTemplateArgumentList2()\n");
  6819378: 1957:    Objects *tiargs = new Objects();
  6819378: 1958:    enum TOK endtok = TOKrparen;
  6819378: 1959:    nextToken();
        -: 1960:
        -: 1961:    // Get TemplateArgumentList
 17140206: 1962:    while (token.value != endtok)
        -: 1963:    {
        -: 1964:            // See if it is an Expression or a Type
 10227997: 1965:            if (isDeclaration(&token, 0, TOKreserved, NULL))
        -: 1966:            {   // Template argument is a type
  8857866: 1967:                Type *ta = parseType();
  8857866: 1968:                tiargs->push(ta);
        -: 1969:            }
        -: 1970:            else
        -: 1971:            {   // Template argument is an expression
  1370131: 1972:                Expression *ea = parseAssignExp();
        -: 1973:
  1370131: 1974:                if (ea->op == TOKfunction)
    85572: 1975:                {   FuncLiteralDeclaration *fd =
((FuncExp *)ea)->fd;
    85572: 1976:                    if (fd->type->ty == Tfunction)
        -: 1977:                    {
    85572: 1978:                        TypeFunction *tf = (TypeFunction
*)fd->type;
        -: 1979:                        /* If there are parameters that
consist of only an identifier,
        -: 1980:                         * rather than assuming the
identifier is a type, as we would
        -: 1981:                         * for regular function
declarations, assume the identifier
        -: 1982:                         * is the parameter name, and
we're building a template with
        -: 1983:                         * a deduced type.
        -: 1984:                         */
    85572: 1985:                        TemplateParameters *tpl = NULL;
   162307: 1986:                        for (int i = 0; i <
tf->parameters->dim; i++)
    76735: 1987:                        {   Parameter *param =
(Parameter *)tf->parameters->data[i];
    76735: 1988:                            if (param->ident == NULL &&
        -: 1989:                                param->type &&
        -: 1990:                                param->type->ty == Tident &&
        -: 1991:                                ((TypeIdentifier
*)param->type)->idents.dim == 0
        -: 1992:                               )
        -: 1993:                            {
        -: 1994:                                /* Switch parameter type
to parameter identifier,
        -: 1995:                                 * parameterize with
template type parameter _T
        -: 1996:                                 */
    24760: 1997:                                TypeIdentifier *pt =
(TypeIdentifier *)param->type;
    24760: 1998:                                param->ident = pt->ident;
    24760: 1999:                                Identifier *id =
Lexer::uniqueId("__T");
    24760: 2000:                                param->type = new
TypeIdentifier(pt->loc, id);
    24760: 2001:                                TemplateParameter *tp =
new TemplateTypeParameter(fd->loc, id, NULL, NULL);
    24760: 2002:                                if (!tpl)
    21473: 2003:                                    tpl = new
TemplateParameters();
    24760: 2004:                                tpl->push(tp);
        -: 2005:                            }
        -: 2006:                        }
        -: 2007:
    85572: 2008:                        if (tpl)
        -: 2009:                        {   // Wrap a template around
function fd
    21473: 2010:                            Dsymbols *decldefs = new
Dsymbols();
    21473: 2011:                            decldefs->push(fd);
        -: 2012:                            TemplateDeclaration *tempdecl =
    21473: 2013:                                new
TemplateDeclaration(fd->loc, fd->ident, tpl, NULL, decldefs, 0);
    21473: 2014:                            tempdecl->literal = 1;
// it's a template 'literal'
    21473: 2015:                            tiargs->push(tempdecl);
    21473: 2016:                            goto L1;
        -: 2017:                        }
        -: 2018:                    }
        -: 2019:                }
        -: 2020:
  1348658: 2021:                tiargs->push(ea);
        -: 2022:            }
 10227997: 2023:         L1:
 10227997: 2024:            if (token.value != TOKcomma)
  6726547: 2025:                break;
  3501450: 2026:            nextToken();
        -: 2027:    }
  6819378: 2028:    check(endtok, "template argument list");
  6819378: 2029:    return tiargs;
        -: 2030:}
        -: 2031:
        -: 2032:/*****************************
        -: 2033: * Parse single template argument, to support the syntax:
        -: 2034: *      foo!arg
        -: 2035: * Input:
        -: 2036: *      current token is the arg
        -: 2037: */
        -: 2038:
  3290982: 2039:Objects *Parser::parseTemplateArgument()
        -: 2040:{
        -: 2041:    //printf("parseTemplateArgument()\n");
  3290982: 2042:    Objects *tiargs = new Objects();
        -: 2043:    Type *ta;
  3290982: 2044:    switch (token.value)
        -: 2045:    {
        -: 2046:        case TOKidentifier:
  2408057: 2047:            ta = new TypeIdentifier(loc, token.ident);
  2408057: 2048:            goto LabelX;
        -: 2049:
    #####: 2050:        case BASIC_TYPES_X(ta):
  3128650: 2051:            tiargs->push(ta);
  3128650: 2052:            nextToken();
  3128650: 2053:            break;
        -: 2054:
        -: 2055:        case TOKint32v:
        -: 2056:        case TOKuns32v:
        -: 2057:        case TOKint64v:
        -: 2058:        case TOKuns64v:
        -: 2059:        case TOKfloat32v:
        -: 2060:        case TOKfloat64v:
        -: 2061:        case TOKfloat80v:
        -: 2062:        case TOKimaginary32v:
        -: 2063:        case TOKimaginary64v:
        -: 2064:        case TOKimaginary80v:
        -: 2065:        case TOKnull:
        -: 2066:        case TOKtrue:
        -: 2067:        case TOKfalse:
        -: 2068:        case TOKcharv:
        -: 2069:        case TOKwcharv:
        -: 2070:        case TOKdcharv:
        -: 2071:        case TOKstring:
        -: 2072:        case TOKfile:
        -: 2073:        case TOKline:
        -: 2074:        {   // Template argument is an expression
   162332: 2075:            Expression *ea = parsePrimaryExp();
   162332: 2076:            tiargs->push(ea);
   162332: 2077:            break;
        -: 2078:        }
        -: 2079:
        -: 2080:        default:
    #####: 2081:            error("template argument expected following !");
        -: 2082:            break;
        -: 2083:    }
  3290982: 2084:    if (token.value == TOKnot)
    #####: 2085:        error("multiple ! arguments are not allowed");
  3290982: 2086:    return tiargs;
        -: 2087:}
        -: 2088:
   683760: 2089:Import *Parser::parseImport(Dsymbols *decldefs, int
isstatic)
        -: 2090:{   Import *s;
        -: 2091:    Identifier *id;
   683760: 2092:    Identifier *aliasid = NULL;
        -: 2093:    Array *a;
   683760: 2094:    Loc loc;
        -: 2095:
        -: 2096:    //printf("Parser::parseImport()\n");
  1183729: 2097:    do
        -: 2098:    {
  1211140: 2099:     L1:
  1211140: 2100:        nextToken();
  1211140: 2101:        if (token.value != TOKidentifier)
    #####: 2102:        {   error("Identifier expected following import");
    #####: 2103:            break;
        -: 2104:        }
        -: 2105:
  1211140: 2106:        loc = this->loc;
  1211140: 2107:        a = NULL;
  1211140: 2108:        id = token.ident;
  1211140: 2109:        nextToken();
  1211140: 2110:        if (!aliasid && token.value == TOKassign)
        -: 2111:        {
    #####: 2112:            aliasid = id;
    #####: 2113:            goto L1;
        -: 2114:        }
  4388813: 2115:        while (token.value == TOKdot)
        -: 2116:        {
  1966533: 2117:            if (!a)
  1207525: 2118:                a = new Array();
  1966533: 2119:            a->push(id);
  1966533: 2120:            nextToken();
  1966533: 2121:            if (token.value != TOKidentifier)
    #####: 2122:            {   error("identifier expected following
package");
    #####: 2123:                break;
        -: 2124:            }
  1966533: 2125:            id = token.ident;
  1966533: 2126:            nextToken();
        -: 2127:        }
        -: 2128:
  1211140: 2129:        s = new Import(loc, a, id, aliasid, isstatic);
  1211140: 2130:        decldefs->push(s);
        -: 2131:
        -: 2132:        /* Look for
        -: 2133:         *      : alias=name, alias=name;
        -: 2134:         * syntax.
        -: 2135:         */
  1211140: 2136:        if (token.value == TOKcolon)
        -: 2137:        {
    39683: 2138:            do
        -: 2139:            {   Identifier *name;
        -: 2140:
    39683: 2141:                nextToken();
    39683: 2142:                if (token.value != TOKidentifier)
    #####: 2143:                {   error("Identifier expected following
:");
    #####: 2144:                    break;
        -: 2145:                }
    39683: 2146:                Identifier *alias = token.ident;
    39683: 2147:                nextToken();
    39683: 2148:                if (token.value == TOKassign)
        -: 2149:                {
    #####: 2150:                    nextToken();
    #####: 2151:                    if (token.value != TOKidentifier)
    #####: 2152:                    {   error("Identifier expected
following %s=", alias->toChars());
    #####: 2153:                        break;
        -: 2154:                    }
    #####: 2155:                    name = token.ident;
    #####: 2156:                    nextToken();
        -: 2157:                }
        -: 2158:                else
    39683: 2159:                {   name = alias;
    39683: 2160:                    alias = NULL;
        -: 2161:                }
    39683: 2162:                s->addAlias(name, alias);
        -: 2163:            } while (token.value == TOKcomma);
    27411: 2164:            break;      // no comma-separated imports of
this form
        -: 2165:        }
        -: 2166:
  1183729: 2167:        aliasid = NULL;
        -: 2168:    } while (token.value == TOKcomma);
        -: 2169:
   683760: 2170:    if (token.value == TOKsemicolon)
   683760: 2171:        nextToken();
        -: 2172:    else
        -: 2173:    {
    #####: 2174:        error("';' expected");
    #####: 2175:        nextToken();
        -: 2176:    }
        -: 2177:
   683760: 2178:    return NULL;
        -: 2179:}
        -: 2180:
        -: 2181:#if DMDV2
 32774299: 2182:Type *Parser::parseType(Identifier **pident,
TemplateParameters **tpl)
        -: 2183:{   Type *t;
        -: 2184:
        -: 2185:    /* Take care of the storage class prefixes that
        -: 2186:     * serve as type attributes:
        -: 2187:     *  const shared, shared const, const, invariant, shared
        -: 2188:     */
 32774299: 2189:    if (token.value == TOKconst && peekNext() ==
TOKshared && peekNext2() != TOKlparen ||
        -: 2190:        token.value == TOKshared && peekNext() ==
TOKconst && peekNext2() != TOKlparen)
        -: 2191:    {
       64: 2192:        nextToken();
       64: 2193:        nextToken();
        -: 2194:        /* shared const type
        -: 2195:         */
       64: 2196:        t = parseType(pident, tpl);
       64: 2197:        t = t->makeSharedConst();
       64: 2198:        return t;
        -: 2199:    }
 32774235: 2200:    else if (token.value == TOKwild && peekNext() ==
TOKshared && peekNext2() != TOKlparen ||
        -: 2201:        token.value == TOKshared && peekNext() ==
TOKwild && peekNext2() != TOKlparen)
        -: 2202:    {
    #####: 2203:        nextToken();
    #####: 2204:        nextToken();
        -: 2205:        /* shared wild type
        -: 2206:         */
    #####: 2207:        t = parseType(pident, tpl);
    #####: 2208:        t = t->makeSharedWild();
    #####: 2209:        return t;
        -: 2210:    }
 32774235: 2211:    else if (token.value == TOKconst && peekNext() !=
TOKlparen)
        -: 2212:    {
    88155: 2213:        nextToken();
        -: 2214:        /* const type
        -: 2215:         */
    88155: 2216:        t = parseType(pident, tpl);
    88155: 2217:        t = t->makeConst();
    88155: 2218:        return t;
        -: 2219:    }
 32686080: 2220:    else if ((token.value == TOKinvariant || token.value
== TOKimmutable) &&
        -: 2221:             peekNext() != TOKlparen)
        -: 2222:    {
    36436: 2223:        nextToken();
        -: 2224:        /* invariant type
        -: 2225:         */
    36436: 2226:        t = parseType(pident, tpl);
    36436: 2227:        t = t->makeInvariant();
    36436: 2228:        return t;
        -: 2229:    }
 32649644: 2230:    else if (token.value == TOKshared && peekNext() !=
TOKlparen)
        -: 2231:    {
    27407: 2232:        nextToken();
        -: 2233:        /* shared type
        -: 2234:         */
    27407: 2235:        t = parseType(pident, tpl);
    27407: 2236:        t = t->makeShared();
    27407: 2237:        return t;
        -: 2238:    }
 32622237: 2239:    else if (token.value == TOKwild && peekNext() !=
TOKlparen)
        -: 2240:    {
    #####: 2241:        nextToken();
        -: 2242:        /* wild type
        -: 2243:         */
    #####: 2244:        t = parseType(pident, tpl);
    #####: 2245:        t = t->makeWild();
    #####: 2246:        return t;
        -: 2247:    }
        -: 2248:    else
 32622237: 2249:        t = parseBasicType();
 32622237: 2250:    t = parseDeclarator(t, pident, tpl);
 32622237: 2251:    return t;
        -: 2252:}
        -: 2253:#endif
        -: 2254:
 58875351: 2255:Type *Parser::parseBasicType()
        -: 2256:{   Type *t;
        -: 2257:    Identifier *id;
        -: 2258:    TypeQualified *tid;
        -: 2259:
        -: 2260:    //printf("parseBasicType()\n");
 58875351: 2261:    switch (token.value)
        -: 2262:    {
  3604835: 2263:        case BASIC_TYPES_X(t):
 28769342: 2264:            nextToken();
 28769342: 2265:            break;
        -: 2266:
        -: 2267:        case TOKidentifier:
 27954149: 2268:            id = token.ident;
 27954149: 2269:            nextToken();
 27954149: 2270:            if (token.value == TOKnot)
        -: 2271:            {   // ident!(template_arguments)
  2951357: 2272:                TemplateInstance *tempinst = new
TemplateInstance(loc, id);
  2951357: 2273:                nextToken();
  2951357: 2274:                if (token.value == TOKlparen)
        -: 2275:                    // ident!(template_arguments)
  2211811: 2276:                    tempinst->tiargs =
parseTemplateArgumentList();
        -: 2277:                else
        -: 2278:                    // ident!template_argument
   739546: 2279:                    tempinst->tiargs =
parseTemplateArgument();
  2951357: 2280:                tid = new TypeInstance(loc, tempinst);
  2951357: 2281:                goto Lident2;
        -: 2282:            }
 25051802: 2283:        Lident:
 25051802: 2284:            tid = new TypeIdentifier(loc, id);
 29144109: 2285:        Lident2:
 59204393: 2286:            while (token.value == TOKdot)
   916175: 2287:            {   nextToken();
   916175: 2288:                if (token.value != TOKidentifier)
    #####: 2289:                {   error("identifier expected following
'.' instead of '%s'", token.toChars());
    #####: 2290:                    break;
        -: 2291:                }
   916175: 2292:                id = token.ident;
   916175: 2293:                nextToken();
   916175: 2294:                if (token.value == TOKnot)
        -: 2295:                {
    49329: 2296:                    TemplateInstance *tempinst = new
TemplateInstance(loc, id);
    49329: 2297:                    nextToken();
    49329: 2298:                    if (token.value == TOKlparen)
        -: 2299:                        // ident!(template_arguments)
    37205: 2300:                        tempinst->tiargs =
parseTemplateArgumentList();
        -: 2301:                    else
        -: 2302:                        // ident!template_argument
    12124: 2303:                        tempinst->tiargs =
parseTemplateArgument();
    49329: 2304:                    tid->addIdent((Identifier *)tempinst);
        -: 2305:                }
        -: 2306:                else
   866846: 2307:                    tid->addIdent(id);
        -: 2308:            }
 29144109: 2309:            t = tid;
 29144109: 2310:            break;
        -: 2311:
        -: 2312:        case TOKdot:
        -: 2313:            // Leading . as in .foo
    49010: 2314:            id = Id::empty;
    49010: 2315:            goto Lident;
        -: 2316:
        -: 2317:        case TOKtypeof:
        -: 2318:            // typeof(expression)
  1140950: 2319:            tid = parseTypeof();
  1140950: 2320:            goto Lident2;
        -: 2321:
        -: 2322:        case TOKconst:
        -: 2323:            // const(type)
   593724: 2324:            nextToken();
   593724: 2325:            check(TOKlparen);
   593724: 2326:            t = parseType();
   593724: 2327:            check(TOKrparen);
   593724: 2328:            if (t->isShared())
      576: 2329:                t = t->makeSharedConst();
        -: 2330:            else
   593148: 2331:                t = t->makeConst();
   593724: 2332:            break;
        -: 2333:
        -: 2334:        case TOKinvariant:
    #####: 2335:            if (!global.params.useDeprecated)
    #####: 2336:                error("use of 'invariant' rather than
'immutable' is deprecated");
        -: 2337:        case TOKimmutable:
        -: 2338:            // invariant(type)
   290139: 2339:            nextToken();
   290139: 2340:            check(TOKlparen);
   290139: 2341:            t = parseType();
   290139: 2342:            check(TOKrparen);
   290139: 2343:            t = t->makeInvariant();
   290139: 2344:            break;
        -: 2345:
        -: 2346:        case TOKshared:
        -: 2347:            // shared(type)
    76757: 2348:            nextToken();
    76757: 2349:            check(TOKlparen);
    76757: 2350:            t = parseType();
    76757: 2351:            check(TOKrparen);
    76757: 2352:            if (t->isConst())
    42946: 2353:                t = t->makeSharedConst();
    33811: 2354:            else if (t->isWild())
       64: 2355:                t = t->makeSharedWild();
        -: 2356:            else
    33747: 2357:                t = t->makeShared();
    76757: 2358:            break;
        -: 2359:
        -: 2360:        case TOKwild:
        -: 2361:            // wild(type)
     1280: 2362:            nextToken();
     1280: 2363:            check(TOKlparen);
     1280: 2364:            t = parseType();
     1280: 2365:            check(TOKrparen);
     1280: 2366:            if (t->isShared())
      128: 2367:                t = t->makeSharedWild();
        -: 2368:            else
     1152: 2369:                t = t->makeWild();
     1280: 2370:            break;
        -: 2371:
        -: 2372:        default:
    #####: 2373:            error("basic type expected, not %s",
token.toChars());
    #####: 2374:            t = Type::tint32;
        -: 2375:            break;
        -: 2376:    }
 58875351: 2377:    return t;
        -: 2378:}
        -: 2379:
        -: 2380:/******************************************
        -: 2381: * Parse things that follow the initial type t.
        -: 2382: *      t *
        -: 2383: *      t []
        -: 2384: *      t [type]
        -: 2385: *      t [expression]
        -: 2386: *      t [expression .. expression]
        -: 2387: *      t function
        -: 2388: *      t delegate
        -: 2389: */
        -: 2390:
 95697569: 2391:Type *Parser::parseBasicType2(Type *t)
        -: 2392:{
        -: 2393:    //printf("parseBasicType2()\n");
 11808946: 2394:    while (1)
        -: 2395:    {
 95697569: 2396:        switch (token.value)
        -: 2397:        {
        -: 2398:            case TOKmul:
  6379418: 2399:                t = new TypePointer(t);
  6379418: 2400:                nextToken();
  6379418: 2401:                continue;
        -: 2402:
        -: 2403:            case TOKlbracket:
        -: 2404:                // Handle []. Make sure things like
        -: 2405:                //     int[3][1] a;
        -: 2406:                // is (array[1] of array[3] of int)
  4993474: 2407:                nextToken();
  4993474: 2408:                if (token.value == TOKrbracket)
        -: 2409:                {
  3299612: 2410:                    t = new
TypeDArray(t);                      // []
  3299612: 2411:                    nextToken();
        -: 2412:                }
  1693862: 2413:                else if (token.value == TOKnew &&
peekNext() == TOKrbracket)
        -: 2414:                {
    #####: 2415:                    t = new
TypeNewArray(t);                    // [new]
    #####: 2416:                    nextToken();
    #####: 2417:                    nextToken();
        -: 2418:                }
  1693862: 2419:                else if (isDeclaration(&token, 0,
TOKrbracket, NULL))
        -: 2420:                {   // It's an associative array declaration
        -: 2421:
        -: 2422:                    //printf("it's an associative array\n");
   275388: 2423:                    Type *index = parseType();
// [ type ]
   275388: 2424:                    t = new TypeAArray(t, index);
   275388: 2425:                    check(TOKrbracket);
        -: 2426:                }
        -: 2427:                else
        -: 2428:                {
        -: 2429:                    //printf("it's type[expression]\n");
  1418474: 2430:                    inBrackets++;
  1418474: 2431:                    Expression *e =
parseAssignExp();           // [ expression ]
  1418474: 2432:                    if (token.value == TOKslice)
        -: 2433:                    {
   271875: 2434:                        nextToken();
   271875: 2435:                        Expression *e2 =
parseAssignExp();      // [ exp .. exp ]
   271875: 2436:                        t = new TypeSlice(t, e, e2);
        -: 2437:                    }
        -: 2438:                    else
  1146599: 2439:                        t = new TypeSArray(t,e);
  1418474: 2440:                    inBrackets--;
  1418474: 2441:                    check(TOKrbracket);
        -: 2442:                }
  4993474: 2443:                continue;
        -: 2444:
        -: 2445:            case TOKdelegate:
        -: 2446:            case TOKfunction:
        -: 2447:            {   // Handle delegate declaration:
        -: 2448:                //      t delegate(parameter list)
nothrow pure
        -: 2449:                //      t function(parameter list)
nothrow pure
        -: 2450:                Parameters *arguments;
        -: 2451:                int varargs;
   436054: 2452:                enum TOK save = token.value;
        -: 2453:
   436054: 2454:                nextToken();
   436054: 2455:                arguments = parseParameters(&varargs);
        -: 2456:
   436054: 2457:                StorageClass stc = parsePostfix();
   436054: 2458:                if (stc & (STCconst | STCimmutable |
STCshared | STCwild))
    #####: 2459:                    error("const/immutable/shared/inout
attributes are only valid for non-static member functions");
        -: 2460:
   436054: 2461:                TypeFunction *tf = new
TypeFunction(arguments, t, varargs, linkage, stc);
        -: 2462:
   436054: 2463:                if (save == TOKdelegate)
   175516: 2464:                    t = new TypeDelegate(tf);
        -: 2465:                else
   260538: 2466:                    t = new TypePointer(tf);    //
pointer to function
   436054: 2467:                continue;
        -: 2468:            }
        -: 2469:
        -: 2470:            default:
 83888623: 2471:                return t;
        -: 2472:        }
        -: 2473:        assert(0);
        -: 2474:    }
        -: 2475:    assert(0);
        -: 2476:    return NULL;
        -: 2477:}
        -: 2478:
 58079445: 2479:Type *Parser::parseDeclarator(Type *t, Identifier
**pident, TemplateParameters **tpl)
        -: 2480:{   Type *ts;
        -: 2481:
        -: 2482:    //printf("parseDeclarator(tpl = %p)\n", tpl);
 58079445: 2483:    t = parseBasicType2(t);
        -: 2484:
 58079445: 2485:    switch (token.value)
        -: 2486:    {
        -: 2487:
        -: 2488:        case TOKidentifier:
 37291392: 2489:            if (pident)
 37291392: 2490:                *pident = token.ident;
        -: 2491:            else
    #####: 2492:                error("unexpected identifer '%s' in
declarator", token.ident->toChars());
 37291392: 2493:            ts = t;
 37291392: 2494:            nextToken();
 37291392: 2495:            break;
        -: 2496:
        -: 2497:        case TOKlparen:
        -: 2498:            /* Parse things with parentheses around the
identifier, like:
        -: 2499:             *  int (*ident[3])[]
        -: 2500:             * although the D style would be:
        -: 2501:             *  int[]*[3] ident
        -: 2502:             */
    12093: 2503:            nextToken();
    12093: 2504:            ts = parseDeclarator(t, pident);
    12093: 2505:            check(TOKrparen);
    12093: 2506:            break;
        -: 2507:
        -: 2508:        default:
 20775960: 2509:            ts = t;
        -: 2510:            break;
        -: 2511:    }
        -: 2512:
        -: 2513:    // parse DeclaratorSuffixes
   108920: 2514:    while (1)
        -: 2515:    {
 58188365: 2516:        switch (token.value)
        -: 2517:        {
        -: 2518:#if CARRAYDECL
        -: 2519:            /* Support C style array syntax:
        -: 2520:             *   int ident[]
        -: 2521:             * as opposed to D-style:
        -: 2522:             *   int[] ident
        -: 2523:             */
        -: 2524:            case TOKlbracket:
        -: 2525:            {   // This is the old C-style post [] syntax.
        -: 2526:                TypeNext *ta;
   108920: 2527:                nextToken();
   108920: 2528:                if (token.value == TOKrbracket)
        -: 2529:                {   // It's a dynamic array
    56663: 2530:                    ta = new TypeDArray(t);
// []
    56663: 2531:                    nextToken();
        -: 2532:                }
    52257: 2533:                else if (token.value == TOKnew &&
peekNext() == TOKrbracket)
        -: 2534:                {
    #####: 2535:                    t = new TypeNewArray(t);
// [new]
    #####: 2536:                    nextToken();
    #####: 2537:                    nextToken();
        -: 2538:                }
    52257: 2539:                else if (isDeclaration(&token, 0,
TOKrbracket, NULL))
        -: 2540:                {   // It's an associative array
        -: 2541:
        -: 2542:                    //printf("it's an associative array\n");
    14137: 2543:                    Type *index = parseType();
// [ type ]
    14137: 2544:                    check(TOKrbracket);
    14137: 2545:                    ta = new TypeAArray(t, index);
        -: 2546:                }
        -: 2547:                else
        -: 2548:                {
        -: 2549:                    //printf("It's a static array\n");
    38120: 2550:                    Expression *e = parseAssignExp();
// [ expression ]
    38120: 2551:                    ta = new TypeSArray(t, e);
    38120: 2552:                    check(TOKrbracket);
        -: 2553:                }
        -: 2554:
        -: 2555:                /* Insert ta into
        -: 2556:                 *   ts -> ... -> t
        -: 2557:                 * so that
        -: 2558:                 *   ts -> ... -> ta -> t
        -: 2559:                 */
        -: 2560:                Type **pt;
   108920: 2561:                for (pt = &ts; *pt != t; pt =
&((TypeNext*)*pt)->next)
        -: 2562:                    ;
   108920: 2563:                *pt = ta;
        -: 2564:                continue;
        -: 2565:            }
        -: 2566:#endif
        -: 2567:            case TOKlparen:
        -: 2568:            {
 11419624: 2569:                if (tpl)
        -: 2570:                {
        -: 2571:                    /* Look ahead to see if this is
(...)(...),
        -: 2572:                     * i.e. a function template declaration
        -: 2573:                     */
 11419496: 2574:                    if (peekPastParen(&token)->value ==
TOKlparen)
        -: 2575:                    {
        -: 2576:                        //printf("function template
declaration\n");
        -: 2577:
        -: 2578:                        // Gather template parameter list
  1547300: 2579:                        *tpl = parseTemplateParameterList();
        -: 2580:                    }
        -: 2581:                }
        -: 2582:
        -: 2583:                int varargs;
 11419624: 2584:                Parameters *arguments =
parseParameters(&varargs);
        -: 2585:
        -: 2586:                /* Parse
const/immutable/shared/inout/nothrow/pure postfix
        -: 2587:                 */
 11419624: 2588:                StorageClass stc = parsePostfix();
 11419624: 2589:                Type *tf = new TypeFunction(arguments,
t, varargs, linkage, stc);
        -: 2590:
 11419624: 2591:                if (stc & STCconst)
   181510: 2592:                {   if (tf->isShared())
    #####: 2593:                        tf = tf->makeSharedConst();
        -: 2594:                    else
   181510: 2595:                        tf = tf->makeConst();
        -: 2596:                }
 11419624: 2597:                if (stc & STCimmutable)
     3223: 2598:                    tf = tf->makeInvariant();
 11419624: 2599:                if (stc & STCshared)
    15347: 2600:                {   if (tf->isConst())
    12124: 2601:                        tf = tf->makeSharedConst();
        -: 2602:                    else
     3223: 2603:                        tf = tf->makeShared();
        -: 2604:                }
 11419624: 2605:                if (stc & STCwild)
    #####: 2606:                {   if (tf->isShared())
    #####: 2607:                        tf = tf->makeSharedWild();
        -: 2608:                    else
    #####: 2609:                        tf = tf->makeWild();
        -: 2610:                }
        -: 2611:
        -: 2612:                /* Insert tf into
        -: 2613:                 *   ts -> ... -> t
        -: 2614:                 * so that
        -: 2615:                 *   ts -> ... -> tf -> t
        -: 2616:                 */
        -: 2617:                Type **pt;
 11419624: 2618:                for (pt = &ts; *pt != t; pt =
&((TypeNext*)*pt)->next)
        -: 2619:                    ;
 11419624: 2620:                *pt = tf;
        -: 2621:                break;
        -: 2622:            }
        -: 2623:        }
        -: 2624:        break;
        -: 2625:    }
        -: 2626:
 58079445: 2627:    return ts;
        -: 2628:}
        -: 2629:
        -: 2630:/**********************************
        -: 2631: * Parse Declarations.
        -: 2632: * These can be:
        -: 2633: *      1. declarations at global/class level
        -: 2634: *      2. declarations at statement level
        -: 2635: * Return array of Declaration *'s.
        -: 2636: */
        -: 2637:
 31336505: 2638:Dsymbols *Parser::parseDeclarations(StorageClass
storage_class)
        -: 2639:{
        -: 2640:    StorageClass stc;
        -: 2641:    Type *ts;
        -: 2642:    Type *t;
        -: 2643:    Type *tfirst;
        -: 2644:    Identifier *ident;
        -: 2645:    Dsymbols *a;
 31336505: 2646:    enum TOK tok = TOKreserved;
 31336505: 2647:    unsigned char *comment = token.blockComment;
 31336505: 2648:    enum LINK link = linkage;
        -: 2649:
        -: 2650:    //printf("parseDeclarations() %s\n", token.toChars());
 31336505: 2651:    if (storage_class)
    76289: 2652:    {   ts = NULL;              // infer type
    76289: 2653:        goto L2;
        -: 2654:    }
        -: 2655:
 31260216: 2656:    switch (token.value)
        -: 2657:    {
        -: 2658:        case TOKalias:
        -: 2659:            /* Look for:
        -: 2660:             *   alias identifier this;
        -: 2661:             */
  2413974: 2662:            tok = token.value;
  2413974: 2663:            nextToken();
  2413974: 2664:            if (token.value == TOKidentifier &&
peek(&token)->value == TOKthis)
        -: 2665:            {
    10901: 2666:                AliasThis *s = new AliasThis(this->loc,
token.ident);
    10901: 2667:                nextToken();
    10901: 2668:                check(TOKthis);
    10901: 2669:                check(TOKsemicolon);
    10901: 2670:                a = new Dsymbols();
    10901: 2671:                a->push(s);
    10901: 2672:                addComment(s, comment);
    10901: 2673:                return a;
        -: 2674:            }
  2403073: 2675:            break;
        -: 2676:        case TOKtypedef:
    67955: 2677:            tok = token.value;
    67955: 2678:            nextToken();
        -: 2679:            break;
        -: 2680:    }
        -: 2681:
 31249315: 2682:    storage_class = STCundefined;
  8131905: 2683:    while (1)
        -: 2684:    {
 39381220: 2685:        switch (token.value)
        -: 2686:        {
        -: 2687:            case TOKconst:
   273380: 2688:                if (peek(&token)->value == TOKlparen)
   125662: 2689:                    break;              // const as type
constructor
   147718: 2690:                stc = STCconst;         // const as
storage class
   147718: 2691:                goto L1;
        -: 2692:
        -: 2693:            case TOKinvariant:
        -: 2694:            case TOKimmutable:
   486577: 2695:                if (peek(&token)->value == TOKlparen)
   108590: 2696:                    break;
   377987: 2697:                stc = STCimmutable;
   377987: 2698:                goto L1;
        -: 2699:
        -: 2700:            case TOKshared:
    14083: 2701:                if (peek(&token)->value == TOKlparen)
    10796: 2702:                    break;
     3287: 2703:                stc = STCshared;
     3287: 2704:                goto L1;
        -: 2705:
        -: 2706:            case TOKwild:
      896: 2707:                if (peek(&token)->value == TOKlparen)
      832: 2708:                    break;
       64: 2709:                stc = STCwild;
       64: 2710:                goto L1;
        -: 2711:
   366463: 2712:            case TOKstatic:     stc = STCstatic;
goto L1;
    #####: 2713:            case TOKfinal:      stc = STCfinal;
goto L1;
  2870692: 2714:            case TOKauto:       stc = STCauto;
goto L1;
    11678: 2715:            case TOKscope:      stc = STCscope;
goto L1;
    #####: 2716:            case TOKoverride:   stc = STCoverride;
goto L1;
    #####: 2717:            case TOKabstract:   stc = STCabstract;
goto L1;
    #####: 2718:            case TOKsynchronized: stc = STCsynchronized;
goto L1;
    #####: 2719:            case TOKdeprecated: stc = STCdeprecated;
goto L1;
        -: 2720:#if DMDV2
       64: 2721:            case TOKnothrow:    stc = STCnothrow;
goto L1;
      128: 2722:            case TOKpure:       stc = STCpure;
goto L1;
     9157: 2723:            case TOKref:        stc = STCref;
goto L1;
      328: 2724:            case TOKtls:        stc = STCtls;
goto L1;
    18253: 2725:            case TOKgshared:    stc = STCgshared;
goto L1;
  4307516: 2726:            case TOKenum:       stc = STCmanifest;
goto L1;
    #####: 2727:            case TOKat:         stc = parseAttribute();
goto L1;
        -: 2728:#endif
  8113399: 2729:            L1:
  8113399: 2730:                if (storage_class & stc)
    #####: 2731:                    error("redundant storage class
'%s'", token.toChars());
  8113399: 2732:                storage_class = storage_class | stc;
  8113399: 2733:                composeStorageClass(storage_class);
  8113399: 2734:                nextToken();
  8113399: 2735:                continue;
        -: 2736:
        -: 2737:            case TOKextern:
    18570: 2738:                if (peek(&token)->value != TOKlparen)
       64: 2739:                {   stc = STCextern;
       64: 2740:                    goto L1;
        -: 2741:                }
        -: 2742:
    18506: 2743:                link = parseLinkage();
    18506: 2744:                continue;
        -: 2745:
        -: 2746:            default:
        -: 2747:                break;
        -: 2748:        }
        -: 2749:        break;
        -: 2750:    }
        -: 2751:
        -: 2752:    /* Look for auto initializers:
        -: 2753:     *  storage_class identifier = initializer;
        -: 2754:     */
 39311166: 2755:    if (storage_class &&
        -: 2756:        token.value == TOKidentifier &&
        -: 2757:        peek(&token)->value == TOKassign)
        -: 2758:    {
  6208345: 2759:        return parseAutoDeclarations(storage_class,
comment);
        -: 2760:    }
        -: 2761:
 25040970: 2762:    if (token.value == TOKclass)
        -: 2763:    {
    #####: 2764:        AggregateDeclaration *s = (AggregateDeclaration
*)parseAggregate();
    #####: 2765:        s->storage_class |= storage_class;
    #####: 2766:        Dsymbols *a = new Dsymbols();
    #####: 2767:        a->push(s);
    #####: 2768:        addComment(s, comment);
    #####: 2769:        return a;
        -: 2770:    }
        -: 2771:
        -: 2772:    /* Look for return type inference for template
functions.
        -: 2773:     */
        -: 2774:    {
        -: 2775:    Token *tk;
 25040970: 2776:    if (storage_class &&
        -: 2777:        token.value == TOKidentifier &&
        -: 2778:        (tk = peek(&token))->value == TOKlparen &&
        -: 2779:        skipParens(tk, &tk) &&
        -: 2780:        peek(tk)->value == TOKlparen)
        -: 2781:    {
       64: 2782:        ts = NULL;
        -: 2783:    }
        -: 2784:    else
        -: 2785:    {
 25040906: 2786:        ts = parseBasicType();
 25040906: 2787:        ts = parseBasicType2(ts);
        -: 2788:    }
        -: 2789:    }
        -: 2790:
 25117259: 2791:L2:
 25117259: 2792:    tfirst = NULL;
 25117259: 2793:    a = new Dsymbols();
        -: 2794:
   263527: 2795:    while (1)
        -: 2796:    {
 25380786: 2797:        Loc loc = this->loc;
 25380786: 2798:        TemplateParameters *tpl = NULL;
        -: 2799:
 25380786: 2800:        ident = NULL;
 25380786: 2801:        t = parseDeclarator(ts, &ident, &tpl);
 25380786: 2802:        assert(t);
 25380786: 2803:        if (!tfirst)
 25117259: 2804:            tfirst = t;
   263527: 2805:        else if (t != tfirst)
        -: 2806:            error("multiple declarations must have the
same type, not %s and %s",
    #####: 2807:                tfirst->toChars(), t->toChars());
 25380786: 2808:        if (!ident)
    #####: 2809:            error("no identifier for declarator %s",
t->toChars());
        -: 2810:
 27851814: 2811:        if (tok == TOKtypedef || tok == TOKalias)
        -: 2812:        {   Declaration *v;
  2471028: 2813:            Initializer *init = NULL;
        -: 2814:
  2471028: 2815:            if (token.value == TOKassign)
        -: 2816:            {
     1287: 2817:                nextToken();
     1287: 2818:                init = parseInitializer();
        -: 2819:            }
  2471028: 2820:            if (tok == TOKtypedef)
    67955: 2821:                v = new TypedefDeclaration(loc, ident,
t, init);
        -: 2822:            else
  2403073: 2823:            {   if (init)
    #####: 2824:                    error("alias cannot have initializer");
  2403073: 2825:                v = new AliasDeclaration(loc, ident, t);
        -: 2826:            }
  2471028: 2827:            v->storage_class = storage_class;
  2471028: 2828:            if (link == linkage)
  2471028: 2829:                a->push(v);
        -: 2830:            else
        -: 2831:            {
    #####: 2832:                Dsymbols *ax = new Dsymbols();
    #####: 2833:                ax->push(v);
    #####: 2834:                Dsymbol *s = new LinkDeclaration(link, ax);
    #####: 2835:                a->push(s);
        -: 2836:            }
  2471028: 2837:            switch (token.value)
        -: 2838:            {   case TOKsemicolon:
  2471028: 2839:                    nextToken();
  2471028: 2840:                    addComment(v, comment);
  2471028: 2841:                    break;
        -: 2842:
        -: 2843:                case TOKcomma:
    #####: 2844:                    nextToken();
    #####: 2845:                    addComment(v, comment);
    #####: 2846:                    continue;
        -: 2847:
        -: 2848:                default:
    #####: 2849:                    error("semicolon expected to close
%s declaration", Token::toChars(tok));
        -: 2850:                    break;
        -: 2851:            }
        -: 2852:        }
 22909758: 2853:        else if (t->ty == Tfunction)
        -: 2854:        {
 11410434: 2855:            TypeFunction *tf = (TypeFunction *)t;
 11410434: 2856:            Expression *constraint = NULL;
        -: 2857:#if 0
        -: 2858:            if (Parameter::isTPL(tf->parameters))
        -: 2859:            {
        -: 2860:                if (!tpl)
        -: 2861:                    tpl = new TemplateParameters();
        -: 2862:            }
        -: 2863:#endif
        -: 2864:            FuncDeclaration *f =
 11410434: 2865:                new FuncDeclaration(loc, 0, ident,
storage_class, t);
 11410434: 2866:            addComment(f, comment);
 11410434: 2867:            if (tpl)
  1547300: 2868:                constraint = parseConstraint();
 11410434: 2869:            parseContracts(f);
 11410434: 2870:            addComment(f, NULL);
        -: 2871:            Dsymbol *s;
 11410434: 2872:            if (link == linkage)
        -: 2873:            {
 11404180: 2874:                s = f;
        -: 2875:            }
        -: 2876:            else
        -: 2877:            {
     6254: 2878:                Dsymbols *ax = new Dsymbols();
     6254: 2879:                ax->push(f);
     6254: 2880:                s = new LinkDeclaration(link, ax);
        -: 2881:            }
        -: 2882:            /* A template parameter list means it's a
function template
        -: 2883:             */
 11410434: 2884:            if (tpl)
        -: 2885:            {
        -: 2886:                // Wrap a template around the function
declaration
  1547300: 2887:                Dsymbols *decldefs = new Dsymbols();
  1547300: 2888:                decldefs->push(s);
        -: 2889:                TemplateDeclaration *tempdecl =
  1547300: 2890:                    new TemplateDeclaration(loc,
s->ident, tpl, constraint, decldefs, 0);
  1547300: 2891:                s = tempdecl;
        -: 2892:            }
 11410434: 2893:            addComment(s, comment);
 11410434: 2894:            a->push(s);
        -: 2895:        }
        -: 2896:        else
        -: 2897:        {
 11499324: 2898:            Initializer *init = NULL;
 11499324: 2899:            if (token.value == TOKassign)
        -: 2900:            {
  5443159: 2901:                nextToken();
  5443159: 2902:                init = parseInitializer();
        -: 2903:            }
        -: 2904:
 11499324: 2905:            VarDeclaration *v = new VarDeclaration(loc,
t, ident, init);
 11499324: 2906:            v->storage_class = storage_class;
 11499324: 2907:            if (link == linkage)
 11499260: 2908:                a->push(v);
        -: 2909:            else
        -: 2910:            {
       64: 2911:                Dsymbols *ax = new Dsymbols();
       64: 2912:                ax->push(v);
       64: 2913:                Dsymbol *s = new LinkDeclaration(link, ax);
       64: 2914:                a->push(s);
        -: 2915:            }
 11499324: 2916:            switch (token.value)
        -: 2917:            {   case TOKsemicolon:
 11235797: 2918:                    nextToken();
 11235797: 2919:                    addComment(v, comment);
 11235797: 2920:                    break;
        -: 2921:
        -: 2922:                case TOKcomma:
   263527: 2923:                    nextToken();
   263527: 2924:                    addComment(v, comment);
   263527: 2925:                    continue;
        -: 2926:
        -: 2927:                default:
    #####: 2928:                    error("semicolon expected, not
'%s'", token.toChars());
        -: 2929:                    break;
        -: 2930:            }
        -: 2931:        }
        -: 2932:        break;
        -: 2933:    }
 25117259: 2934:    return a;
        -: 2935:}
        -: 2936:
        -: 2937:/*****************************************
        -: 2938: * Parse auto declarations of the form:
        -: 2939: *   storageClass ident = init, ident = init, ... ;
        -: 2940: * and return the array of them.
        -: 2941: * Starts with token on the first ident.
        -: 2942: * Ends with scanner past closing ';'
        -: 2943: */
        -: 2944:
        -: 2945:#if DMDV2
  6232370: 2946:Dsymbols *Parser::parseAutoDeclarations(StorageClass
storageClass, unsigned char *comment)
        -: 2947:{
  6232370: 2948:    Dsymbols *a = new Dsymbols;
        -: 2949:
    89911: 2950:    while (1)
        -: 2951:    {
  6322281: 2952:        Identifier *ident = token.ident;
  6322281: 2953:        nextToken();            // skip over ident
  6322281: 2954:        assert(token.value == TOKassign);
  6322281: 2955:        nextToken();            // skip over '='
  6322281: 2956:        Initializer *init = parseInitializer();
  6322281: 2957:        VarDeclaration *v = new VarDeclaration(loc,
NULL, ident, init);
  6322281: 2958:        v->storage_class = storageClass;
  6322281: 2959:        a->push(v);
  6322281: 2960:        if (token.value == TOKsemicolon)
        -: 2961:        {
  6232370: 2962:            nextToken();
  6232370: 2963:            addComment(v, comment);
        -: 2964:        }
    89911: 2965:        else if (token.value == TOKcomma)
        -: 2966:        {
    89911: 2967:            nextToken();
    89911: 2968:            if (token.value == TOKidentifier &&
        -: 2969:                peek(&token)->value == TOKassign)
        -: 2970:            {
    89911: 2971:                addComment(v, comment);
        -: 2972:                continue;
        -: 2973:            }
        -: 2974:            else
    #####: 2975:                error("Identifier expected following
comma");
        -: 2976:        }
        -: 2977:        else
    #####: 2978:            error("semicolon expected following auto
declaration, not '%s'", token.toChars());
        -: 2979:        break;
        -: 2980:    }
  6232370: 2981:    return a;
        -: 2982:}
        -: 2983:#endif
        -: 2984:
        -: 2985:/*****************************************
        -: 2986: * Parse contracts following function declaration.
        -: 2987: */
        -: 2988:
 12079418: 2989:void Parser::parseContracts(FuncDeclaration *f)
        -: 2990:{
 12079418: 2991:    enum LINK linksave = linkage;
        -: 2992:
        -: 2993:    // The following is irrelevant, as it is overridden
by sc->linkage in
        -: 2994:    // TypeFunction::semantic
 12079418: 2995:    linkage = LINKd;            // nested functions have
D linkage
 12311691: 2996:L1:
 12311691: 2997:    switch (token.value)
        -: 2998:    {
        -: 2999:        case TOKlcurly:
  7059011: 3000:            if (f->frequire || f->fensure)
    #####: 3001:                error("missing body { ... } after in or
out");
  7059011: 3002:            f->fbody = parseStatement(PSsemi);
  7059011: 3003:            f->endloc = endloc;
  7059011: 3004:            break;
        -: 3005:
        -: 3006:        case TOKbody:
   222873: 3007:            nextToken();
   222873: 3008:            f->fbody = parseStatement(PScurly);
   222873: 3009:            f->endloc = endloc;
   222873: 3010:            break;
        -: 3011:
        -: 3012:        case TOKsemicolon:
  4797526: 3013:            if (f->frequire || f->fensure)
    #####: 3014:                error("missing body { ... } after in or
out");
  4797526: 3015:            nextToken();
  4797526: 3016:            break;
        -: 3017:
        -: 3018:#if 0   // Do we want this for function declarations, so
we can do:
        -: 3019:    // int x, y, foo(), z;
        -: 3020:        case TOKcomma:
        -: 3021:            nextToken();
        -: 3022:            continue;
        -: 3023:#endif
        -: 3024:
        -: 3025:#if 0 // Dumped feature
        -: 3026:        case TOKthrow:
        -: 3027:            if (!f->fthrows)
        -: 3028:                f->fthrows = new Array();
        -: 3029:            nextToken();
        -: 3030:            check(TOKlparen);
        -: 3031:            while (1)
        -: 3032:            {
        -: 3033:                Type *tb = parseBasicType();
        -: 3034:                f->fthrows->push(tb);
        -: 3035:                if (token.value == TOKcomma)
        -: 3036:                {   nextToken();
        -: 3037:                    continue;
        -: 3038:                }
        -: 3039:                break;
        -: 3040:            }
        -: 3041:            check(TOKrparen);
        -: 3042:            goto L1;
        -: 3043:#endif
        -: 3044:
        -: 3045:        case TOKin:
   198423: 3046:            nextToken();
   198423: 3047:            if (f->frequire)
    #####: 3048:                error("redundant 'in' statement");
   198423: 3049:            f->frequire = parseStatement(PScurly | PSscope);
   198423: 3050:            goto L1;
        -: 3051:
        -: 3052:        case TOKout:
        -: 3053:            // parse: out (identifier) { statement }
    33850: 3054:            nextToken();
    33850: 3055:            if (token.value != TOKlcurly)
        -: 3056:            {
    27595: 3057:                check(TOKlparen);
    27595: 3058:                if (token.value != TOKidentifier)
    #####: 3059:                    error("(identifier) following 'out'
expected, not %s", token.toChars());
    27595: 3060:                f->outId = token.ident;
    27595: 3061:                nextToken();
    27595: 3062:                check(TOKrparen);
        -: 3063:            }
    33850: 3064:            if (f->fensure)
    #####: 3065:                error("redundant 'out' statement");
    33850: 3066:            f->fensure = parseStatement(PScurly | PSscope);
    33850: 3067:            goto L1;
        -: 3068:
        -: 3069:        default:
        8: 3070:            if (!f->frequire && !f->fensure)
// allow these even with no body
    #####: 3071:                error("semicolon expected following
function declaration");
        -: 3072:            break;
        -: 3073:    }
 12079418: 3074:    linkage = linksave;
 12079418: 3075:}
        -: 3076:
        -: 3077:/*****************************************
        -: 3078: * Parse initializer for variable declaration.
        -: 3079: */
        -: 3080:
 18050480: 3081:Initializer *Parser::parseInitializer()
        -: 3082:{
        -: 3083:    StructInitializer *is;
        -: 3084:    ArrayInitializer *ia;
        -: 3085:    ExpInitializer *ie;
        -: 3086:    Expression *e;
        -: 3087:    Identifier *id;
        -: 3088:    Initializer *value;
        -: 3089:    int comma;
 18050480: 3090:    Loc loc = this->loc;
        -: 3091:    Token *t;
        -: 3092:    int braces;
        -: 3093:    int brackets;
        -: 3094:
 18050480: 3095:    switch (token.value)
        -: 3096:    {
        -: 3097:        case TOKlcurly:
        -: 3098:            /* Scan ahead to see if it is a struct
initializer or
        -: 3099:             * a function literal.
        -: 3100:             * If it contains a ';', it is a function
literal.
        -: 3101:             * Treat { } as a struct initializer.
        -: 3102:             */
   886119: 3103:            braces = 1;
  8277903: 3104:            for (t = peek(&token); 1; t = peek(t))
        -: 3105:            {
  8277903: 3106:                switch (t->value)
        -: 3107:                {
        -: 3108:                    case TOKsemicolon:
        -: 3109:                    case TOKreturn:
       64: 3110:                        goto Lexpression;
        -: 3111:
        -: 3112:                    case TOKlcurly:
       64: 3113:                        braces++;
       64: 3114:                        continue;
        -: 3115:
        -: 3116:                    case TOKrcurly:
   886055: 3117:                        if (--braces == 0)
   886055: 3118:                            break;
    #####: 3119:                        continue;
        -: 3120:
        -: 3121:                    case TOKeof:
    #####: 3122:                        break;
        -: 3123:
        -: 3124:                    default:
  7391720: 3125:                        continue;
        -: 3126:                }
        -: 3127:                break;
        -: 3128:            }
        -: 3129:
   886055: 3130:            is = new StructInitializer(loc);
   886055: 3131:            nextToken();
   886055: 3132:            comma = 0;
  6394219: 3133:            while (1)
        -: 3134:            {
  7280274: 3135:                switch (token.value)
        -: 3136:                {
        -: 3137:                    case TOKidentifier:
   370537: 3138:                        if (comma == 1)
    #####: 3139:                            error("comma expected
separating field initializers");
   370537: 3140:                        t = peek(&token);
   370537: 3141:                        if (t->value == TOKcolon)
        -: 3142:                        {
      561: 3143:                            id = token.ident;
      561: 3144:                            nextToken();
      561: 3145:                            nextToken();        // skip
over ':'
        -: 3146:                        }
        -: 3147:                        else
   369976: 3148:                        {   id = NULL;
        -: 3149:                        }
   370537: 3150:                        value = parseInitializer();
   370537: 3151:                        is->addInit(id, value);
   370537: 3152:                        comma = 1;
   370537: 3153:                        continue;
        -: 3154:
        -: 3155:                    case TOKcomma:
  2754242: 3156:                        nextToken();
  2754242: 3157:                        comma = 2;
  2754242: 3158:                        continue;
        -: 3159:
        -: 3160:                    case TOKrcurly:             // allow
trailing comma's
   886055: 3161:                        nextToken();
   886055: 3162:                        break;
        -: 3163:
        -: 3164:                    case TOKeof:
    #####: 3165:                        error("found EOF instead of
initializer");
    #####: 3166:                        break;
        -: 3167:
        -: 3168:                    default:
  3269440: 3169:                        value = parseInitializer();
  3269440: 3170:                        is->addInit(NULL, value);
  3269440: 3171:                        comma = 1;
  3269440: 3172:                        continue;
        -: 3173:                        //error("found '%s' instead of
field initializer", token.toChars());
        -: 3174:                        //break;
        -: 3175:                }
        -: 3176:                break;
        -: 3177:            }
   886055: 3178:            return is;
        -: 3179:
        -: 3180:        case TOKlbracket:
        -: 3181:            /* Scan ahead to see if it is an array
initializer or
        -: 3182:             * an expression.
        -: 3183:             * If it ends with a ';' ',' or '}', it is
an array initializer.
        -: 3184:             */
  2474010: 3185:            brackets = 1;
 42819179: 3186:            for (t = peek(&token); 1; t = peek(t))
        -: 3187:            {
 42819179: 3188:                switch (t->value)
        -: 3189:                {
        -: 3190:                    case TOKlbracket:
  1753271: 3191:                        brackets++;
  1753271: 3192:                        continue;
        -: 3193:
        -: 3194:                    case TOKrbracket:
  4227281: 3195:                        if (--brackets == 0)
  2474010: 3196:                        {   t = peek(t);
  2474010: 3197:                            if (t->value != TOKsemicolon &&
        -: 3198:                                t->value != TOKcomma &&
        -: 3199:                                t->value != TOKrbracket &&
        -: 3200:                                t->value != TOKrcurly)
    #####: 3201:                                goto Lexpression;
  2474010: 3202:                            break;
        -: 3203:                        }
  1753271: 3204:                        continue;
        -: 3205:
        -: 3206:                    case TOKeof:
    #####: 3207:                        break;
        -: 3208:
        -: 3209:                    default:
 36838627: 3210:                        continue;
        -: 3211:                }
        -: 3212:                break;
        -: 3213:            }
        -: 3214:
  2474010: 3215:            ia = new ArrayInitializer(loc);
  2474010: 3216:            nextToken();
  2474010: 3217:            comma = 0;
 22612877: 3218:            while (1)
        -: 3219:            {
 25086887: 3220:                switch (token.value)
        -: 3221:                {
        -: 3222:                    default:
  9900016: 3223:                        if (comma == 1)
    #####: 3224:                        {   error("comma expected
separating array initializers, not %s", token.toChars());
    #####: 3225:                            nextToken();
    #####: 3226:                            break;
        -: 3227:                        }
  9900016: 3228:                        e = parseAssignExp();
  9900016: 3229:                        if (!e)
    #####: 3230:                            break;
  9900016: 3231:                        if (token.value == TOKcolon)
        -: 3232:                        {
    53271: 3233:                            nextToken();
    53271: 3234:                            value = parseInitializer();
        -: 3235:                        }
        -: 3236:                        else
  9846745: 3237:                        {   value = new
ExpInitializer(e->loc, e);
  9846745: 3238:                            e = NULL;
        -: 3239:                        }
  9900016: 3240:                        ia->addInit(e, value);
  9900016: 3241:                        comma = 1;
  9900016: 3242:                        continue;
        -: 3243:
        -: 3244:                    case TOKlcurly:
        -: 3245:                    case TOKlbracket:
  2590505: 3246:                        if (comma == 1)
    #####: 3247:                            error("comma expected
separating array initializers, not %s", token.toChars());
  2590505: 3248:                        value = parseInitializer();
  2590505: 3249:                        ia->addInit(NULL, value);
  2590505: 3250:                        comma = 1;
  2590505: 3251:                        continue;
        -: 3252:
        -: 3253:                    case TOKcomma:
 10122356: 3254:                        nextToken();
 10122356: 3255:                        comma = 2;
 10122356: 3256:                        continue;
        -: 3257:
        -: 3258:                    case TOKrbracket:           // allow
trailing comma's
  2474010: 3259:                        nextToken();
  2474010: 3260:                        break;
        -: 3261:
        -: 3262:                    case TOKeof:
    #####: 3263:                        error("found '%s' instead of
array initializer", token.toChars());
        -: 3264:                        break;
        -: 3265:                }
        -: 3266:                break;
        -: 3267:            }
  2474010: 3268:            return ia;
        -: 3269:
        -: 3270:        case TOKvoid:
   183356: 3271:            t = peek(&token);
   183356: 3272:            if (t->value == TOKsemicolon || t->value ==
TOKcomma)
        -: 3273:            {
   183292: 3274:                nextToken();
   183292: 3275:                return new VoidInitializer(loc);
        -: 3276:            }
        -: 3277:            goto Lexpression;
        -: 3278:
        -: 3279:        default:
 14507123: 3280:        Lexpression:
 14507123: 3281:            e = parseAssignExp();
 14507123: 3282:            ie = new ExpInitializer(loc, e);
 14507123: 3283:            return ie;
        -: 3284:    }
        -: 3285:}
        -: 3286:
        -: 3287:/*****************************************
        -: 3288: * Parses default argument initializer expression that
is an assign expression,
        -: 3289: * with special handling for __FILE__ and __LINE__.
        -: 3290: */
        -: 3291:
        -: 3292:#if DMDV2
   525662: 3293:Expression *Parser::parseDefaultInitExp()
        -: 3294:{
   525662: 3295:    if (token.value == TOKfile ||
        -: 3296:        token.value == TOKline)
        -: 3297:    {
    48944: 3298:        Token *t = peek(&token);
    48944: 3299:        if (t->value == TOKcomma || t->value == TOKrparen)
        -: 3300:        {   Expression *e;
        -: 3301:
    48816: 3302:            if (token.value == TOKfile)
    24376: 3303:                e = new FileInitExp(loc);
        -: 3304:            else
    24440: 3305:                e = new LineInitExp(loc);
    48816: 3306:            nextToken();
    48816: 3307:            return e;
        -: 3308:        }
        -: 3309:    }
        -: 3310:
   476846: 3311:    Expression *e = parseAssignExp();
   476846: 3312:    return e;
        -: 3313:}
        -: 3314:#endif
        -: 3315:
        -: 3316:/*****************************************
        -: 3317: * Input:
        -: 3318: *      flags   PSxxxx
        -: 3319: */
        -: 3320:
 82913462: 3321:Statement *Parser::parseStatement(int flags)
        -: 3322:{   Statement *s;
        -: 3323:    Token *t;
        -: 3324:    Condition *condition;
        -: 3325:    Statement *ifbody;
        -: 3326:    Statement *elsebody;
        -: 3327:    bool isfinal;
 82913462: 3328:    Loc loc = this->loc;
        -: 3329:
        -: 3330:    //printf("parseStatement()\n");
        -: 3331:
 82913462: 3332:    if (flags & PScurly && token.value != TOKlcurly)
    #####: 3333:        error("statement expected to be { }, not %s",
token.toChars());
        -: 3334:
 82913462: 3335:    switch (token.value)
        -: 3336:    {
        -: 3337:        case TOKidentifier:
        -: 3338:            /* A leading identifier can be a
declaration, label, or expression.
        -: 3339:             * The easiest case to check first is label:
        -: 3340:             */
 22247565: 3341:            t = peek(&token);
 22247565: 3342:            if (t->value == TOKcolon)
        -: 3343:            {   // It's a label
        -: 3344:
   255672: 3345:                Identifier *ident = token.ident;
   255672: 3346:                nextToken();
   255672: 3347:                nextToken();
   255672: 3348:                s = parseStatement(PSsemi);
   255672: 3349:                s = new LabelStatement(loc, ident, s);
   255672: 3350:                break;
        -: 3351:            }
        -: 3352:            // fallthrough to TOKdot
        -: 3353:        case TOKdot:
        -: 3354:        case TOKtypeof:
 22078853: 3355:            if (isDeclaration(&token, 2, TOKreserved, NULL))
  2364602: 3356:                goto Ldeclaration;
        -: 3357:            else
 19714251: 3358:                goto Lexp;
        -: 3359:            break;
        -: 3360:
        -: 3361:        case TOKassert:
        -: 3362:        case TOKthis:
        -: 3363:        case TOKsuper:
        -: 3364:        case TOKint32v:
        -: 3365:        case TOKuns32v:
        -: 3366:        case TOKint64v:
        -: 3367:        case TOKuns64v:
        -: 3368:        case TOKfloat32v:
        -: 3369:        case TOKfloat64v:
        -: 3370:        case TOKfloat80v:
        -: 3371:        case TOKimaginary32v:
        -: 3372:        case TOKimaginary64v:
        -: 3373:        case TOKimaginary80v:
        -: 3374:        case TOKcharv:
        -: 3375:        case TOKwcharv:
        -: 3376:        case TOKdcharv:
        -: 3377:        case TOKnull:
        -: 3378:        case TOKtrue:
        -: 3379:        case TOKfalse:
        -: 3380:        case TOKstring:
        -: 3381:        case TOKlparen:
        -: 3382:        case TOKcast:
        -: 3383:        case TOKmul:
        -: 3384:        case TOKmin:
        -: 3385:        case TOKadd:
        -: 3386:        case TOKtilde:
        -: 3387:        case TOKnot:
        -: 3388:        case TOKplusplus:
        -: 3389:        case TOKminusminus:
        -: 3390:        case TOKnew:
        -: 3391:        case TOKdelete:
        -: 3392:        case TOKdelegate:
        -: 3393:        case TOKfunction:
        -: 3394:        case TOKtypeid:
        -: 3395:        case TOKis:
        -: 3396:        case TOKlbracket:
        -: 3397:#if DMDV2
        -: 3398:        case TOKtraits:
        -: 3399:        case TOKfile:
        -: 3400:        case TOKline:
        -: 3401:#endif
 29750427: 3402:        Lexp:
        -: 3403:        {
 29750427: 3404:            Expression *exp = parseExpression();
 29750427: 3405:            check(TOKsemicolon, "statement");
 29750427: 3406:            s = new ExpStatement(loc, exp);
 29750427: 3407:            break;
        -: 3408:        }
        -: 3409:
        -: 3410:        case TOKstatic:
        -: 3411:        {   // Look ahead to see if it's static assert()
or static if()
        -: 3412:            Token *t;
        -: 3413:
  3127351: 3414:            t = peek(&token);
  3127351: 3415:            if (t->value == TOKassert)
        -: 3416:            {
  1880375: 3417:                nextToken();
  1880375: 3418:                s = new
StaticAssertStatement(parseStaticAssert());
  1880375: 3419:                break;
        -: 3420:            }
  1246976: 3421:            if (t->value == TOKif)
        -: 3422:            {
   859038: 3423:                nextToken();
   859038: 3424:                condition = parseStaticIfCondition();
   859038: 3425:                goto Lcondition;
        -: 3426:            }
   387938: 3427:            if (t->value == TOKstruct || t->value ==
TOKunion || t->value == TOKclass)
        -: 3428:            {
    21475: 3429:                nextToken();
    21475: 3430:                Dsymbols *a = parseBlock();
    21475: 3431:                Dsymbol *d = new
StorageClassDeclaration(STCstatic, a);
    21475: 3432:                s = new DeclarationStatement(loc, d);
    21475: 3433:                if (flags & PSscope)
    #####: 3434:                    s = new ScopeStatement(loc, s);
    21475: 3435:                break;
        -: 3436:            }
   366463: 3437:            goto Ldeclaration;
        -: 3438:        }
        -: 3439:
        -: 3440:        case TOKfinal:
     6129: 3441:            if (peekNext() == TOKswitch)
        -: 3442:            {
     6129: 3443:                nextToken();
     6129: 3444:                isfinal = TRUE;
     6129: 3445:                goto Lswitch;
        -: 3446:            }
        -: 3447:            goto Ldeclaration;
        -: 3448:
        -: 3449:        case BASIC_TYPES:
        -: 3450:        case TOKtypedef:
        -: 3451:        case TOKalias:
        -: 3452:        case TOKconst:
        -: 3453:        case TOKauto:
        -: 3454:        case TOKextern:
        -: 3455:        case TOKinvariant:
        -: 3456:#if DMDV2
        -: 3457:        case TOKimmutable:
        -: 3458:        case TOKshared:
        -: 3459:        case TOKwild:
        -: 3460:        case TOKnothrow:
        -: 3461:        case TOKpure:
        -: 3462:        case TOKtls:
        -: 3463:        case TOKgshared:
        -: 3464:        case TOKat:
        -: 3465:#endif
        -: 3466://      case TOKtypeof:
 10612581: 3467:        Ldeclaration:
        -: 3468:        {   Array *a;
        -: 3469:
 10612581: 3470:            a = parseDeclarations(STCundefined);
 10612581: 3471:            if (a->dim > 1)
        -: 3472:            {
   201778: 3473:                Statements *as = new Statements();
   201778: 3474:                as->reserve(a->dim);
   677506: 3475:                for (int i = 0; i < a->dim; i++)
        -: 3476:                {
   475728: 3477:                    Dsymbol *d = (Dsymbol *)a->data[i];
   475728: 3478:                    s = new DeclarationStatement(loc, d);
   475728: 3479:                    as->push(s);
        -: 3480:                }
   201778: 3481:                s = new
CompoundDeclarationStatement(loc, as);
        -: 3482:            }
 10410803: 3483:            else if (a->dim == 1)
        -: 3484:            {
 10410803: 3485:                Dsymbol *d = (Dsymbol *)a->data[0];
 10410803: 3486:                s = new DeclarationStatement(loc, d);
        -: 3487:            }
        -: 3488:            else
    #####: 3489:                assert(0);
 10612581: 3490:            if (flags & PSscope)
      960: 3491:                s = new ScopeStatement(loc, s);
 10612581: 3492:            break;
        -: 3493:        }
        -: 3494:
        -: 3495:        case TOKstruct:
        -: 3496:        case TOKunion:
        -: 3497:        case TOKclass:
        -: 3498:        case TOKinterface:
        -: 3499:        {   Dsymbol *d;
        -: 3500:
   566284: 3501:            d = parseAggregate();
   566284: 3502:            s = new DeclarationStatement(loc, d);
   566284: 3503:            break;
        -: 3504:        }
        -: 3505:
        -: 3506:        case TOKenum:
        -: 3507:        {   /* Determine if this is a manifest constant
declaration,
        -: 3508:             * or a conventional enum.
        -: 3509:             */
        -: 3510:            Dsymbol *d;
   192293: 3511:            Token *t = peek(&token);
   201642: 3512:            if (t->value == TOKlcurly || t->value ==
TOKcolon)
     9349: 3513:                d = parseEnum();
   182944: 3514:            else if (t->value != TOKidentifier)
    44285: 3515:                goto Ldeclaration;
        -: 3516:            else
        -: 3517:            {
   138659: 3518:                t = peek(t);
   138659: 3519:                if (t->value == TOKlcurly || t->value ==
TOKcolon ||
        -: 3520:                    t->value == TOKsemicolon)
    45727: 3521:                    d = parseEnum();
        -: 3522:                else
        -: 3523:                    goto Ldeclaration;
        -: 3524:            }
    55076: 3525:            s = new DeclarationStatement(loc, d);
    55076: 3526:            break;
        -: 3527:        }
        -: 3528:
        -: 3529:        case TOKmixin:
    55823: 3530:        {   t = peek(&token);
    55823: 3531:            if (t->value == TOKlparen)
        -: 3532:            {   // mixin(string)
    33646: 3533:                nextToken();
    33646: 3534:                check(TOKlparen, "mixin");
    33646: 3535:                Expression *e = parseAssignExp();
    33646: 3536:                check(TOKrparen);
    33646: 3537:                check(TOKsemicolon);
    33646: 3538:                s = new CompileStatement(loc, e);
    33646: 3539:                break;
        -: 3540:            }
    22177: 3541:            Dsymbol *d = parseMixin();
    22177: 3542:            s = new DeclarationStatement(loc, d);
    22177: 3543:            break;
        -: 3544:        }
        -: 3545:
        -: 3546:        case TOKlcurly:
        -: 3547:        {
 16476514: 3548:            nextToken();
        -: 3549:            //if (token.value == TOKsemicolon)
        -: 3550:                //error("use '{ }' for an empty
statement, not a ';'");
 16476514: 3551:            Statements *statements = new Statements();
 87143056: 3552:            while (token.value != TOKrcurly &&
token.value != TOKeof)
        -: 3553:            {
 54190028: 3554:                statements->push(parseStatement(PSsemi |
PScurlyscope));
        -: 3555:            }
 16476514: 3556:            endloc = this->loc;
 16476514: 3557:            s = new CompoundStatement(loc, statements);
 16476514: 3558:            if (flags & (PSscope | PScurlyscope))
  4866296: 3559:                s = new ScopeStatement(loc, s);
 16476514: 3560:            check(TOKrcurly, "compound statement");
 16476514: 3561:            break;
        -: 3562:        }
        -: 3563:
        -: 3564:        case TOKwhile:
        -: 3565:        {   Expression *condition;
        -: 3566:            Statement *body;
        -: 3567:
   349305: 3568:            nextToken();
   349305: 3569:            check(TOKlparen);
   349305: 3570:            condition = parseExpression();
   349305: 3571:            check(TOKrparen);
   349305: 3572:            body = parseStatement(PSscope);
   349305: 3573:            s = new WhileStatement(loc, condition, body);
   349305: 3574:            break;
        -: 3575:        }
        -: 3576:
        -: 3577:        case TOKsemicolon:
   114314: 3578:            if (!(flags & PSsemi))
    #####: 3579:                error("use '{ }' for an empty statement,
not a ';'");
   114314: 3580:            nextToken();
   114314: 3581:            s = new ExpStatement(loc, NULL);
   114314: 3582:            break;
        -: 3583:
        -: 3584:        case TOKdo:
        -: 3585:        {   Statement *body;
        -: 3586:            Expression *condition;
        -: 3587:
    66404: 3588:            nextToken();
    66404: 3589:            body = parseStatement(PSscope);
    66404: 3590:            check(TOKwhile);
    66404: 3591:            check(TOKlparen);
    66404: 3592:            condition = parseExpression();
    66404: 3593:            check(TOKrparen);
    66404: 3594:            s = new DoStatement(loc, body, condition);
    66404: 3595:            break;
        -: 3596:        }
        -: 3597:
        -: 3598:        case TOKfor:
        -: 3599:        {
        -: 3600:            Statement *init;
        -: 3601:            Expression *condition;
        -: 3602:            Expression *increment;
        -: 3603:            Statement *body;
        -: 3604:
   887570: 3605:            nextToken();
   887570: 3606:            check(TOKlparen);
   887570: 3607:            if (token.value == TOKsemicolon)
   312011: 3608:            {   init = NULL;
   312011: 3609:                nextToken();
        -: 3610:            }
        -: 3611:            else
   575559: 3612:            {   init = parseStatement(0);
        -: 3613:            }
   887570: 3614:            if (token.value == TOKsemicolon)
        -: 3615:            {
   140494: 3616:                condition = NULL;
   140494: 3617:                nextToken();
        -: 3618:            }
        -: 3619:            else
        -: 3620:            {
   747076: 3621:                condition = parseExpression();
   747076: 3622:                check(TOKsemicolon, "for condition");
        -: 3623:            }
   887570: 3624:            if (token.value == TOKrparen)
   230003: 3625:            {   increment = NULL;
   230003: 3626:                nextToken();
        -: 3627:            }
        -: 3628:            else
   657567: 3629:            {   increment = parseExpression();
   657567: 3630:                check(TOKrparen);
        -: 3631:            }
   887570: 3632:            body = parseStatement(PSscope);
   887570: 3633:            s = new ForStatement(loc, init, condition,
increment, body);
   887570: 3634:            if (init)
   575559: 3635:                s = new ScopeStatement(loc, s);
   887570: 3636:            break;
        -: 3637:        }
        -: 3638:
        -: 3639:        case TOKforeach:
        -: 3640:        case TOKforeach_reverse:
        -: 3641:        {
  1045217: 3642:            enum TOK op = token.value;
        -: 3643:
  1045217: 3644:            nextToken();
  1045217: 3645:            check(TOKlparen);
        -: 3646:
  1045217: 3647:            Parameters *arguments = new Parameters();
        -: 3648:
   271473: 3649:            while (1)
        -: 3650:            {
  1316690: 3651:                Identifier *ai = NULL;
        -: 3652:                Type *at;
        -: 3653:
  1316690: 3654:                StorageClass storageClass = 0;
  1316690: 3655:                if (token.value == TOKref
        -: 3656:#if D1INOUT
        -: 3657:                        || token.value == TOKinout
        -: 3658:#endif
        -: 3659:                   )
    71511: 3660:                {   storageClass = STCref;
    71511: 3661:                    nextToken();
        -: 3662:                }
  1316690: 3663:                if (token.value == TOKidentifier)
        -: 3664:                {
  1176122: 3665:                    Token *t = peek(&token);
  1176122: 3666:                    if (t->value == TOKcomma || t->value
== TOKsemicolon)
  1092215: 3667:                    {   ai = token.ident;
  1092215: 3668:                        at = NULL;              // infer
argument type
  1092215: 3669:                        nextToken();
  1092215: 3670:                        goto Larg;
        -: 3671:                    }
        -: 3672:                }
   224475: 3673:                at = parseType(&ai);
   224475: 3674:                if (!ai)
    #####: 3675:                    error("no identifier for declarator
%s", at->toChars());
  1316690: 3676:              Larg:
  1316690: 3677:                Parameter *a = new
Parameter(storageClass, at, ai, NULL);
  1316690: 3678:                arguments->push(a);
  1316690: 3679:                if (token.value == TOKcomma)
   271473: 3680:                {   nextToken();
        -: 3681:                    continue;
        -: 3682:                }
        -: 3683:                break;
        -: 3684:            }
  1045217: 3685:            check(TOKsemicolon);
        -: 3686:
  1045217: 3687:            Expression *aggr = parseExpression();
  1254138: 3688:            if (token.value == TOKslice &&
arguments->dim == 1)
        -: 3689:            {
   208921: 3690:                Parameter *a = (Parameter
*)arguments->data[0];
   208921: 3691:                delete arguments;
   208921: 3692:                nextToken();
   208921: 3693:                Expression *upr = parseExpression();
   208921: 3694:                check(TOKrparen);
   208921: 3695:                Statement *body = parseStatement(0);
   208921: 3696:                s = new ForeachRangeStatement(loc, op,
a, aggr, upr, body);
        -: 3697:            }
        -: 3698:            else
        -: 3699:            {
   836296: 3700:                check(TOKrparen);
   836296: 3701:                Statement *body = parseStatement(0);
   836296: 3702:                s = new ForeachStatement(loc, op,
arguments, aggr, body);
        -: 3703:            }
  1045217: 3704:            break;
        -: 3705:        }
        -: 3706:
        -: 3707:        case TOKif:
  5606096: 3708:        {   Parameter *arg = NULL;
        -: 3709:            Expression *condition;
        -: 3710:            Statement *ifbody;
        -: 3711:            Statement *elsebody;
        -: 3712:
  5606096: 3713:            nextToken();
  5606096: 3714:            check(TOKlparen);
        -: 3715:
  5606096: 3716:            if (token.value == TOKauto)
        -: 3717:            {
     6256: 3718:                nextToken();
     6256: 3719:                if (token.value == TOKidentifier)
        -: 3720:                {
     6256: 3721:                    Token *t = peek(&token);
     6256: 3722:                    if (t->value == TOKassign)
        -: 3723:                    {
     6256: 3724:                        arg = new Parameter(0, NULL,
token.ident, NULL);
     6256: 3725:                        nextToken();
     6256: 3726:                        nextToken();
        -: 3727:                    }
        -: 3728:                    else
    #####: 3729:                    {   error("= expected following auto
identifier");
    #####: 3730:                        goto Lerror;
        -: 3731:                    }
        -: 3732:                }
        -: 3733:                else
    #####: 3734:                {   error("identifier expected following
auto");
    #####: 3735:                    goto Lerror;
        -: 3736:                }
        -: 3737:            }
  5599840: 3738:            else if (isDeclaration(&token, 2, TOKassign,
NULL))
        -: 3739:            {
        -: 3740:                Type *at;
        -: 3741:                Identifier *ai;
        -: 3742:
     6126: 3743:                at = parseType(&ai);
     6126: 3744:                check(TOKassign);
     6126: 3745:                arg = new Parameter(0, at, ai, NULL);
        -: 3746:            }
        -: 3747:
        -: 3748:            // Check for " ident;"
  5593714: 3749:            else if (token.value == TOKidentifier)
        -: 3750:            {
  4504198: 3751:                Token *t = peek(&token);
  4504198: 3752:                if (t->value == TOKcomma || t->value ==
TOKsemicolon)
        -: 3753:                {
    #####: 3754:                    arg = new Parameter(0, NULL,
token.ident, NULL);
    #####: 3755:                    nextToken();
    #####: 3756:                    nextToken();
        -: 3757:                    if (1 || !global.params.useDeprecated)
    #####: 3758:                        error("if (v; e) is deprecated,
use if (auto v = e)");
        -: 3759:                }
        -: 3760:            }
        -: 3761:
  5606096: 3762:            condition = parseExpression();
  5606096: 3763:            check(TOKrparen);
  5606096: 3764:            ifbody = parseStatement(PSscope);
  5606096: 3765:            if (token.value == TOKelse)
        -: 3766:            {
  1571282: 3767:                nextToken();
  1571282: 3768:                elsebody = parseStatement(PSscope);
        -: 3769:            }
        -: 3770:            else
  4034814: 3771:                elsebody = NULL;
  5606096: 3772:            s = new IfStatement(loc, arg, condition,
ifbody, elsebody);
  5606096: 3773:            break;
        -: 3774:        }
        -: 3775:
        -: 3776:        case TOKscope:
   379041: 3777:            if (peek(&token)->value != TOKlparen)
      910: 3778:                goto Ldeclaration;              // scope
used as storage class
   378131: 3779:            nextToken();
   378131: 3780:            check(TOKlparen);
   378131: 3781:            if (token.value != TOKidentifier)
    #####: 3782:            {   error("scope identifier expected");
    #####: 3783:                goto Lerror;
        -: 3784:            }
        -: 3785:            else
   378131: 3786:            {   TOK t = TOKon_scope_exit;
   378131: 3787:                Identifier *id = token.ident;
        -: 3788:
   378131: 3789:                if (id == Id::exit)
   164396: 3790:                    t = TOKon_scope_exit;
   213735: 3791:                else if (id == Id::failure)
    40960: 3792:                    t = TOKon_scope_failure;
   172775: 3793:                else if (id == Id::success)
   172775: 3794:                    t = TOKon_scope_success;
        -: 3795:                else
    #####: 3796:                    error("valid scope identifiers are
exit, failure, or success, not %s", id->toChars());
   378131: 3797:                nextToken();
   378131: 3798:                check(TOKrparen);
   378131: 3799:                Statement *st =
parseStatement(PScurlyscope);
   378131: 3800:                s = new OnScopeStatement(loc, t, st);
   378131: 3801:                break;
        -: 3802:            }
        -: 3803:
        -: 3804:        case TOKdebug:
   937932: 3805:            nextToken();
   937932: 3806:            condition = parseDebugCondition();
   937932: 3807:            goto Lcondition;
        -: 3808:
        -: 3809:        case TOKversion:
   392679: 3810:            nextToken();
   392679: 3811:            condition = parseVersionCondition();
        -: 3812:            goto Lcondition;
        -: 3813:
  2189649: 3814:        Lcondition:
  2189649: 3815:            ifbody = parseStatement(0 /*PSsemi*/);
  2189649: 3816:            elsebody = NULL;
  2189649: 3817:            if (token.value == TOKelse)
        -: 3818:            {
   802427: 3819:                nextToken();
   802427: 3820:                elsebody = parseStatement(0 /*PSsemi*/);
        -: 3821:            }
  2189649: 3822:            s = new ConditionalStatement(loc, condition,
ifbody, elsebody);
  2189649: 3823:            break;
        -: 3824:
        -: 3825:        case TOKpragma:
        -: 3826:        {   Identifier *ident;
    16303: 3827:            Expressions *args = NULL;
        -: 3828:            Statement *body;
        -: 3829:
    16303: 3830:            nextToken();
    16303: 3831:            check(TOKlparen);
    16303: 3832:            if (token.value != TOKidentifier)
    #####: 3833:            {   error("pragma(identifier expected");
    #####: 3834:                goto Lerror;
        -: 3835:            }
    16303: 3836:            ident = token.ident;
    16303: 3837:            nextToken();
    16303: 3838:            if (token.value == TOKcomma && peekNext() !=
TOKrparen)
    16303: 3839:                args = parseArguments();        //
pragma(identifier, args...);
        -: 3840:            else
    #####: 3841:                check(TOKrparen);               //
pragma(identifier);
    16303: 3842:            if (token.value == TOKsemicolon)
    16303: 3843:            {   nextToken();
    16303: 3844:                body = NULL;
        -: 3845:            }
        -: 3846:            else
    #####: 3847:                body = parseStatement(PSsemi);
    16303: 3848:            s = new PragmaStatement(loc, ident, args, body);
    16303: 3849:            break;
        -: 3850:        }
        -: 3851:
        -: 3852:        case TOKswitch:
   243002: 3853:            isfinal = FALSE;
        -: 3854:            goto Lswitch;
        -: 3855:
   249131: 3856:        Lswitch:
        -: 3857:        {
   249131: 3858:            nextToken();
   249131: 3859:            check(TOKlparen);
   249131: 3860:            Expression *condition = parseExpression();
   249131: 3861:            check(TOKrparen);
   249131: 3862:            Statement *body = parseStatement(PSscope);
   249131: 3863:            s = new SwitchStatement(loc, condition,
body, isfinal);
   249131: 3864:            break;
        -: 3865:        }
        -: 3866:
        -: 3867:        case TOKcase:
        -: 3868:        {   Expression *exp;
        -: 3869:            Statements *statements;
  2005075: 3870:            Array cases;        // array of Expression's
  2005075: 3871:            Expression *last = NULL;
        -: 3872:
    24320: 3873:            while (1)
        -: 3874:            {
  2029395: 3875:                nextToken();
  2029395: 3876:                exp = parseAssignExp();
  2029395: 3877:                cases.push(exp);
  2029395: 3878:                if (token.value != TOKcomma)
  2005075: 3879:                    break;
        -: 3880:            }
  2005075: 3881:            check(TOKcolon);
        -: 3882:
        -: 3883:#if DMDV2
        -: 3884:            /* case exp: .. case last:
        -: 3885:             */
  2005075: 3886:            if (token.value == TOKslice)
        -: 3887:            {
     3036: 3888:                if (cases.dim > 1)
    #####: 3889:                    error("only one case allowed for
start of case range");
     3036: 3890:                nextToken();
     3036: 3891:                check(TOKcase);
     3036: 3892:                last = parseAssignExp();
     3036: 3893:                check(TOKcolon);
        -: 3894:            }
        -: 3895:#endif
        -: 3896:
  2005075: 3897:            statements = new Statements();
  8726521: 3898:            while (token.value != TOKcase &&
        -: 3899:                   token.value != TOKdefault &&
        -: 3900:                   token.value != TOKeof &&
        -: 3901:                   token.value != TOKrcurly)
        -: 3902:            {
  4716371: 3903:                statements->push(parseStatement(PSsemi |
PScurlyscope));
        -: 3904:            }
  2005075: 3905:            s = new CompoundStatement(loc, statements);
  2005075: 3906:            s = new ScopeStatement(loc, s);
        -: 3907:
        -: 3908:#if DMDV2
  2005075: 3909:            if (last)
        -: 3910:            {
     3036: 3911:                s = new CaseRangeStatement(loc, exp,
last, s);
        -: 3912:            }
        -: 3913:            else
        -: 3914:#endif
        -: 3915:            {
        -: 3916:                // Keep cases in order by building the
case statements backwards
  4028398: 3917:                for (int i = cases.dim; i; i--)
        -: 3918:                {
  2026359: 3919:                    exp = (Expression *)cases.data[i - 1];
  2026359: 3920:                    s = new CaseStatement(loc, exp, s);
        -: 3921:                }
        -: 3922:            }
  2005075: 3923:            break;
        -: 3924:        }
        -: 3925:
        -: 3926:        case TOKdefault:
        -: 3927:        {
        -: 3928:            Statements *statements;
        -: 3929:
   242013: 3930:            nextToken();
   242013: 3931:            check(TOKcolon);
        -: 3932:
   242013: 3933:            statements = new Statements();
   920646: 3934:            while (token.value != TOKcase &&
        -: 3935:                   token.value != TOKdefault &&
        -: 3936:                   token.value != TOKeof &&
        -: 3937:                   token.value != TOKrcurly)
        -: 3938:            {
   436620: 3939:                statements->push(parseStatement(PSsemi |
PScurlyscope));
        -: 3940:            }
   242013: 3941:            s = new CompoundStatement(loc, statements);
   242013: 3942:            s = new ScopeStatement(loc, s);
   242013: 3943:            s = new DefaultStatement(loc, s);
   242013: 3944:            break;
        -: 3945:        }
        -: 3946:
        -: 3947:        case TOKreturn:
        -: 3948:        {   Expression *exp;
        -: 3949:
  7049282: 3950:            nextToken();
  7049282: 3951:            if (token.value == TOKsemicolon)
   291164: 3952:                exp = NULL;
        -: 3953:            else
  6758118: 3954:                exp = parseExpression();
  7049282: 3955:            check(TOKsemicolon, "return statement");
  7049282: 3956:            s = new ReturnStatement(loc, exp);
  7049282: 3957:            break;
        -: 3958:        }
        -: 3959:
        -: 3960:        case TOKbreak:
        -: 3961:        {   Identifier *ident;
        -: 3962:
  1499225: 3963:            nextToken();
  1499225: 3964:            if (token.value == TOKidentifier)
     5227: 3965:            {   ident = token.ident;
     5227: 3966:                nextToken();
        -: 3967:            }
        -: 3968:            else
  1493998: 3969:                ident = NULL;
  1499225: 3970:            check(TOKsemicolon, "break statement");
  1499225: 3971:            s = new BreakStatement(loc, ident);
  1499225: 3972:            break;
        -: 3973:        }
        -: 3974:
        -: 3975:        case TOKcontinue:
        -: 3976:        {   Identifier *ident;
        -: 3977:
   255913: 3978:            nextToken();
   255913: 3979:            if (token.value == TOKidentifier)
     5032: 3980:            {   ident = token.ident;
     5032: 3981:                nextToken();
        -: 3982:            }
        -: 3983:            else
   250881: 3984:                ident = NULL;
   255913: 3985:            check(TOKsemicolon, "continue statement");
   255913: 3986:            s = new ContinueStatement(loc, ident);
   255913: 3987:            break;
        -: 3988:        }
        -: 3989:
        -: 3990:        case TOKgoto:
        -: 3991:        {   Identifier *ident;
        -: 3992:
   930028: 3993:            nextToken();
   930028: 3994:            if (token.value == TOKdefault)
        -: 3995:            {
       99: 3996:                nextToken();
       99: 3997:                s = new GotoDefaultStatement(loc);
        -: 3998:            }
   929929: 3999:            else if (token.value == TOKcase)
        -: 4000:            {
     6147: 4001:                Expression *exp = NULL;
        -: 4002:
     6147: 4003:                nextToken();
     6147: 4004:                if (token.value != TOKsemicolon)
     6146: 4005:                    exp = parseExpression();
     6147: 4006:                s = new GotoCaseStatement(loc, exp);
        -: 4007:            }
        -: 4008:            else
        -: 4009:            {
   923782: 4010:                if (token.value != TOKidentifier)
    #####: 4011:                {   error("Identifier expected following
goto");
    #####: 4012:                    ident = NULL;
        -: 4013:                }
        -: 4014:                else
   923782: 4015:                {   ident = token.ident;
   923782: 4016:                    nextToken();
        -: 4017:                }
   923782: 4018:                s = new GotoStatement(loc, ident);
        -: 4019:            }
   930028: 4020:            check(TOKsemicolon, "goto statement");
   930028: 4021:            break;
        -: 4022:        }
        -: 4023:
        -: 4024:        case TOKsynchronized:
        -: 4025:        {   Expression *exp;
        -: 4026:            Statement *body;
        -: 4027:
      455: 4028:            nextToken();
      455: 4029:            if (token.value == TOKlparen)
        -: 4030:            {
      261: 4031:                nextToken();
      261: 4032:                exp = parseExpression();
      261: 4033:                check(TOKrparen);
        -: 4034:            }
        -: 4035:            else
      194: 4036:                exp = NULL;
      455: 4037:            body = parseStatement(PSscope);
      455: 4038:            s = new SynchronizedStatement(loc, exp, body);
      455: 4039:            break;
        -: 4040:        }
        -: 4041:
        -: 4042:        case TOKwith:
        -: 4043:        {   Expression *exp;
        -: 4044:            Statement *body;
        -: 4045:
     4322: 4046:            nextToken();
     4322: 4047:            check(TOKlparen);
     4322: 4048:            exp = parseExpression();
     4322: 4049:            check(TOKrparen);
     4322: 4050:            body = parseStatement(PSscope);
     4322: 4051:            s = new WithStatement(loc, exp, body);
     4322: 4052:            break;
        -: 4053:        }
        -: 4054:
        -: 4055:        case TOKtry:
        -: 4056:        {   Statement *body;
   107339: 4057:            Array *catches = NULL;
   107339: 4058:            Statement *finalbody = NULL;
        -: 4059:
   107339: 4060:            nextToken();
   107339: 4061:            body = parseStatement(PSscope);
   321663: 4062:            while (token.value == TOKcatch)
        -: 4063:            {
        -: 4064:                Statement *handler;
        -: 4065:                Catch *c;
        -: 4066:                Type *t;
        -: 4067:                Identifier *id;
   106985: 4068:                Loc loc = this->loc;
        -: 4069:
   106985: 4070:                nextToken();
   106985: 4071:                if (token.value == TOKlcurly)
        -: 4072:                {
     3166: 4073:                    t = NULL;
     3166: 4074:                    id = NULL;
        -: 4075:                }
        -: 4076:                else
        -: 4077:                {
   103819: 4078:                    check(TOKlparen);
   103819: 4079:                    id = NULL;
   103819: 4080:                    t = parseType(&id);
   103819: 4081:                    check(TOKrparen);
        -: 4082:                }
   106985: 4083:                handler = parseStatement(0);
   106985: 4084:                c = new Catch(loc, t, id, handler);
   106985: 4085:                if (!catches)
   106983: 4086:                    catches = new Array();
   106985: 4087:                catches->push(c);
        -: 4088:            }
        -: 4089:
   107339: 4090:            if (token.value == TOKfinally)
      426: 4091:            {   nextToken();
      426: 4092:                finalbody = parseStatement(0);
        -: 4093:            }
        -: 4094:
   107339: 4095:            s = body;
   107339: 4096:            if (!catches && !finalbody)
    #####: 4097:                error("catch or finally expected
following try");
        -: 4098:            else
   107339: 4099:            {   if (catches)
   106983: 4100:                    s = new TryCatchStatement(loc, body,
catches);
   107339: 4101:                if (finalbody)
      426: 4102:                    s = new TryFinallyStatement(loc, s,
finalbody);
        -: 4103:            }
   107339: 4104:            break;
        -: 4105:        }
        -: 4106:
        -: 4107:        case TOKthrow:
        -: 4108:        {   Expression *exp;
        -: 4109:
   194132: 4110:            nextToken();
   194132: 4111:            exp = parseExpression();
   194132: 4112:            check(TOKsemicolon, "throw statement");
   194132: 4113:            s = new ThrowStatement(loc, exp);
   194132: 4114:            break;
        -: 4115:        }
        -: 4116:
        -: 4117:        case TOKvolatile:
      256: 4118:            nextToken();
      256: 4119:            s = parseStatement(PSsemi | PScurlyscope);
        -: 4120:#if DMDV2
      256: 4121:            if (!global.params.useDeprecated)
    #####: 4122:                error("volatile statements deprecated;
used synchronized statements instead");
        -: 4123:#endif
      256: 4124:            s = new VolatileStatement(loc, s);
      256: 4125:            break;
        -: 4126:
        -: 4127:        case TOKasm:
        -: 4128:        {   Statements *statements;
        -: 4129:            Identifier *label;
    49075: 4130:            Loc labelloc;
        -: 4131:            Token *toklist;
        -: 4132:            Token **ptoklist;
        -: 4133:
        -: 4134:            // Parse the asm block into a sequence of
AsmStatements,
        -: 4135:            // each AsmStatement is one instruction.
        -: 4136:            // Separate out labels.
        -: 4137:            // Defer parsing of AsmStatements until
semantic processing.
        -: 4138:
    49075: 4139:            nextToken();
    49075: 4140:            check(TOKlcurly);
    49075: 4141:            toklist = NULL;
    49075: 4142:            ptoklist = &toklist;
    49075: 4143:            label = NULL;
    49075: 4144:            statements = new Statements();
  3540410: 4145:            while (1)
        -: 4146:            {
  3589485: 4147:                switch (token.value)
        -: 4148:                {
        -: 4149:                    case TOKidentifier:
  1481957: 4150:                        if (!toklist)
        -: 4151:                        {
        -: 4152:                            // Look ahead to see if it
is a label
   660385: 4153:                            t = peek(&token);
   660385: 4154:                            if (t->value == TOKcolon)
        -: 4155:                            {   // It's a label
    64063: 4156:                                label = token.ident;
    64063: 4157:                                labelloc = this->loc;
    64063: 4158:                                nextToken();
    64063: 4159:                                nextToken();
    64063: 4160:                                continue;
        -: 4161:                            }
        -: 4162:                        }
  1417894: 4163:                        goto Ldefault;
        -: 4164:
        -: 4165:                    case TOKrcurly:
    49075: 4166:                        if (toklist || label)
        -: 4167:                        {
    #####: 4168:                            error("asm statements must
end in ';'");
        -: 4169:                        }
    49075: 4170:                        break;
        -: 4171:
        -: 4172:                    case TOKsemicolon:
   645750: 4173:                        s = NULL;
   645750: 4174:                        if (toklist || label)
        -: 4175:                        {   // Create AsmStatement from
list of tokens we've saved
   633433: 4176:                            s = new
AsmStatement(this->loc, toklist);
   633433: 4177:                            toklist = NULL;
   633433: 4178:                            ptoklist = &toklist;
   633433: 4179:                            if (label)
    64063: 4180:                            {   s = new
LabelStatement(labelloc, label, s);
    64063: 4181:                                label = NULL;
        -: 4182:                            }
   633433: 4183:                            statements->push(s);
        -: 4184:                        }
   645750: 4185:                        nextToken();
   645750: 4186:                        continue;
        -: 4187:
        -: 4188:                    case TOKeof:
        -: 4189:                        /* { */
    #####: 4190:                        error("matching '}' expected,
not end of file");
    #####: 4191:                        break;
        -: 4192:
        -: 4193:                    default:
  2830597: 4194:                    Ldefault:
  2830597: 4195:                        *ptoklist = new Token();
  2830597: 4196:                        memcpy(*ptoklist, &token,
sizeof(Token));
  2830597: 4197:                        ptoklist = &(*ptoklist)->next;
  2830597: 4198:                        *ptoklist = NULL;
        -: 4199:
  2830597: 4200:                        nextToken();
  2830597: 4201:                        continue;
        -: 4202:                }
        -: 4203:                break;
        -: 4204:            }
    49075: 4205:            s = new CompoundStatement(loc, statements);
    49075: 4206:            nextToken();
    49075: 4207:            break;
        -: 4208:        }
        -: 4209:
        -: 4210:        default:
    #####: 4211:            error("found '%s' instead of statement",
token.toChars());
        -: 4212:            goto Lerror;
        -: 4213:
    #####: 4214:        Lerror:
    #####: 4215:            while (token.value != TOKrcurly &&
        -: 4216:                   token.value != TOKsemicolon &&
        -: 4217:                   token.value != TOKeof)
    #####: 4218:                nextToken();
    #####: 4219:            if (token.value == TOKsemicolon)
    #####: 4220:                nextToken();
    #####: 4221:            s = NULL;
        -: 4222:            break;
        -: 4223:    }
        -: 4224:
 82913462: 4225:    return s;
        -: 4226:}
        -: 4227:
135513135: 4228:void Parser::check(enum TOK value)
        -: 4229:{
135513135: 4230:    check(loc, value);
135513135: 4231:}
        -: 4232:
140737638: 4233:void Parser::check(Loc loc, enum TOK value)
        -: 4234:{
140737638: 4235:    if (token.value != value)
    #####: 4236:        error(loc, "found '%s' when expecting '%s'",
token.toChars(), Token::toChars(value));
140737638: 4237:    nextToken();
140737638: 4238:}
        -: 4239:
 74899543: 4240:void Parser::check(enum TOK value, const char *string)
        -: 4241:{
 74899543: 4242:    if (token.value != value)
        -: 4243:        error("found '%s' when expecting '%s' following %s",
    #####: 4244:            token.toChars(), Token::toChars(value), string);
 74899543: 4245:    nextToken();
 74899543: 4246:}
        -: 4247:
  3503234: 4248:void Parser::checkParens(enum TOK value, Expression *e)
        -: 4249:{
  3503234: 4250:    if (precedence[e->op] == PREC_rel && !e->parens)
    #####: 4251:        error(loc, "%s must be parenthesized when next
to operator %s", e->toChars(), Token::toChars(value));
  3503234: 4252:}
        -: 4253:
        -: 4254:/************************************
        -: 4255: * Determine if the scanner is sitting on the start of a
declaration.
        -: 4256: * Input:
        -: 4257: *      needId  0       no identifier
        -: 4258: *              1       identifier optional
        -: 4259: *              2       must have identifier
        -: 4260: * Output:
        -: 4261: *      if *pt is not NULL, it is set to the ending
token, which would be endtok
        -: 4262: */
        -: 4263:
 48035848: 4264:int Parser::isDeclaration(Token *t, int needId, enum TOK
endtok, Token **pt)
        -: 4265:{
        -: 4266:    //printf("isDeclaration(needId = %d)\n", needId);
 48035848: 4267:    int haveId = 0;
        -: 4268:
        -: 4269:#if DMDV2
 48035848: 4270:    if ((t->value == TOKconst ||
        -: 4271:         t->value == TOKinvariant ||
        -: 4272:         t->value == TOKimmutable ||
        -: 4273:         t->value == TOKwild ||
        -: 4274:         t->value == TOKshared) &&
        -: 4275:        peek(t)->value != TOKlparen)
        -: 4276:    {   /* const type
        -: 4277:         * immutable type
        -: 4278:         * shared type
        -: 4279:         * wild type
        -: 4280:         */
    84996: 4281:        t = peek(t);
        -: 4282:    }
        -: 4283:#endif
        -: 4284:
 48035848: 4285:    if (!isBasicType(&t))
        -: 4286:    {
  7215239: 4287:        goto Lisnot;
        -: 4288:    }
 40820609: 4289:    if (!isDeclarator(&t, &haveId, endtok))
 25384322: 4290:        goto Lisnot;
 15436287: 4291:    if ( needId == 1 ||
        -: 4292:        (needId == 0 && !haveId) ||
        -: 4293:        (needId == 2 &&  haveId))
 13204798: 4294:    {   if (pt)
  1493867: 4295:            *pt = t;
        -: 4296:        goto Lis;
        -: 4297:    }
        -: 4298:    else
        -: 4299:        goto Lisnot;
        -: 4300:
 13204798: 4301:Lis:
        -: 4302:    //printf("\tis declaration, t = %s\n", t->toChars());
 13204798: 4303:    return TRUE;
        -: 4304:
 34831050: 4305:Lisnot:
        -: 4306:    //printf("\tis not declaration\n");
 34831050: 4307:    return FALSE;
        -: 4308:}
        -: 4309:
 48240066: 4310:int Parser::isBasicType(Token **pt)
        -: 4311:{
        -: 4312:    // This code parallels parseBasicType()
 48240066: 4313:    Token *t = *pt;
        -: 4314:    Token *t2;
        -: 4315:    int parens;
 48240066: 4316:    int haveId = 0;
        -: 4317:
 48240066: 4318:    switch (t->value)
        -: 4319:    {
        -: 4320:        case BASIC_TYPES:
  2794287: 4321:            t = peek(t);
  2794287: 4322:            break;
        -: 4323:
        -: 4324:        case TOKidentifier:
 37825254: 4325:        L5:
 37825254: 4326:            t = peek(t);
 37825254: 4327:            if (t->value == TOKnot)
        -: 4328:            {
  1201887: 4329:                goto L4;
        -: 4330:            }
 36623367: 4331:            goto L3;
   821055: 4332:            while (1)
        -: 4333:            {
  1270283: 4334:        L2:
  1270283: 4335:                t = peek(t);
 43271021: 4336:        L3:
 43271021: 4337:                if (t->value == TOKdot)
        -: 4338:                {
  5399806: 4339:        Ldot:
  5399806: 4340:                    t = peek(t);
  5399806: 4341:                    if (t->value != TOKidentifier)
        1: 4342:                        goto Lfalse;
  5399805: 4343:                    t = peek(t);
  5399805: 4344:                    if (t->value != TOKnot)
  5377371: 4345:                        goto L3;
  1224321: 4346:        L4:
        -: 4347:                    /* Seen a !
        -: 4348:                     * Look for:
        -: 4349:                     * !( args ), !identifier, etc.
        -: 4350:                     */
  1224321: 4351:                    t = peek(t);
  1224321: 4352:                    switch (t->value)
        -: 4353:                    {   case TOKidentifier:
   256932: 4354:                            goto L5;
        -: 4355:                        case TOKlparen:
   830532: 4356:                            if (!skipParens(t, &t))
     9477: 4357:                                goto Lfalse;
        -: 4358:                            break;
        -: 4359:                        case BASIC_TYPES:
        -: 4360:                        case TOKint32v:
        -: 4361:                        case TOKuns32v:
        -: 4362:                        case TOKint64v:
        -: 4363:                        case TOKuns64v:
        -: 4364:                        case TOKfloat32v:
        -: 4365:                        case TOKfloat64v:
        -: 4366:                        case TOKfloat80v:
        -: 4367:                        case TOKimaginary32v:
        -: 4368:                        case TOKimaginary64v:
        -: 4369:                        case TOKimaginary80v:
        -: 4370:                        case TOKnull:
        -: 4371:                        case TOKtrue:
        -: 4372:                        case TOKfalse:
        -: 4373:                        case TOKcharv:
        -: 4374:                        case TOKwcharv:
        -: 4375:                        case TOKdcharv:
        -: 4376:                        case TOKstring:
        -: 4377:                        case TOKfile:
        -: 4378:                        case TOKline:
   136532: 4379:                            goto L2;
        -: 4380:                        default:
      325: 4381:                            goto Lfalse;
        -: 4382:                    }
        -: 4383:                }
        -: 4384:                else
 37935842: 4385:                    break;
        -: 4386:            }
 37935842: 4387:            break;
        -: 4388:
        -: 4389:        case TOKdot:
    64627: 4390:            goto Ldot;
        -: 4391:
        -: 4392:        case TOKtypeof:
        -: 4393:            /* typeof(exp).identifier...
        -: 4394:             */
   312824: 4395:            t = peek(t);
   312824: 4396:            if (t->value != TOKlparen)
    #####: 4397:                goto Lfalse;
   312824: 4398:            if (!skipParens(t, &t))
      128: 4399:                goto Lfalse;
   312696: 4400:            goto L2;
        -: 4401:
        -: 4402:        case TOKconst:
        -: 4403:        case TOKinvariant:
        -: 4404:        case TOKimmutable:
        -: 4405:        case TOKshared:
        -: 4406:        case TOKwild:
        -: 4407:            // const(type)  or  immutable(type)  or
shared(type)  or  wild(type)
   248519: 4408:            t = peek(t);
   248519: 4409:            if (t->value != TOKlparen)
    #####: 4410:                goto Lfalse;
   248519: 4411:            t = peek(t);
   248519: 4412:            if (!isDeclaration(t, 0, TOKrparen, &t))
        -: 4413:            {
    #####: 4414:                goto Lfalse;
        -: 4415:            }
   248519: 4416:            t = peek(t);
   248519: 4417:            break;
        -: 4418:
        -: 4419:        default:
  7251487: 4420:            goto Lfalse;
        -: 4421:    }
 40978648: 4422:    *pt = t;
        -: 4423:    //printf("is\n");
 40978648: 4424:    return TRUE;
        -: 4425:
  7261418: 4426:Lfalse:
        -: 4427:    //printf("is not\n");
  7261418: 4428:    return FALSE;
        -: 4429:}
        -: 4430:
 46030304: 4431:int Parser::isDeclarator(Token **pt, int *haveId, enum
TOK endtok)
        -: 4432:{   // This code parallels parseDeclarator()
 46030304: 4433:    Token *t = *pt;
        -: 4434:    int parens;
        -: 4435:
        -: 4436:    //printf("Parser::isDeclarator()\n");
        -: 4437:    //t->print();
 46030304: 4438:    if (t->value == TOKassign)
  9091745: 4439:        return FALSE;
        -: 4440:
  3497245: 4441:    while (1)
        -: 4442:    {
 40435804: 4443:        parens = FALSE;
 40435804: 4444:        switch (t->value)
        -: 4445:        {
        -: 4446:            case TOKmul:
        -: 4447:            //case TOKand:
   204489: 4448:                t = peek(t);
   204489: 4449:                continue;
        -: 4450:
        -: 4451:            case TOKlbracket:
  3346866: 4452:                t = peek(t);
  3346866: 4453:                if (t->value == TOKrbracket)
        -: 4454:                {
   588840: 4455:                    t = peek(t);
        -: 4456:                }
  2758026: 4457:                else if (t->value == TOKnew &&
peek(t)->value == TOKrbracket)
        -: 4458:                {
    #####: 4459:                    t = peek(t);
    #####: 4460:                    t = peek(t);
        -: 4461:                }
  2758026: 4462:                else if (isDeclaration(t, 0,
TOKrbracket, &t))
        -: 4463:                {   // It's an associative array declaration
   912797: 4464:                    t = peek(t);
        -: 4465:                }
        -: 4466:                else
        -: 4467:                {
        -: 4468:                    // [ expression ]
        -: 4469:                    // [ expression .. expression ]
  1845229: 4470:                    if (!isExpression(&t))
    #####: 4471:                        return FALSE;
  1845229: 4472:                    if (t->value == TOKslice)
   394575: 4473:                    {   t = peek(t);
   394575: 4474:                        if (!isExpression(&t))
    #####: 4475:                            return FALSE;
        -: 4476:                    }
  1845229: 4477:                    if (t->value != TOKrbracket)
    66938: 4478:                        return FALSE;
  1778291: 4479:                    t = peek(t);
        -: 4480:                }
  3279928: 4481:                continue;
        -: 4482:
        -: 4483:            case TOKidentifier:
  4988229: 4484:                if (*haveId)
    #####: 4485:                    return FALSE;
  4988229: 4486:                *haveId = TRUE;
  4988229: 4487:                t = peek(t);
  4988229: 4488:                break;
        -: 4489:
        -: 4490:            case TOKlparen:
  6931812: 4491:                t = peek(t);
        -: 4492:
  6931812: 4493:                if (t->value == TOKrparen)
   664175: 4494:                    return FALSE;               // () is
not a declarator
        -: 4495:
        -: 4496:                /* Regard ( identifier ) as not a declarator
        -: 4497:                 * BUG: what about ( *identifier ) in
        -: 4498:                 *      f(*p)(x);
        -: 4499:                 * where f is a class instance with
overloaded () ?
        -: 4500:                 * Should we just disallow C-style
function pointer declarations?
        -: 4501:                 */
  6267637: 4502:                if (t->value == TOKidentifier)
  3681092: 4503:                {   Token *t2 = peek(t);
  3681092: 4504:                    if (t2->value == TOKrparen)
  1215917: 4505:                        return FALSE;
        -: 4506:                }
        -: 4507:
        -: 4508:
  5051720: 4509:                if (!isDeclarator(&t, haveId, TOKrparen))
  4999730: 4510:                    return FALSE;
    51990: 4511:                t = peek(t);
    51990: 4512:                parens = TRUE;
    51990: 4513:                break;
        -: 4514:
        -: 4515:            case TOKdelegate:
        -: 4516:            case TOKfunction:
    13276: 4517:                t = peek(t);
    13276: 4518:                if (!isParameters(&t))
      448: 4519:                    return FALSE;
    12828: 4520:                continue;
        -: 4521:        }
 29991351: 4522:        break;
        -: 4523:    }
        -: 4524:
   158743: 4525:    while (1)
        -: 4526:    {
 30150094: 4527:        switch (t->value)
        -: 4528:        {
        -: 4529:#if CARRAYDECL
        -: 4530:            case TOKlbracket:
   167893: 4531:                parens = FALSE;
   167893: 4532:                t = peek(t);
   167893: 4533:                if (t->value == TOKrbracket)
        -: 4534:                {
    21282: 4535:                    t = peek(t);
        -: 4536:                }
   146611: 4537:                else if (isDeclaration(t, 0,
TOKrbracket, &t))
        -: 4538:                {   // It's an associative array declaration
    65976: 4539:                    t = peek(t);
        -: 4540:                }
        -: 4541:                else
        -: 4542:                {
        -: 4543:                    // [ expression ]
    80635: 4544:                    if (!isExpression(&t))
    #####: 4545:                        return FALSE;
    80635: 4546:                    if (t->value != TOKrbracket)
    63972: 4547:                        return FALSE;
    16663: 4548:                    t = peek(t);
        -: 4549:                }
   103921: 4550:                continue;
        -: 4551:#endif
        -: 4552:
        -: 4553:            case TOKlparen:
   143572: 4554:                parens = FALSE;
   143572: 4555:                if (!isParameters(&t))
    88750: 4556:                    return FALSE;
        -: 4557:#if DMDV2
    #####: 4558:                while (1)
        -: 4559:                {
    54822: 4560:                    switch (t->value)
        -: 4561:                    {
        -: 4562:                        case TOKconst:
        -: 4563:                        case TOKinvariant:
        -: 4564:                        case TOKimmutable:
        -: 4565:                        case TOKshared:
        -: 4566:                        case TOKwild:
        -: 4567:                        case TOKpure:
        -: 4568:                        case TOKnothrow:
    #####: 4569:                            t = peek(t);
    #####: 4570:                            continue;
        -: 4571:                        case TOKat:
    #####: 4572:                            t = peek(t);        // skip '@'
    #####: 4573:                            t = peek(t);        // skip
identifier
    #####: 4574:                            continue;
        -: 4575:                        default:
        -: 4576:                            break;
        -: 4577:                    }
        -: 4578:                    break;
        -: 4579:                }
        -: 4580:#endif
    54822: 4581:                continue;
        -: 4582:
        -: 4583:            // Valid tokens that follow a declaration
        -: 4584:            case TOKrparen:
        -: 4585:            case TOKrbracket:
        -: 4586:            case TOKassign:
        -: 4587:            case TOKcomma:
        -: 4588:            case TOKsemicolon:
        -: 4589:            case TOKlcurly:
        -: 4590:            case TOKin:
        -: 4591:                // The !parens is to disallow
unnecessary parentheses
 17717800: 4592:                if (!parens && (endtok == TOKreserved ||
endtok == t->value))
 15603681: 4593:                {   *pt = t;
 15603681: 4594:                    return TRUE;
        -: 4595:                }
  2114119: 4596:                return FALSE;
        -: 4597:
        -: 4598:            default:
 12120829: 4599:                return FALSE;
        -: 4600:        }
        -: 4601:    }
        -: 4602:}
        -: 4603:
        -: 4604:
   156848: 4605:int Parser::isParameters(Token **pt)
        -: 4606:{   // This code parallels parseParameters()
   156848: 4607:    Token *t = *pt;
        -: 4608:
        -: 4609:    //printf("isParameters()\n");
   156848: 4610:    if (t->value != TOKlparen)
      448: 4611:        return FALSE;
        -: 4612:
   156400: 4613:    t = peek(t);
    73412: 4614:    for (;1; t = peek(t))
        -: 4615:    {
   229876: 4616:     L1:
   229876: 4617:        switch (t->value)
        -: 4618:        {
        -: 4619:            case TOKrparen:
    19212: 4620:                break;
        -: 4621:
        -: 4622:            case TOKdotdotdot:
    #####: 4623:                t = peek(t);
    #####: 4624:                break;
        -: 4625:
        -: 4626:#if D1INOUT
        -: 4627:            case TOKinout:
        -: 4628:#endif
        -: 4629:            case TOKin:
        -: 4630:            case TOKout:
        -: 4631:            case TOKref:
        -: 4632:            case TOKlazy:
        -: 4633:            case TOKfinal:
        -: 4634:            case TOKauto:
     6318: 4635:                continue;
        -: 4636:
        -: 4637:            case TOKconst:
        -: 4638:            case TOKinvariant:
        -: 4639:            case TOKimmutable:
        -: 4640:            case TOKshared:
        -: 4641:            case TOKwild:
      128: 4642:                t = peek(t);
      128: 4643:                if (t->value == TOKlparen)
        -: 4644:                {
       64: 4645:                    t = peek(t);
       64: 4646:                    if (!isDeclaration(t, 0, TOKrparen, &t))
    #####: 4647:                        return FALSE;
       64: 4648:                    t = peek(t);        // skip past
closing ')'
       64: 4649:                    goto L2;
        -: 4650:                }
       64: 4651:                goto L1;
        -: 4652:
        -: 4653:#if 0
        -: 4654:            case TOKstatic:
        -: 4655:                continue;
        -: 4656:            case TOKauto:
        -: 4657:            case TOKalias:
        -: 4658:                t = peek(t);
        -: 4659:                if (t->value == TOKidentifier)
        -: 4660:                    t = peek(t);
        -: 4661:                if (t->value == TOKassign)
        -: 4662:                {   t = peek(t);
        -: 4663:                    if (!isExpression(&t))
        -: 4664:                        return FALSE;
        -: 4665:                }
        -: 4666:                goto L3;
        -: 4667:#endif
        -: 4668:
        -: 4669:            default:
   204218: 4670:            {   if (!isBasicType(&t))
    46179: 4671:                    return FALSE;
   158103: 4672:            L2:
   158103: 4673:                int tmp = FALSE;
   158103: 4674:                if (t->value != TOKdotdotdot &&
        -: 4675:                    !isDeclarator(&t, &tmp, TOKreserved))
    42571: 4676:                    return FALSE;
   115532: 4677:                if (t->value == TOKassign)
        1: 4678:                {   t = peek(t);
        1: 4679:                    if (!isExpression(&t))
    #####: 4680:                        return FALSE;
        -: 4681:                }
   115532: 4682:                if (t->value == TOKdotdotdot)
        -: 4683:                {
      128: 4684:                    t = peek(t);
      128: 4685:                    break;
        -: 4686:                }
        -: 4687:            }
   115404: 4688:            L3:
   115404: 4689:                if (t->value == TOKcomma)
        -: 4690:                {
    67094: 4691:                    continue;
        -: 4692:                }
        -: 4693:                break;
        -: 4694:        }
        -: 4695:        break;
        -: 4696:    }
    67650: 4697:    if (t->value != TOKrparen)
    #####: 4698:        return FALSE;
    67650: 4699:    t = peek(t);
    67650: 4700:    *pt = t;
    67650: 4701:    return TRUE;
        -: 4702:}
        -: 4703:
  2320440: 4704:int Parser::isExpression(Token **pt)
        -: 4705:{
        -: 4706:    // This is supposed to determine if something is an
expression.
        -: 4707:    // What it actually does is scan until a closing
right bracket
        -: 4708:    // is found.
        -: 4709:
  2320440: 4710:    Token *t = *pt;
  2320440: 4711:    int brnest = 0;
  2320440: 4712:    int panest = 0;
  2320440: 4713:    int curlynest = 0;
        -: 4714:
  3414975: 4715:    for (;; t = peek(t))
        -: 4716:    {
  5735415: 4717:        switch (t->value)
        -: 4718:        {
        -: 4719:            case TOKlbracket:
     3108: 4720:                brnest++;
     3108: 4721:                continue;
        -: 4722:
        -: 4723:            case TOKrbracket:
  1798062: 4724:                if (--brnest >= 0)
     3108: 4725:                    continue;
  1794954: 4726:                break;
        -: 4727:
        -: 4728:            case TOKlparen:
    20713: 4729:                panest++;
    20713: 4730:                continue;
        -: 4731:
        -: 4732:            case TOKcomma:
    68490: 4733:                if (brnest || panest)
     1552: 4734:                    continue;
    66938: 4735:                break;
        -: 4736:
        -: 4737:            case TOKrparen:
    20714: 4738:                if (--panest >= 0)
    20713: 4739:                    continue;
        1: 4740:                break;
        -: 4741:
        -: 4742:            case TOKlcurly:
    #####: 4743:                curlynest++;
    #####: 4744:                continue;
        -: 4745:
        -: 4746:            case TOKrcurly:
    #####: 4747:                if (--curlynest >= 0)
    #####: 4748:                    continue;
    #####: 4749:                return FALSE;
        -: 4750:
        -: 4751:            case TOKslice:
   458547: 4752:                if (brnest)
    #####: 4753:                    continue;
   458547: 4754:                break;
        -: 4755:
        -: 4756:            case TOKsemicolon:
    #####: 4757:                if (curlynest)
    #####: 4758:                    continue;
    #####: 4759:                return FALSE;
        -: 4760:
        -: 4761:            case TOKeof:
    #####: 4762:                return FALSE;
        -: 4763:
        -: 4764:            default:
  3365781: 4765:                continue;
        -: 4766:        }
        -: 4767:        break;
        -: 4768:    }
        -: 4769:
  2320440: 4770:    *pt = t;
  2320440: 4771:    return TRUE;
        -: 4772:}
        -: 4773:
        -: 4774:/**********************************************
        -: 4775: * Skip over
        -: 4776: *      instance foo.bar(parameters...)
        -: 4777: * Output:
        -: 4778: *      if (pt), *pt is set to the token following the
closing )
        -: 4779: * Returns:
        -: 4780: *      1       it's valid instance syntax
        -: 4781: *      0       invalid instance syntax
        -: 4782: */
        -: 4783:
    #####: 4784:int Parser::isTemplateInstance(Token *t, Token **pt)
        -: 4785:{
    #####: 4786:    t = peek(t);
    #####: 4787:    if (t->value != TOKdot)
        -: 4788:    {
    #####: 4789:        if (t->value != TOKidentifier)
    #####: 4790:            goto Lfalse;
    #####: 4791:        t = peek(t);
        -: 4792:    }
    #####: 4793:    while (t->value == TOKdot)
        -: 4794:    {
    #####: 4795:        t = peek(t);
    #####: 4796:        if (t->value != TOKidentifier)
    #####: 4797:            goto Lfalse;
    #####: 4798:        t = peek(t);
        -: 4799:    }
    #####: 4800:    if (t->value != TOKlparen)
    #####: 4801:        goto Lfalse;
        -: 4802:
        -: 4803:    // Skip over the template arguments
    #####: 4804:    while (1)
        -: 4805:    {
    #####: 4806:        while (1)
        -: 4807:        {
    #####: 4808:            t = peek(t);
    #####: 4809:            switch (t->value)
        -: 4810:            {
        -: 4811:                case TOKlparen:
    #####: 4812:                    if (!skipParens(t, &t))
    #####: 4813:                        goto Lfalse;
    #####: 4814:                    continue;
        -: 4815:                case TOKrparen:
    #####: 4816:                    break;
        -: 4817:                case TOKcomma:
    #####: 4818:                    break;
        -: 4819:                case TOKeof:
        -: 4820:                case TOKsemicolon:
    #####: 4821:                    goto Lfalse;
        -: 4822:                default:
    #####: 4823:                    continue;
        -: 4824:            }
        -: 4825:            break;
        -: 4826:        }
        -: 4827:
    #####: 4828:        if (t->value != TOKcomma)
    #####: 4829:            break;
        -: 4830:    }
    #####: 4831:    if (t->value != TOKrparen)
    #####: 4832:        goto Lfalse;
    #####: 4833:    t = peek(t);
    #####: 4834:    if (pt)
    #####: 4835:        *pt = t;
    #####: 4836:    return 1;
        -: 4837:
    #####: 4838:Lfalse:
    #####: 4839:    return 0;
        -: 4840:}
        -: 4841:
        -: 4842:/*******************************************
        -: 4843: * Skip parens, brackets.
        -: 4844: * Input:
        -: 4845: *      t is on opening (
        -: 4846: * Output:
        -: 4847: *      *pt is set to closing token, which is ')' on success
        -: 4848: * Returns:
        -: 4849: *      !=0     successful
        -: 4850: *      0       some parsing error
        -: 4851: */
        -: 4852:
  1219709: 4853:int Parser::skipParens(Token *t, Token **pt)
        -: 4854:{
  1219709: 4855:    int parens = 0;
        -: 4856:
  5939145: 4857:    while (1)
        -: 4858:    {
  7158854: 4859:        switch (t->value)
        -: 4860:        {
        -: 4861:            case TOKlparen:
  1373481: 4862:                parens++;
  1373481: 4863:                break;
        -: 4864:
        -: 4865:            case TOKrparen:
  1363876: 4866:                parens--;
  1363876: 4867:                if (parens < 0)
    #####: 4868:                    goto Lfalse;
  1363876: 4869:                if (parens == 0)
  1210104: 4870:                    goto Ldone;
   153772: 4871:                break;
        -: 4872:
        -: 4873:            case TOKeof:
        -: 4874:            case TOKsemicolon:
     9605: 4875:                goto Lfalse;
        -: 4876:
        -: 4877:             default:
        -: 4878:                break;
        -: 4879:        }
  5939145: 4880:        t = peek(t);
        -: 4881:    }
        -: 4882:
  1210104: 4883:  Ldone:
  1210104: 4884:    if (*pt)
  1210104: 4885:        *pt = t;
  1210104: 4886:    return 1;
        -: 4887:
     9605: 4888:  Lfalse:
     9605: 4889:    return 0;
        -: 4890:}
        -: 4891:
        -: 4892:/********************************* Expression Parser
***************************/
        -: 4893:
187736165: 4894:Expression *Parser::parsePrimaryExp()
        -: 4895:{   Expression *e;
        -: 4896:    Type *t;
        -: 4897:    Identifier *id;
        -: 4898:    enum TOK save;
187736165: 4899:    Loc loc = this->loc;
        -: 4900:
        -: 4901:    //printf("parsePrimaryExp(): loc = %d\n", loc.linnum);
187736165: 4902:    switch (token.value)
        -: 4903:    {
        -: 4904:        case TOKidentifier:
102771702: 4905:            id = token.ident;
102771702: 4906:            nextToken();
102771702: 4907:            if (token.value == TOKnot && (save =
peekNext()) != TOKis && save != TOKin)
        -: 4908:            {   // identifier!(template-argument-list)
        -: 4909:                TemplateInstance *tempinst;
        -: 4910:
  6658118: 4911:                tempinst = new TemplateInstance(loc, id);
  6658118: 4912:                nextToken();
  6658118: 4913:                if (token.value == TOKlparen)
        -: 4914:                    // ident!(template_arguments)
  4149482: 4915:                    tempinst->tiargs =
parseTemplateArgumentList();
        -: 4916:                else
        -: 4917:                    // ident!template_argument
  2508636: 4918:                    tempinst->tiargs =
parseTemplateArgument();
  6658118: 4919:                e = new ScopeExp(loc, tempinst);
        -: 4920:            }
        -: 4921:            else
 96113584: 4922:                e = new IdentifierExp(loc, id);
102771702: 4923:            break;
        -: 4924:
        -: 4925:        case TOKdollar:
   926372: 4926:            if (!inBrackets)
    #####: 4927:                error("'$' is valid only inside [] of
index or slice");
   926372: 4928:            e = new DollarExp(loc);
   926372: 4929:            nextToken();
   926372: 4930:            break;
        -: 4931:
        -: 4932:        case TOKdot:
        -: 4933:            // Signal global scope '.' operator with ""
identifier
   204718: 4934:            e = new IdentifierExp(loc, Id::empty);
   204718: 4935:            break;
        -: 4936:
        -: 4937:        case TOKthis:
   714221: 4938:            e = new ThisExp(loc);
   714221: 4939:            nextToken();
   714221: 4940:            break;
        -: 4941:
        -: 4942:        case TOKsuper:
    93095: 4943:            e = new SuperExp(loc);
    93095: 4944:            nextToken();
    93095: 4945:            break;
        -: 4946:
        -: 4947:        case TOKint32v:
 38986650: 4948:            e = new IntegerExp(loc, token.int32value,
Type::tint32);
 38986650: 4949:            nextToken();
 38986650: 4950:            break;
        -: 4951:
        -: 4952:        case TOKuns32v:
   545274: 4953:            e = new IntegerExp(loc, token.uns32value,
Type::tuns32);
   545274: 4954:            nextToken();
   545274: 4955:            break;
        -: 4956:
        -: 4957:        case TOKint64v:
   315804: 4958:            e = new IntegerExp(loc, token.int64value,
Type::tint64);
   315804: 4959:            nextToken();
   315804: 4960:            break;
        -: 4961:
        -: 4962:        case TOKuns64v:
   156965: 4963:            e = new IntegerExp(loc, token.uns64value,
Type::tuns64);
   156965: 4964:            nextToken();
   156965: 4965:            break;
        -: 4966:
        -: 4967:        case TOKfloat32v:
    73076: 4968:            e = new RealExp(loc, token.float80value,
Type::tfloat32);
    73076: 4969:            nextToken();
    73076: 4970:            break;
        -: 4971:
        -: 4972:        case TOKfloat64v:
  1380392: 4973:            e = new RealExp(loc, token.float80value,
Type::tfloat64);
  1380392: 4974:            nextToken();
  1380392: 4975:            break;
        -: 4976:
        -: 4977:        case TOKfloat80v:
   394612: 4978:            e = new RealExp(loc, token.float80value,
Type::tfloat80);
   394612: 4979:            nextToken();
   394612: 4980:            break;
        -: 4981:
        -: 4982:        case TOKimaginary32v:
     3287: 4983:            e = new RealExp(loc, token.float80value,
Type::timaginary32);
     3287: 4984:            nextToken();
     3287: 4985:            break;
        -: 4986:
        -: 4987:        case TOKimaginary64v:
   154805: 4988:            e = new RealExp(loc, token.float80value,
Type::timaginary64);
   154805: 4989:            nextToken();
   154805: 4990:            break;
        -: 4991:
        -: 4992:        case TOKimaginary80v:
    21602: 4993:            e = new RealExp(loc, token.float80value,
Type::timaginary80);
    21602: 4994:            nextToken();
    21602: 4995:            break;
        -: 4996:
        -: 4997:        case TOKnull:
   651198: 4998:            e = new NullExp(loc);
   651198: 4999:            nextToken();
   651198: 5000:            break;
        -: 5001:
        -: 5002:#if DMDV2
        -: 5003:        case TOKfile:
   175799: 5004:        {   const char *s = loc.filename ? loc.filename
: mod->ident->toChars();
   175799: 5005:            e = new StringExp(loc, (char *)s, strlen(s), 0);
   175799: 5006:            nextToken();
   175799: 5007:            break;
        -: 5008:        }
        -: 5009:
        -: 5010:        case TOKline:
   214044: 5011:            e = new IntegerExp(loc, loc.linnum,
Type::tint32);
   214044: 5012:            nextToken();
   214044: 5013:            break;
        -: 5014:#endif
        -: 5015:
        -: 5016:        case TOKtrue:
   732539: 5017:            e = new IntegerExp(loc, 1, Type::tbool);
   732539: 5018:            nextToken();
   732539: 5019:            break;
        -: 5020:
        -: 5021:        case TOKfalse:
   834110: 5022:            e = new IntegerExp(loc, 0, Type::tbool);
   834110: 5023:            nextToken();
   834110: 5024:            break;
        -: 5025:
        -: 5026:        case TOKcharv:
  3170970: 5027:            e = new IntegerExp(loc, token.uns32value,
Type::tchar);
  3170970: 5028:            nextToken();
  3170970: 5029:            break;
        -: 5030:
        -: 5031:        case TOKwcharv:
   136527: 5032:            e = new IntegerExp(loc, token.uns32value,
Type::twchar);
   136527: 5033:            nextToken();
   136527: 5034:            break;
        -: 5035:
        -: 5036:        case TOKdcharv:
    44445: 5037:            e = new IntegerExp(loc, token.uns32value,
Type::tdchar);
    44445: 5038:            nextToken();
    44445: 5039:            break;
        -: 5040:
        -: 5041:        case TOKstring:
        -: 5042:        {   unsigned char *s;
        -: 5043:            unsigned len;
        -: 5044:            unsigned char postfix;
        -: 5045:
        -: 5046:            // cat adjacent strings
 16432293: 5047:            s = token.ustring;
 16432293: 5048:            len = token.len;
 16432293: 5049:            postfix = token.postfix;
   105324: 5050:            while (1)
        -: 5051:            {
 16537617: 5052:                nextToken();
 16537617: 5053:                if (token.value == TOKstring)
        -: 5054:                {   unsigned len1;
        -: 5055:                    unsigned len2;
        -: 5056:                    unsigned char *s2;
        -: 5057:
   105324: 5058:                    if (token.postfix)
    #####: 5059:                    {   if (token.postfix != postfix)
    #####: 5060:                            error("mismatched string
literal postfixes '%c' and '%c'", postfix, token.postfix);
    #####: 5061:                        postfix = token.postfix;
        -: 5062:                    }
        -: 5063:
   105324: 5064:                    len1 = len;
   105324: 5065:                    len2 = token.len;
   105324: 5066:                    len = len1 + len2;
   105324: 5067:                    s2 = (unsigned char
*)mem.malloc((len + 1) * sizeof(unsigned char));
   105324: 5068:                    memcpy(s2, s, len1 * sizeof(unsigned
char));
   105324: 5069:                    memcpy(s2 + len1, token.ustring,
(len2 + 1) * sizeof(unsigned char));
   105324: 5070:                    s = s2;
        -: 5071:                }
        -: 5072:                else
 16432293: 5073:                    break;
        -: 5074:            }
 16432293: 5075:            e = new StringExp(loc, s, len, postfix);
 16432293: 5076:            break;
        -: 5077:        }
        -: 5078:
      128: 5079:        case BASIC_TYPES_X(t):
  1800201: 5080:            nextToken();
  1800201: 5081:        L1:
  1800201: 5082:            check(TOKdot, t->toChars());
  1800201: 5083:            if (token.value != TOKidentifier)
    #####: 5084:            {   error("found '%s' when expecting
identifier following '%s.'", token.toChars(), t->toChars());
    #####: 5085:                goto Lerr;
        -: 5086:            }
  1800201: 5087:            e = typeDotIdExp(loc, t, token.ident);
  1800201: 5088:            nextToken();
  1800201: 5089:            break;
        -: 5090:
        -: 5091:        case TOKtypeof:
        -: 5092:        {
   157429: 5093:            t = parseTypeof();
   157429: 5094:            e = new TypeExp(loc, t);
   157429: 5095:            break;
        -: 5096:        }
        -: 5097:
        -: 5098:        case TOKtypeid:
        -: 5099:        {
   189717: 5100:            nextToken();
   189717: 5101:            check(TOKlparen, "typeid");
        -: 5102:            Object *o;
   189717: 5103:            if (isDeclaration(&token, 0, TOKreserved, NULL))
        -: 5104:            {   // argument is a type
   189589: 5105:                o = parseType();
        -: 5106:            }
        -: 5107:            else
        -: 5108:            {   // argument is an expression
      128: 5109:                o = parseAssignExp();
        -: 5110:            }
   189717: 5111:            check(TOKrparen);
   189717: 5112:            e = new TypeidExp(loc, o);
   189717: 5113:            break;
        -: 5114:        }
        -: 5115:
        -: 5116:#if DMDV2
        -: 5117:        case TOKtraits:
        -: 5118:        {   /* __traits(identifier, args...)
        -: 5119:             */
        -: 5120:            Identifier *ident;
   206038: 5121:            Objects *args = NULL;
        -: 5122:
   206038: 5123:            nextToken();
   206038: 5124:            check(TOKlparen);
   206038: 5125:            if (token.value != TOKidentifier)
    #####: 5126:            {   error("__traits(identifier, args...)
expected");
    #####: 5127:                goto Lerr;
        -: 5128:            }
   206038: 5129:            ident = token.ident;
   206038: 5130:            nextToken();
   206038: 5131:            if (token.value == TOKcomma)
   205334: 5132:                args = parseTemplateArgumentList2();
// __traits(identifier, args...)
        -: 5133:            else
      704: 5134:                check(TOKrparen);               //
__traits(identifier)
        -: 5135:
   206038: 5136:            e = new TraitsExp(loc, ident, args);
   206038: 5137:            break;
        -: 5138:        }
        -: 5139:#endif
        -: 5140:
        -: 5141:        case TOKis:
        -: 5142:        {   Type *targ;
  1771747: 5143:            Identifier *ident = NULL;
  1771747: 5144:            Type *tspec = NULL;
  1771747: 5145:            enum TOK tok = TOKreserved;
  1771747: 5146:            enum TOK tok2 = TOKreserved;
  1771747: 5147:            TemplateParameters *tpl = NULL;
  1771747: 5148:            Loc loc = this->loc;
        -: 5149:
  1771747: 5150:            nextToken();
  1771747: 5151:            if (token.value == TOKlparen)
        -: 5152:            {
  1771747: 5153:                nextToken();
  1771747: 5154:                targ = parseType(&ident);
  1771747: 5155:                if (token.value == TOKcolon ||
token.value == TOKequal)
        -: 5156:                {
  1401922: 5157:                    tok = token.value;
  1401922: 5158:                    nextToken();
  1401922: 5159:                    if (tok == TOKequal &&
        -: 5160:                        (token.value == TOKtypedef ||
        -: 5161:                         token.value == TOKstruct ||
        -: 5162:                         token.value == TOKunion ||
        -: 5163:                         token.value == TOKclass ||
        -: 5164:                         token.value == TOKsuper ||
        -: 5165:                         token.value == TOKenum ||
        -: 5166:                         token.value == TOKinterface ||
        -: 5167:#if DMDV2
        -: 5168:                         token.value == TOKconst &&
peek(&token)->value == TOKrparen ||
        -: 5169:                         token.value == TOKinvariant &&
peek(&token)->value == TOKrparen ||
        -: 5170:                         token.value == TOKimmutable &&
peek(&token)->value == TOKrparen ||
        -: 5171:                         token.value == TOKshared &&
peek(&token)->value == TOKrparen ||
        -: 5172:                         token.value == TOKwild &&
peek(&token)->value == TOKrparen ||
        -: 5173:#endif
        -: 5174:                         token.value == TOKfunction ||
        -: 5175:                         token.value == TOKdelegate ||
        -: 5176:                         token.value == TOKreturn))
        -: 5177:                    {
   339265: 5178:                        tok2 = token.value;
   339265: 5179:                        nextToken();
        -: 5180:                    }
        -: 5181:                    else
        -: 5182:                    {
  1062657: 5183:                        tspec = parseType();
        -: 5184:                    }
        -: 5185:                }
  1858535: 5186:                if (ident && tspec)
        -: 5187:                {
    86788: 5188:                    if (token.value == TOKcomma)
    27727: 5189:                        tpl = parseTemplateParameterList(1);
        -: 5190:                    else
    59061: 5191:                    {   tpl = new TemplateParameters();
    59061: 5192:                        check(TOKrparen);
        -: 5193:                    }
    86788: 5194:                    TemplateParameter *tp = new
TemplateTypeParameter(loc, ident, NULL, NULL);
    86788: 5195:                    tpl->insert(0, tp);
        -: 5196:                }
        -: 5197:                else
  1684959: 5198:                    check(TOKrparen);
        -: 5199:            }
        -: 5200:            else
    #####: 5201:            {   error("(type identifier :
specialization) expected following is");
    #####: 5202:                goto Lerr;
        -: 5203:            }
  1771747: 5204:            e = new IsExp(loc, targ, ident, tok, tspec,
tok2, tpl);
  1771747: 5205:            break;
        -: 5206:        }
        -: 5207:
        -: 5208:        case TOKassert:
  9069692: 5209:        {   Expression *msg = NULL;
        -: 5210:
  9069692: 5211:            nextToken();
  9069692: 5212:            check(TOKlparen, "assert");
  9069692: 5213:            e = parseAssignExp();
  9069692: 5214:            if (token.value == TOKcomma)
   344999: 5215:            {   nextToken();
   344999: 5216:                msg = parseAssignExp();
        -: 5217:            }
  9069692: 5218:            check(TOKrparen);
  9069692: 5219:            e = new AssertExp(loc, e, msg);
  9069692: 5220:            break;
        -: 5221:        }
        -: 5222:
        -: 5223:        case TOKmixin:
        -: 5224:        {
    30931: 5225:            nextToken();
    30931: 5226:            check(TOKlparen, "mixin");
    30931: 5227:            e = parseAssignExp();
    30931: 5228:            check(TOKrparen);
    30931: 5229:            e = new CompileExp(loc, e);
    30931: 5230:            break;
        -: 5231:        }
        -: 5232:
        -: 5233:        case TOKimport:
        -: 5234:        {
        1: 5235:            nextToken();
        1: 5236:            check(TOKlparen, "import");
        1: 5237:            e = parseAssignExp();
        1: 5238:            check(TOKrparen);
        1: 5239:            e = new FileExp(loc, e);
        1: 5240:            break;
        -: 5241:        }
        -: 5242:
        -: 5243:        case TOKlparen:
  4309142: 5244:            if (peekPastParen(&token)->value == TOKlcurly)
        -: 5245:            {   // (arguments) { statements... }
    70846: 5246:                save = TOKdelegate;
    70846: 5247:                goto case_delegate;
        -: 5248:            }
        -: 5249:            // ( expression )
  4238296: 5250:            nextToken();
  4238296: 5251:            e = parseExpression();
  4238296: 5252:            e->parens = 1;
  4238296: 5253:            check(loc, TOKrparen);
  4238296: 5254:            break;
        -: 5255:
        -: 5256:        case TOKlbracket:
        -: 5257:        {   /* Parse array literals and associative
array literals:
        -: 5258:             *  [ value, value, value ... ]
        -: 5259:             *  [ key:value, key:value, key:value ... ]
        -: 5260:             */
   986207: 5261:            Expressions *values = new Expressions();
   986207: 5262:            Expressions *keys = NULL;
        -: 5263:
   986207: 5264:            nextToken();
  5188017: 5265:            while (token.value != TOKrbracket &&
token.value != TOKeof)
        -: 5266:            {
  4155449: 5267:                    Expression *e = parseAssignExp();
  4234759: 5268:                    if (token.value == TOKcolon && (keys
|| values->dim == 0))
    79310: 5269:                    {   nextToken();
    79310: 5270:                        if (!keys)
     9369: 5271:                            keys = new Expressions();
    79310: 5272:                        keys->push(e);
    79310: 5273:                        e = parseAssignExp();
        -: 5274:                    }
  4076139: 5275:                    else if (keys)
    #####: 5276:                    {   error("'key:value' expected for
associative array literal");
    #####: 5277:                        delete keys;
    #####: 5278:                        keys = NULL;
        -: 5279:                    }
  4155449: 5280:                    values->push(e);
  4155449: 5281:                    if (token.value == TOKrbracket)
   939846: 5282:                        break;
  3215603: 5283:                    check(TOKcomma);
        -: 5284:            }
   986207: 5285:            check(loc, TOKrbracket);
        -: 5286:
   986207: 5287:            if (keys)
     9369: 5288:                e = new AssocArrayLiteralExp(loc, keys,
values);
        -: 5289:            else
   976838: 5290:                e = new ArrayLiteralExp(loc, values);
   986207: 5291:            break;
        -: 5292:        }
        -: 5293:
        -: 5294:        case TOKlcurly:
        -: 5295:            // { statements... }
    65476: 5296:            save = TOKdelegate;
    65476: 5297:            goto case_delegate;
        -: 5298:
        -: 5299:        case TOKfunction:
        -: 5300:        case TOKdelegate:
    15084: 5301:            save = token.value;
    15084: 5302:            nextToken();
   151406: 5303:        case_delegate:
        -: 5304:        {
        -: 5305:            /* function type(parameters) { body } pure
nothrow
        -: 5306:             * delegate type(parameters) { body } pure
nothrow
        -: 5307:             * (parameters) { body }
        -: 5308:             * { body }
        -: 5309:             */
        -: 5310:            Parameters *arguments;
        -: 5311:            int varargs;
        -: 5312:            FuncLiteralDeclaration *fd;
        -: 5313:            Type *t;
   151406: 5314:            StorageClass stc = 0;
        -: 5315:
   151406: 5316:            if (token.value == TOKlcurly)
        -: 5317:            {
    65604: 5318:                t = NULL;
    65604: 5319:                varargs = 0;
    65604: 5320:                arguments = new Parameters();
        -: 5321:            }
        -: 5322:            else
        -: 5323:            {
    85802: 5324:                if (token.value == TOKlparen)
    71487: 5325:                    t = NULL;
        -: 5326:                else
        -: 5327:                {
    14315: 5328:                    t = parseBasicType();
    14315: 5329:                    t = parseBasicType2(t);     //
function return type
        -: 5330:                }
    85802: 5331:                arguments = parseParameters(&varargs);
    85802: 5332:                stc = parsePostfix();
    85802: 5333:                if (stc & (STCconst | STCimmutable |
STCshared | STCwild))
    #####: 5334:                    error("const/immutable/shared/inout
attributes are only valid for non-static member functions");
        -: 5335:            }
        -: 5336:
   151406: 5337:            TypeFunction *tf = new
TypeFunction(arguments, t, varargs, linkage, stc);
        -: 5338:
   151406: 5339:            fd = new FuncLiteralDeclaration(loc, 0, tf,
save, NULL);
   151406: 5340:            parseContracts(fd);
   151406: 5341:            e = new FuncExp(loc, fd);
   151406: 5342:            break;
        -: 5343:        }
        -: 5344:
        -: 5345:        default:
    #####: 5346:            error("expression expected, not '%s'",
token.toChars());
    #####: 5347:        Lerr:
        -: 5348:            // Anything for e, as long as it's not NULL
    #####: 5349:            e = new IntegerExp(loc, 0, Type::tint32);
    #####: 5350:            nextToken();
        -: 5351:            break;
        -: 5352:    }
187736165: 5353:    return e;
        -: 5354:}
        -: 5355:
187752762: 5356:Expression *Parser::parsePostExp(Expression *e)
        -: 5357:{
187752762: 5358:    Loc loc;
        -: 5359:
 55191831: 5360:    while (1)
        -: 5361:    {
242944593: 5362:        loc = this->loc;
242944593: 5363:        switch (token.value)
        -: 5364:        {
        -: 5365:            case TOKdot:
 23349333: 5366:                nextToken();
 23349333: 5367:                if (token.value == TOKidentifier)
 23349266: 5368:                {   Identifier *id = token.ident;
        -: 5369:
 23349266: 5370:                    nextToken();
 23349266: 5371:                    if (token.value == TOKnot &&
peekNext() != TOKis)
        -: 5372:                    {   //
identifier!(template-argument-list)
   227352: 5373:                        TemplateInstance *tempinst = new
TemplateInstance(loc, id);
        -: 5374:                        Objects *tiargs;
   227352: 5375:                        nextToken();
   227352: 5376:                        if (token.value == TOKlparen)
        -: 5377:                            // ident!(template_arguments)
   196676: 5378:                            tiargs =
parseTemplateArgumentList();
        -: 5379:                        else
        -: 5380:                            // ident!template_argument
    30676: 5381:                            tiargs =
parseTemplateArgument();
   227352: 5382:                        e = new
DotTemplateInstanceExp(loc, e, id, tiargs);
        -: 5383:                    }
        -: 5384:                    else
 23121914: 5385:                        e = new DotIdExp(loc, e, id);
 23349266: 5386:                    continue;
        -: 5387:                }
       67: 5388:                else if (token.value == TOKnew)
        -: 5389:                {
       67: 5390:                    e = parseNewExp(e);
       67: 5391:                    continue;
        -: 5392:                }
        -: 5393:                else
    #####: 5394:                    error("identifier expected following
'.', not '%s'", token.toChars());
    #####: 5395:                break;
        -: 5396:
        -: 5397:            case TOKplusplus:
  1270178: 5398:                e = new PostExp(TOKplusplus, loc, e);
  1270178: 5399:                break;
        -: 5400:
        -: 5401:            case TOKminusminus:
   115212: 5402:                e = new PostExp(TOKminusminus, loc, e);
   115212: 5403:                break;
        -: 5404:
        -: 5405:            case TOKlparen:
 21526275: 5406:                e = new CallExp(loc, e, parseArguments());
 21526275: 5407:                continue;
        -: 5408:
        -: 5409:            case TOKlbracket:
        -: 5410:            {   // array dereferences:
        -: 5411:                //      array[index]
        -: 5412:                //      array[]
        -: 5413:                //      array[lwr .. upr]
        -: 5414:                Expression *index;
        -: 5415:                Expression *upr;
        -: 5416:
  8930833: 5417:                inBrackets++;
  8930833: 5418:                nextToken();
  8930833: 5419:                if (token.value == TOKrbracket)
        -: 5420:                {   // array[]
   432231: 5421:                    e = new SliceExp(loc, e, NULL, NULL);
   432231: 5422:                    nextToken();
        -: 5423:                }
        -: 5424:                else
        -: 5425:                {
  8498602: 5426:                    index = parseAssignExp();
  8498602: 5427:                    if (token.value == TOKslice)
        -: 5428:                    {   // array[lwr .. upr]
  1755223: 5429:                        nextToken();
  1755223: 5430:                        upr = parseAssignExp();
  1755223: 5431:                        e = new SliceExp(loc, e, index,
upr);
        -: 5432:                    }
        -: 5433:                    else
        -: 5434:                    {   // array[index, i2, i3, i4, ...]
  6743379: 5435:                        Expressions *arguments = new
Expressions();
  6743379: 5436:                        arguments->push(index);
  6743379: 5437:                        if (token.value == TOKcomma)
        -: 5438:                        {
      384: 5439:                            nextToken();
      896: 5440:                            while (token.value !=
TOKrbracket && token.value != TOKeof)
        -: 5441:                            {
      448: 5442:                                Expression *arg =
parseAssignExp();
      448: 5443:                                arguments->push(arg);
      448: 5444:                                if (token.value ==
TOKrbracket)
      320: 5445:                                    break;
      128: 5446:                                check(TOKcomma);
        -: 5447:                            }
        -: 5448:                        }
  6743379: 5449:                        e = new ArrayExp(loc, e, arguments);
        -: 5450:                    }
  8498602: 5451:                    check(TOKrbracket);
  8498602: 5452:                    inBrackets--;
        -: 5453:                }
  8930833: 5454:                continue;
        -: 5455:            }
        -: 5456:
        -: 5457:            default:
187752762: 5458:                return e;
        -: 5459:        }
  1385390: 5460:        nextToken();
        -: 5461:    }
        -: 5462:}
        -: 5463:
199609516: 5464:Expression *Parser::parseUnaryExp()
        -: 5465:{   Expression *e;
199609516: 5466:    Loc loc = this->loc;
        -: 5467:
199609516: 5468:    switch (token.value)
        -: 5469:    {
        -: 5470:        case TOKand:
  1614995: 5471:            nextToken();
  1614995: 5472:            e = parseUnaryExp();
  1614995: 5473:            e = new AddrExp(loc, e);
  1614995: 5474:            break;
        -: 5475:
        -: 5476:        case TOKplusplus:
   456053: 5477:            nextToken();
   456053: 5478:            e = parseUnaryExp();
        -: 5479:            //e = new AddAssignExp(loc, e, new
IntegerExp(loc, 1, Type::tint32));
   456053: 5480:            e = new PreExp(TOKpreplusplus, loc, e);
   456053: 5481:            break;
        -: 5482:
        -: 5483:        case TOKminusminus:
   112876: 5484:            nextToken();
   112876: 5485:            e = parseUnaryExp();
        -: 5486:            //e = new MinAssignExp(loc, e, new
IntegerExp(loc, 1, Type::tint32));
   112876: 5487:            e = new PreExp(TOKpreminusminus, loc, e);
   112876: 5488:            break;
        -: 5489:
        -: 5490:        case TOKmul:
   664666: 5491:            nextToken();
   664666: 5492:            e = parseUnaryExp();
   664666: 5493:            e = new PtrExp(loc, e);
   664666: 5494:            break;
        -: 5495:
        -: 5496:        case TOKmin:
  1517841: 5497:            nextToken();
  1517841: 5498:            e = parseUnaryExp();
  1517841: 5499:            e = new NegExp(loc, e);
  1517841: 5500:            break;
        -: 5501:
        -: 5502:        case TOKadd:
   142855: 5503:            nextToken();
   142855: 5504:            e = parseUnaryExp();
   142855: 5505:            e = new UAddExp(loc, e);
   142855: 5506:            break;
        -: 5507:
        -: 5508:        case TOKnot:
  2873861: 5509:            nextToken();
  2873861: 5510:            e = parseUnaryExp();
  2873861: 5511:            e = new NotExp(loc, e);
  2873861: 5512:            break;
        -: 5513:
        -: 5514:        case TOKtilde:
   197789: 5515:            nextToken();
   197789: 5516:            e = parseUnaryExp();
   197789: 5517:            e = new ComExp(loc, e);
   197789: 5518:            break;
        -: 5519:
        -: 5520:        case TOKdelete:
    40768: 5521:            nextToken();
    40768: 5522:            e = parseUnaryExp();
    40768: 5523:            e = new DeleteExp(loc, e);
    40768: 5524:            break;
        -: 5525:
        -: 5526:        case TOKnew:
   757437: 5527:            e = parseNewExp(NULL);
   757437: 5528:            break;
        -: 5529:
        -: 5530:        case TOKcast:                           //
cast(type) expression
        -: 5531:        {
  3477357: 5532:            nextToken();
  3477357: 5533:            check(TOKlparen);
        -: 5534:            /* Look for cast(), cast(const),
cast(immutable),
        -: 5535:             * cast(shared), cast(shared const),
cast(wild), cast(shared wild)
        -: 5536:             */
        -: 5537:            unsigned m;
  3477357: 5538:            if (token.value == TOKrparen)
        -: 5539:            {
     3543: 5540:                m = 0;
     3543: 5541:                goto Lmod1;
        -: 5542:            }
  3473814: 5543:            else if (token.value == TOKconst &&
peekNext() == TOKrparen)
        -: 5544:            {
      320: 5545:                m = MODconst;
      320: 5546:                goto Lmod2;
        -: 5547:            }
  3473494: 5548:            else if ((token.value == TOKimmutable ||
token.value == TOKinvariant) && peekNext() == TOKrparen)
        -: 5549:            {
      256: 5550:                m = MODimmutable;
      256: 5551:                goto Lmod2;
        -: 5552:            }
  3473238: 5553:            else if (token.value == TOKshared &&
peekNext() == TOKrparen)
        -: 5554:            {
    12252: 5555:                m = MODshared;
    12252: 5556:                goto Lmod2;
        -: 5557:            }
  3460986: 5558:            else if (token.value == TOKwild &&
peekNext() == TOKrparen)
        -: 5559:            {
      128: 5560:                m = MODwild;
      128: 5561:                goto Lmod2;
        -: 5562:            }
  3460858: 5563:            else if (token.value == TOKwild &&
peekNext() == TOKshared && peekNext2() == TOKrparen ||
        -: 5564:                     token.value == TOKshared &&
peekNext() == TOKwild && peekNext2() == TOKrparen)
        -: 5565:            {
    #####: 5566:                m = MODshared | MODwild;
    #####: 5567:                goto Lmod3;
        -: 5568:            }
  3460858: 5569:            else if (token.value == TOKconst &&
peekNext() == TOKshared && peekNext2() == TOKrparen ||
        -: 5570:                     token.value == TOKshared &&
peekNext() == TOKconst && peekNext2() == TOKrparen)
        -: 5571:            {
      128: 5572:                m = MODshared | MODconst;
      128: 5573:              Lmod3:
      128: 5574:                nextToken();
    13084: 5575:              Lmod2:
    13084: 5576:                nextToken();
    16627: 5577:              Lmod1:
    16627: 5578:                nextToken();
    16627: 5579:                e = parseUnaryExp();
    16627: 5580:                e = new CastExp(loc, e, m);
        -: 5581:            }
        -: 5582:            else
        -: 5583:            {
  3460730: 5584:                Type *t = parseType();          // ( type )
  3460730: 5585:                check(TOKrparen);
  3460730: 5586:                e = parseUnaryExp();
  3460730: 5587:                e = new CastExp(loc, e, t);
        -: 5588:            }
  3477357: 5589:            break;
        -: 5590:        }
        -: 5591:
        -: 5592:        case TOKwild:
        -: 5593:        case TOKshared:
        -: 5594:        case TOKconst:
        -: 5595:        case TOKinvariant:
        -: 5596:        case TOKimmutable:      //
immutable(type)(arguments)
        -: 5597:        {
      256: 5598:            Type *t = parseBasicType();
      256: 5599:            if (token.value != TOKlparen)
    #####: 5600:                error("(arguments) expected following
type");
      256: 5601:            e = new TypeExp(loc, t);
      256: 5602:            e = new CallExp(loc, e, parseArguments());
      256: 5603:            break;
        -: 5604:        }
        -: 5605:
        -: 5606:
        -: 5607:        case TOKlparen:
        -: 5608:        {   Token *tk;
        -: 5609:
  4488071: 5610:            tk = peek(&token);
        -: 5611:#if CCASTSYNTAX
        -: 5612:            // If cast
  4488071: 5613:            if (isDeclaration(tk, 0, TOKrparen, &tk))
        -: 5614:            {
   266511: 5615:                tk = peek(tk);          // skip over
right parenthesis
   266511: 5616:                switch (tk->value)
        -: 5617:                {
        -: 5618:                    case TOKnot:
       64: 5619:                        tk = peek(tk);
       64: 5620:                        if (tk->value == TOKis ||
tk->value == TOKin)   // !is or !in
       64: 5621:                            break;
        -: 5622:                    case TOKdot:
        -: 5623:                    case TOKplusplus:
        -: 5624:                    case TOKminusminus:
        -: 5625:                    case TOKdelete:
        -: 5626:                    case TOKnew:
        -: 5627:                    case TOKlparen:
        -: 5628:                    case TOKidentifier:
        -: 5629:                    case TOKthis:
        -: 5630:                    case TOKsuper:
        -: 5631:                    case TOKint32v:
        -: 5632:                    case TOKuns32v:
        -: 5633:                    case TOKint64v:
        -: 5634:                    case TOKuns64v:
        -: 5635:                    case TOKfloat32v:
        -: 5636:                    case TOKfloat64v:
        -: 5637:                    case TOKfloat80v:
        -: 5638:                    case TOKimaginary32v:
        -: 5639:                    case TOKimaginary64v:
        -: 5640:                    case TOKimaginary80v:
        -: 5641:                    case TOKnull:
        -: 5642:                    case TOKtrue:
        -: 5643:                    case TOKfalse:
        -: 5644:                    case TOKcharv:
        -: 5645:                    case TOKwcharv:
        -: 5646:                    case TOKdcharv:
        -: 5647:                    case TOKstring:
        -: 5648:#if 0
        -: 5649:                    case TOKtilde:
        -: 5650:                    case TOKand:
        -: 5651:                    case TOKmul:
        -: 5652:                    case TOKmin:
        -: 5653:                    case TOKadd:
        -: 5654:#endif
        -: 5655:                    case TOKfunction:
        -: 5656:                    case TOKdelegate:
        -: 5657:                    case TOKtypeof:
        -: 5658:#if DMDV2
        -: 5659:                    case TOKfile:
        -: 5660:                    case TOKline:
        -: 5661:#endif
        -: 5662:                    case BASIC_TYPES:           //
(type)int.size
        -: 5663:                    {   // (type) una_exp
        -: 5664:                        Type *t;
        -: 5665:
   178929: 5666:                        nextToken();
   178929: 5667:                        t = parseType();
   178929: 5668:                        check(TOKrparen);
        -: 5669:
        -: 5670:                        // if .identifier
   178929: 5671:                        if (token.value == TOKdot)
        -: 5672:                        {
   178929: 5673:                            nextToken();
   178929: 5674:                            if (token.value !=
TOKidentifier)
    #####: 5675:                            {   error("Identifier
expected following (type).");
    #####: 5676:                                return NULL;
        -: 5677:                            }
   178929: 5678:                            e = typeDotIdExp(loc, t,
token.ident);
   178929: 5679:                            nextToken();
   178929: 5680:                            e = parsePostExp(e);
        -: 5681:                        }
        -: 5682:                        else
        -: 5683:                        {
    #####: 5684:                            e = parseUnaryExp();
    #####: 5685:                            e = new CastExp(loc, e, t);
    #####: 5686:                            error("C style cast illegal,
use %s", e->toChars());
        -: 5687:                        }
   178929: 5688:                        return e;
        -: 5689:                    }
        -: 5690:                }
        -: 5691:            }
        -: 5692:#endif
  4309142: 5693:            e = parsePrimaryExp();
  4309142: 5694:            e = parsePostExp(e);
  4309142: 5695:            break;
        -: 5696:        }
        -: 5697:        default:
183264691: 5698:            e = parsePrimaryExp();
183264691: 5699:            e = parsePostExp(e);
        -: 5700:            break;
        -: 5701:    }
199430587: 5702:    assert(e);
        -: 5703:
        -: 5704:    // ^^ is right associative and has higher precedence
than the unary operators
398861350: 5705:    while (token.value == TOKpow)
        -: 5706:    {
      176: 5707:        nextToken();
      176: 5708:        Expression *e2 = parseUnaryExp();
      176: 5709:        e = new PowExp(loc, e, e2);
        -: 5710:    }
        -: 5711:
199430587: 5712:    return e;
        -: 5713:}
        -: 5714:
186314304: 5715:Expression *Parser::parseMulExp()
        -: 5716:{   Expression *e;
        -: 5717:    Expression *e2;
186314304: 5718:    Loc loc = this->loc;
        -: 5719:
186314304: 5720:    e = parseUnaryExp();
  2195975: 5721:    while (1)
        -: 5722:    {
188510279: 5723:        switch (token.value)
        -: 5724:        {
  1516333: 5725:            case TOKmul: nextToken(); e2 =
parseUnaryExp(); e = new MulExp(loc,e,e2); continue;
   500497: 5726:            case TOKdiv: nextToken(); e2 =
parseUnaryExp(); e = new DivExp(loc,e,e2); continue;
   179145: 5727:            case TOKmod: nextToken(); e2 =
parseUnaryExp(); e = new ModExp(loc,e,e2); continue;
        -: 5728:
        -: 5729:            default:
        -: 5730:                break;
        -: 5731:        }
        -: 5732:        break;
        -: 5733:    }
186314304: 5734:    return e;
        -: 5735:}
        -: 5736:
179407959: 5737:Expression *Parser::parseAddExp()
        -: 5738:{   Expression *e;
        -: 5739:    Expression *e2;
179407959: 5740:    Loc loc = this->loc;
        -: 5741:
179407959: 5742:    e = parseMulExp();
  6906345: 5743:    while (1)
        -: 5744:    {
186314304: 5745:        switch (token.value)
        -: 5746:        {
  3292153: 5747:            case TOKadd:    nextToken(); e2 =
parseMulExp(); e = new AddExp(loc,e,e2); continue;
  2181365: 5748:            case TOKmin:    nextToken(); e2 =
parseMulExp(); e = new MinExp(loc,e,e2); continue;
  1432827: 5749:            case TOKtilde:  nextToken(); e2 =
parseMulExp(); e = new CatExp(loc,e,e2); continue;
        -: 5750:
        -: 5751:            default:
        -: 5752:                break;
        -: 5753:        }
        -: 5754:        break;
        -: 5755:    }
179407959: 5756:    return e;
        -: 5757:}
        -: 5758:
178783908: 5759:Expression *Parser::parseShiftExp()
        -: 5760:{   Expression *e;
        -: 5761:    Expression *e2;
178783908: 5762:    Loc loc = this->loc;
        -: 5763:
178783908: 5764:    e = parseAddExp();
   624051: 5765:    while (1)
        -: 5766:    {
179407959: 5767:        switch (token.value)
        -: 5768:        {
   263256: 5769:            case TOKshl:  nextToken(); e2 =
parseAddExp(); e = new ShlExp(loc,e,e2);  continue;
   335649: 5770:            case TOKshr:  nextToken(); e2 =
parseAddExp(); e = new ShrExp(loc,e,e2);  continue;
    25146: 5771:            case TOKushr: nextToken(); e2 =
parseAddExp(); e = new UshrExp(loc,e,e2); continue;
        -: 5772:
        -: 5773:            default:
        -: 5774:                break;
        -: 5775:        }
        -: 5776:        break;
        -: 5777:    }
178783908: 5778:    return e;
        -: 5779:}
        -: 5780:
        -: 5781:#if DMDV1
        -: 5782:Expression *Parser::parseRelExp()
        -: 5783:{   Expression *e;
        -: 5784:    Expression *e2;
        -: 5785:    enum TOK op;
        -: 5786:    Loc loc = this->loc;
        -: 5787:
        -: 5788:    e = parseShiftExp();
        -: 5789:    while (1)
        -: 5790:    {
        -: 5791:        switch (token.value)
        -: 5792:        {
        -: 5793:            case TOKlt:
        -: 5794:            case TOKle:
        -: 5795:            case TOKgt:
        -: 5796:            case TOKge:
        -: 5797:            case TOKunord:
        -: 5798:            case TOKlg:
        -: 5799:            case TOKleg:
        -: 5800:            case TOKule:
        -: 5801:            case TOKul:
        -: 5802:            case TOKuge:
        -: 5803:            case TOKug:
        -: 5804:            case TOKue:
        -: 5805:                op = token.value;
        -: 5806:                nextToken();
        -: 5807:                e2 = parseShiftExp();
        -: 5808:                e = new CmpExp(op, loc, e, e2);
        -: 5809:                continue;
        -: 5810:
        -: 5811:            case TOKnot:                // could be !in
        -: 5812:                if (peekNext() == TOKin)
        -: 5813:                {
        -: 5814:                    nextToken();
        -: 5815:                    nextToken();
        -: 5816:                    e2 = parseShiftExp();
        -: 5817:                    e = new InExp(loc, e, e2);
        -: 5818:                    e = new NotExp(loc, e);
        -: 5819:                    continue;
        -: 5820:                }
        -: 5821:                break;
        -: 5822:
        -: 5823:            case TOKin:
        -: 5824:                nextToken();
        -: 5825:                e2 = parseShiftExp();
        -: 5826:                e = new InExp(loc, e, e2);
        -: 5827:                continue;
        -: 5828:
        -: 5829:            default:
        -: 5830:                break;
        -: 5831:        }
        -: 5832:        break;
        -: 5833:    }
        -: 5834:    return e;
        -: 5835:}
        -: 5836:#endif
        -: 5837:
        -: 5838:#if DMDV1
        -: 5839:Expression *Parser::parseEqualExp()
        -: 5840:{   Expression *e;
        -: 5841:    Expression *e2;
        -: 5842:    Token *t;
        -: 5843:    Loc loc = this->loc;
        -: 5844:
        -: 5845:    e = parseRelExp();
        -: 5846:    while (1)
        -: 5847:    {   enum TOK value = token.value;
        -: 5848:
        -: 5849:        switch (value)
        -: 5850:        {
        -: 5851:            case TOKequal:
        -: 5852:            case TOKnotequal:
        -: 5853:                nextToken();
        -: 5854:                e2 = parseRelExp();
        -: 5855:                e = new EqualExp(value, loc, e, e2);
        -: 5856:                continue;
        -: 5857:
        -: 5858:            case TOKidentity:
        -: 5859:                error("'===' is no longer legal, use
'is' instead");
        -: 5860:                goto L1;
        -: 5861:
        -: 5862:            case TOKnotidentity:
        -: 5863:                error("'!==' is no longer legal, use
'!is' instead");
        -: 5864:                goto L1;
        -: 5865:
        -: 5866:            case TOKis:
        -: 5867:                value = TOKidentity;
        -: 5868:                goto L1;
        -: 5869:
        -: 5870:            case TOKnot:
        -: 5871:                // Attempt to identify '!is'
        -: 5872:                t = peek(&token);
        -: 5873:                if (t->value != TOKis)
        -: 5874:                    break;
        -: 5875:                nextToken();
        -: 5876:                value = TOKnotidentity;
        -: 5877:                goto L1;
        -: 5878:
        -: 5879:            L1:
        -: 5880:                nextToken();
        -: 5881:                e2 = parseRelExp();
        -: 5882:                e = new IdentityExp(value, loc, e, e2);
        -: 5883:                continue;
        -: 5884:
        -: 5885:            default:
        -: 5886:                break;
        -: 5887:        }
        -: 5888:        break;
        -: 5889:    }
        -: 5890:    return e;
        -: 5891:}
        -: 5892:#endif
        -: 5893:
163565571: 5894:Expression *Parser::parseCmpExp()
        -: 5895:{   Expression *e;
        -: 5896:    Expression *e2;
        -: 5897:    Token *t;
163565571: 5898:    Loc loc = this->loc;
        -: 5899:
163565571: 5900:    e = parseShiftExp();
163565571: 5901:    enum TOK op = token.value;
        -: 5902:
163565571: 5903:    switch (op)
        -: 5904:    {
        -: 5905:        case TOKequal:
        -: 5906:        case TOKnotequal:
 10926317: 5907:            nextToken();
 10926317: 5908:            e2 = parseShiftExp();
 10926317: 5909:            e = new EqualExp(op, loc, e, e2);
 10926317: 5910:            break;
        -: 5911:
        -: 5912:        case TOKis:
   112424: 5913:            op = TOKidentity;
   112424: 5914:            goto L1;
        -: 5915:
        -: 5916:        case TOKnot:
        -: 5917:            // Attempt to identify '!is'
    40849: 5918:            t = peek(&token);
    40849: 5919:            if (t->value == TOKin)
        -: 5920:            {
        2: 5921:                nextToken();
        2: 5922:                nextToken();
        2: 5923:                e2 = parseShiftExp();
        2: 5924:                e = new InExp(loc, e, e2);
        2: 5925:                e = new NotExp(loc, e);
        2: 5926:                break;
        -: 5927:            }
    40847: 5928:            if (t->value != TOKis)
    #####: 5929:                break;
    40847: 5930:            nextToken();
    40847: 5931:            op = TOKnotidentity;
        -: 5932:            goto L1;
        -: 5933:
   153271: 5934:        L1:
   153271: 5935:            nextToken();
   153271: 5936:            e2 = parseShiftExp();
   153271: 5937:            e = new IdentityExp(op, loc, e, e2);
   153271: 5938:            break;
        -: 5939:
        -: 5940:        case TOKlt:
        -: 5941:        case TOKle:
        -: 5942:        case TOKgt:
        -: 5943:        case TOKge:
        -: 5944:        case TOKunord:
        -: 5945:        case TOKlg:
        -: 5946:        case TOKleg:
        -: 5947:        case TOKule:
        -: 5948:        case TOKul:
        -: 5949:        case TOKuge:
        -: 5950:        case TOKug:
        -: 5951:        case TOKue:
  4123540: 5952:            nextToken();
  4123540: 5953:            e2 = parseShiftExp();
  4123540: 5954:            e = new CmpExp(op, loc, e, e2);
  4123540: 5955:            break;
        -: 5956:
        -: 5957:        case TOKin:
    15207: 5958:            nextToken();
    15207: 5959:            e2 = parseShiftExp();
    15207: 5960:            e = new InExp(loc, e, e2);
        -: 5961:            break;
        -: 5962:
        -: 5963:        default:
        -: 5964:            break;
        -: 5965:    }
163565571: 5966:    return e;
        -: 5967:}
        -: 5968:
162266597: 5969:Expression *Parser::parseAndExp()
        -: 5970:{
162266597: 5971:    Loc loc = this->loc;
        -: 5972:
162266597: 5973:    Expression *e = parseCmpExp();
325832168: 5974:    while (token.value == TOKand)
        -: 5975:    {
  1298974: 5976:        checkParens(TOKand, e);
  1298974: 5977:        nextToken();
  1298974: 5978:        Expression *e2 = parseCmpExp();
  1298974: 5979:        checkParens(TOKand, e2);
  1298974: 5980:        e = new AndExp(loc,e,e2);
  1298974: 5981:        loc = this->loc;
        -: 5982:    }
162266597: 5983:    return e;
        -: 5984:}
        -: 5985:
162221160: 5986:Expression *Parser::parseXorExp()
        -: 5987:{
162221160: 5988:    Loc loc = this->loc;
        -: 5989:
162221160: 5990:    Expression *e = parseAndExp();
324487757: 5991:    while (token.value == TOKxor)
        -: 5992:    {
    45437: 5993:        checkParens(TOKxor, e);
    45437: 5994:        nextToken();
    45437: 5995:        Expression *e2 = parseAndExp();
    45437: 5996:        checkParens(TOKxor, e2);
    45437: 5997:        e = new XorExp(loc, e, e2);
        -: 5998:    }
162221160: 5999:    return e;
        -: 6000:}
        -: 6001:
161813954: 6002:Expression *Parser::parseOrExp()
        -: 6003:{
161813954: 6004:    Loc loc = this->loc;
        -: 6005:
161813954: 6006:    Expression *e = parseXorExp();
324035114: 6007:    while (token.value == TOKor)
        -: 6008:    {
   407206: 6009:        checkParens(TOKor, e);
   407206: 6010:        nextToken();
   407206: 6011:        Expression *e2 = parseXorExp();
   407206: 6012:        checkParens(TOKor, e2);
   407206: 6013:        e = new OrExp(loc, e, e2);
        -: 6014:    }
161813954: 6015:    return e;
        -: 6016:}
        -: 6017:
159228582: 6018:Expression *Parser::parseAndAndExp()
        -: 6019:{   Expression *e;
        -: 6020:    Expression *e2;
159228582: 6021:    Loc loc = this->loc;
        -: 6022:
159228582: 6023:    e = parseOrExp();
321042536: 6024:    while (token.value == TOKandand)
        -: 6025:    {
  2585372: 6026:        nextToken();
  2585372: 6027:        e2 = parseOrExp();
  2585372: 6028:        e = new AndAndExp(loc, e, e2);
        -: 6029:    }
159228582: 6030:    return e;
        -: 6031:}
        -: 6032:
158299180: 6033:Expression *Parser::parseOrOrExp()
        -: 6034:{   Expression *e;
        -: 6035:    Expression *e2;
158299180: 6036:    Loc loc = this->loc;
        -: 6037:
158299180: 6038:    e = parseAndAndExp();
317527762: 6039:    while (token.value == TOKoror)
        -: 6040:    {
   929402: 6041:        nextToken();
   929402: 6042:        e2 = parseAndAndExp();
   929402: 6043:        e = new OrOrExp(loc, e, e2);
        -: 6044:    }
158299180: 6045:    return e;
        -: 6046:}
        -: 6047:
158299180: 6048:Expression *Parser::parseCondExp()
        -: 6049:{   Expression *e;
        -: 6050:    Expression *e1;
        -: 6051:    Expression *e2;
158299180: 6052:    Loc loc = this->loc;
        -: 6053:
158299180: 6054:    e = parseOrOrExp();
158299180: 6055:    if (token.value == TOKquestion)
        -: 6056:    {
   601903: 6057:        nextToken();
   601903: 6058:        e1 = parseExpression();
   601903: 6059:        check(TOKcolon);
   601903: 6060:        e2 = parseCondExp();
   601903: 6061:        e = new CondExp(loc, e, e1, e2);
        -: 6062:    }
158299180: 6063:    return e;
        -: 6064:}
        -: 6065:
157520254: 6066:Expression *Parser::parseAssignExp()
        -: 6067:{   Expression *e;
        -: 6068:    Expression *e2;
157520254: 6069:    Loc loc;
        -: 6070:
157520254: 6071:    e = parseCondExp();
 12563059: 6072:    while (1)
        -: 6073:    {
170083313: 6074:        loc = this->loc;
170083313: 6075:        switch (token.value)
        -: 6076:        {
        -: 6077:#define X(tok,ector) \
        -: 6078:            case tok:  nextToken(); e2 =
parseAssignExp(); e = new ector(loc,e,e2); continue;
        -: 6079:
 10704590: 6080:            X(TOKassign,    AssignExp);
   649084: 6081:            X(TOKaddass,    AddAssignExp);
   151181: 6082:            X(TOKminass,    MinAssignExp);
    83729: 6083:            X(TOKmulass,    MulAssignExp);
    40267: 6084:            X(TOKdivass,    DivAssignExp);
     6846: 6085:            X(TOKmodass,    ModAssignExp);
     1552: 6086:            X(TOKpowass,    PowAssignExp);
   142235: 6087:            X(TOKandass,    AndAssignExp);
   166915: 6088:            X(TOKorass,     OrAssignExp);
    12606: 6089:            X(TOKxorass,    XorAssignExp);
    31073: 6090:            X(TOKshlass,    ShlAssignExp);
    39824: 6091:            X(TOKshrass,    ShrAssignExp);
     6382: 6092:            X(TOKushrass,   UshrAssignExp);
   526775: 6093:            X(TOKcatass,    CatAssignExp);
        -: 6094:
        -: 6095:#undef X
        -: 6096:            default:
        -: 6097:                break;
        -: 6098:        }
        -: 6099:        break;
        -: 6100:    }
157520254: 6101:    return e;
        -: 6102:}
        -: 6103:
 52552484: 6104:Expression *Parser::parseExpression()
        -: 6105:{   Expression *e;
        -: 6106:    Expression *e2;
 52552484: 6107:    Loc loc = this->loc;
        -: 6108:
        -: 6109:    //printf("Parser::parseExpression() loc = %d\n",
loc.linnum);
 52552484: 6110:    e = parseAssignExp();
105216534: 6111:    while (token.value == TOKcomma)
        -: 6112:    {
   111566: 6113:        nextToken();
   111566: 6114:        e2 = parseAssignExp();
   111566: 6115:        e = new CommaExp(loc, e, e2);
   111566: 6116:        loc = this->loc;
        -: 6117:    }
 52552484: 6118:    return e;
        -: 6119:}
        -: 6120:
        -: 6121:
        -: 6122:/*************************
        -: 6123: * Collect argument list.
        -: 6124: * Assume current token is ',', '(' or '['.
        -: 6125: */
        -: 6126:
 21957991: 6127:Expressions *Parser::parseArguments()
        -: 6128:{   // function call
        -: 6129:    Expressions *arguments;
        -: 6130:    Expression *arg;
        -: 6131:    enum TOK endtok;
        -: 6132:
 21957991: 6133:    arguments = new Expressions();
 21957991: 6134:    if (token.value == TOKlbracket)
    #####: 6135:        endtok = TOKrbracket;
        -: 6136:    else
 21957991: 6137:        endtok = TOKrparen;
        -: 6138:
        -: 6139:    {
 21957991: 6140:        nextToken();
 56679831: 6141:        while (token.value != endtok)
        -: 6142:        {
 33252209: 6143:                arg = parseAssignExp();
 33252209: 6144:                arguments->push(arg);
 33252209: 6145:                if (token.value == endtok)
 20488360: 6146:                    break;
 12763849: 6147:                check(TOKcomma);
        -: 6148:        }
 21957991: 6149:        check(endtok);
        -: 6150:    }
 21957991: 6151:    return arguments;
        -: 6152:}
        -: 6153:
        -: 6154:/*******************************************
        -: 6155: */
        -: 6156:
   757504: 6157:Expression *Parser::parseNewExp(Expression *thisexp)
        -: 6158:{   Type *t;
        -: 6159:    Expressions *newargs;
   757504: 6160:    Expressions *arguments = NULL;
        -: 6161:    Expression *e;
   757504: 6162:    Loc loc = this->loc;
        -: 6163:
   757504: 6164:    nextToken();
   757504: 6165:    newargs = NULL;
   757504: 6166:    if (token.value == TOKlparen)
        -: 6167:    {
     3161: 6168:        newargs = parseArguments();
        -: 6169:    }
        -: 6170:
        -: 6171:    // An anonymous nested class starts with "class"
   757504: 6172:    if (token.value == TOKclass)
        -: 6173:    {
     3547: 6174:        nextToken();
     3547: 6175:        if (token.value == TOKlparen)
      194: 6176:            arguments = parseArguments();
        -: 6177:
     3547: 6178:        BaseClasses *baseclasses = NULL;
     3547: 6179:        if (token.value != TOKlcurly)
     3419: 6180:            baseclasses = parseBaseClasses();
        -: 6181:
     3547: 6182:        Identifier *id = NULL;
     3547: 6183:        ClassDeclaration *cd = new ClassDeclaration(loc,
id, baseclasses);
        -: 6184:
     3547: 6185:        if (token.value != TOKlcurly)
    #####: 6186:        {   error("{ members } expected for anonymous
class");
    #####: 6187:            cd->members = NULL;
        -: 6188:        }
        -: 6189:        else
        -: 6190:        {
     3547: 6191:            nextToken();
     3547: 6192:            Dsymbols *decl = parseDeclDefs(0);
     3547: 6193:            if (token.value != TOKrcurly)
    #####: 6194:                error("class member expected");
     3547: 6195:            nextToken();
     3547: 6196:            cd->members = decl;
        -: 6197:        }
        -: 6198:
     3547: 6199:        e = new NewAnonClassExp(loc, thisexp, newargs,
cd, arguments);
        -: 6200:
     3547: 6201:        return e;
        -: 6202:    }
        -: 6203:
   753957: 6204:    t = parseBasicType();
   753957: 6205:    t = parseBasicType2(t);
   753957: 6206:    if (t->ty == Taarray)
    71221: 6207:    {   TypeAArray *taa = (TypeAArray *)t;
    71221: 6208:        Type *index = taa->index;
        -: 6209:
    71221: 6210:        Expression *e = index->toExpression();
    71221: 6211:        if (e)
    71221: 6212:        {   arguments = new Expressions();
    71221: 6213:            arguments->push(e);
    71221: 6214:            t = new TypeDArray(taa->next);
        -: 6215:        }
        -: 6216:        else
        -: 6217:        {
    #####: 6218:            error("need size of rightmost array, not
type %s", index->toChars());
    #####: 6219:            return new NullExp(loc);
        -: 6220:        }
        -: 6221:    }
   682736: 6222:    else if (t->ty == Tsarray)
        -: 6223:    {
   189136: 6224:        TypeSArray *tsa = (TypeSArray *)t;
   189136: 6225:        Expression *e = tsa->dim;
        -: 6226:
   189136: 6227:        arguments = new Expressions();
   189136: 6228:        arguments->push(e);
   189136: 6229:        t = new TypeDArray(tsa->next);
        -: 6230:    }
   493600: 6231:    else if (token.value == TOKlparen)
        -: 6232:    {
   398297: 6233:        arguments = parseArguments();
        -: 6234:    }
   753957: 6235:    e = new NewExp(loc, thisexp, newargs, t, arguments);
   753957: 6236:    return e;
        -: 6237:}
        -: 6238:
        -: 6239:/**********************************************
        -: 6240: */
        -: 6241:
 71292756: 6242:void Parser::addComment(Dsymbol *s, unsigned char
*blockComment)
        -: 6243:{
 71292756: 6244:    s->addComment(combineComments(blockComment,
token.lineComment));
 71292756: 6245:    token.lineComment = NULL;
 71292756: 6246:}
        -: 6247:
        -: 6248:
        -: 6249:/**********************************
        -: 6250: * Set operator precedence for each operator.
        -: 6251: */
        -: 6252:
        -: 6253:enum PREC precedence[TOKMAX];
        -: 6254:
     5534: 6255:void initPrecedence()
        -: 6256:{
  1261752: 6257:    for (int i = 0; i < TOKMAX; i++)
  1256218: 6258:        precedence[i] = PREC_zero;
        -: 6259:
     5534: 6260:    precedence[TOKtype] = PREC_expr;
     5534: 6261:    precedence[TOKerror] = PREC_expr;
        -: 6262:
     5534: 6263:    precedence[TOKtypeof] = PREC_primary;
     5534: 6264:    precedence[TOKmixin] = PREC_primary;
        -: 6265:
     5534: 6266:    precedence[TOKdotvar] = PREC_primary;
     5534: 6267:    precedence[TOKimport] = PREC_primary;
     5534: 6268:    precedence[TOKidentifier] = PREC_primary;
     5534: 6269:    precedence[TOKthis] = PREC_primary;
     5534: 6270:    precedence[TOKsuper] = PREC_primary;
     5534: 6271:    precedence[TOKint64] = PREC_primary;
     5534: 6272:    precedence[TOKfloat64] = PREC_primary;
     5534: 6273:    precedence[TOKnull] = PREC_primary;
     5534: 6274:    precedence[TOKstring] = PREC_primary;
     5534: 6275:    precedence[TOKarrayliteral] = PREC_primary;
     5534: 6276:    precedence[TOKtypeid] = PREC_primary;
     5534: 6277:    precedence[TOKis] = PREC_primary;
     5534: 6278:    precedence[TOKassert] = PREC_primary;
     5534: 6279:    precedence[TOKfunction] = PREC_primary;
     5534: 6280:    precedence[TOKvar] = PREC_primary;
     5534: 6281:    precedence[TOKsymoff] = PREC_primary;
     5534: 6282:    precedence[TOKstructliteral] = PREC_primary;
     5534: 6283:    precedence[TOKarraylength] = PREC_primary;
        -: 6284:#if DMDV2
     5534: 6285:    precedence[TOKtraits] = PREC_primary;
     5534: 6286:    precedence[TOKdefault] = PREC_primary;
        -: 6287:#endif
        -: 6288:
        -: 6289:    // post
     5534: 6290:    precedence[TOKdotti] = PREC_primary;
     5534: 6291:    precedence[TOKdot] = PREC_primary;
     5534: 6292:    precedence[TOKdottd] = PREC_primary;
        -: 6293://  precedence[TOKarrow] = PREC_primary;
     5534: 6294:    precedence[TOKplusplus] = PREC_primary;
     5534: 6295:    precedence[TOKminusminus] = PREC_primary;
     5534: 6296:    precedence[TOKpreplusplus] = PREC_primary;
     5534: 6297:    precedence[TOKpreminusminus] = PREC_primary;
     5534: 6298:    precedence[TOKcall] = PREC_primary;
     5534: 6299:    precedence[TOKslice] = PREC_primary;
     5534: 6300:    precedence[TOKarray] = PREC_primary;
     5534: 6301:    precedence[TOKindex] = PREC_primary;
        -: 6302:
     5534: 6303:    precedence[TOKaddress] = PREC_unary;
     5534: 6304:    precedence[TOKstar] = PREC_unary;
     5534: 6305:    precedence[TOKneg] = PREC_unary;
     5534: 6306:    precedence[TOKuadd] = PREC_unary;
     5534: 6307:    precedence[TOKnot] = PREC_unary;
     5534: 6308:    precedence[TOKtobool] = PREC_add;
     5534: 6309:    precedence[TOKtilde] = PREC_unary;
     5534: 6310:    precedence[TOKdelete] = PREC_unary;
     5534: 6311:    precedence[TOKnew] = PREC_unary;
     5534: 6312:    precedence[TOKcast] = PREC_unary;
        -: 6313:
     5534: 6314:    precedence[TOKpow] = PREC_pow;
        -: 6315:
     5534: 6316:    precedence[TOKmul] = PREC_mul;
     5534: 6317:    precedence[TOKdiv] = PREC_mul;
     5534: 6318:    precedence[TOKmod] = PREC_mul;
     5534: 6319:    precedence[TOKpow] = PREC_mul;
        -: 6320:
     5534: 6321:    precedence[TOKadd] = PREC_add;
     5534: 6322:    precedence[TOKmin] = PREC_add;
     5534: 6323:    precedence[TOKcat] = PREC_add;
        -: 6324:
     5534: 6325:    precedence[TOKshl] = PREC_shift;
     5534: 6326:    precedence[TOKshr] = PREC_shift;
     5534: 6327:    precedence[TOKushr] = PREC_shift;
        -: 6328:
     5534: 6329:    precedence[TOKlt] = PREC_rel;
     5534: 6330:    precedence[TOKle] = PREC_rel;
     5534: 6331:    precedence[TOKgt] = PREC_rel;
     5534: 6332:    precedence[TOKge] = PREC_rel;
     5534: 6333:    precedence[TOKunord] = PREC_rel;
     5534: 6334:    precedence[TOKlg] = PREC_rel;
     5534: 6335:    precedence[TOKleg] = PREC_rel;
     5534: 6336:    precedence[TOKule] = PREC_rel;
     5534: 6337:    precedence[TOKul] = PREC_rel;
     5534: 6338:    precedence[TOKuge] = PREC_rel;
     5534: 6339:    precedence[TOKug] = PREC_rel;
     5534: 6340:    precedence[TOKue] = PREC_rel;
     5534: 6341:    precedence[TOKin] = PREC_rel;
        -: 6342:
        -: 6343:#if 0
        -: 6344:    precedence[TOKequal] = PREC_equal;
        -: 6345:    precedence[TOKnotequal] = PREC_equal;
        -: 6346:    precedence[TOKidentity] = PREC_equal;
        -: 6347:    precedence[TOKnotidentity] = PREC_equal;
        -: 6348:#else
        -: 6349:    /* Note that we changed precedence, so that < and !=
have the same
        -: 6350:     * precedence. This change is in the parser, too.
        -: 6351:     */
     5534: 6352:    precedence[TOKequal] = PREC_rel;
     5534: 6353:    precedence[TOKnotequal] = PREC_rel;
     5534: 6354:    precedence[TOKidentity] = PREC_rel;
     5534: 6355:    precedence[TOKnotidentity] = PREC_rel;
        -: 6356:#endif
        -: 6357:
     5534: 6358:    precedence[TOKand] = PREC_and;
        -: 6359:
     5534: 6360:    precedence[TOKxor] = PREC_xor;
        -: 6361:
     5534: 6362:    precedence[TOKor] = PREC_or;
        -: 6363:
     5534: 6364:    precedence[TOKandand] = PREC_andand;
        -: 6365:
     5534: 6366:    precedence[TOKoror] = PREC_oror;
        -: 6367:
     5534: 6368:    precedence[TOKquestion] = PREC_cond;
        -: 6369:
     5534: 6370:    precedence[TOKassign] = PREC_assign;
     5534: 6371:    precedence[TOKconstruct] = PREC_assign;
     5534: 6372:    precedence[TOKblit] = PREC_assign;
     5534: 6373:    precedence[TOKaddass] = PREC_assign;
     5534: 6374:    precedence[TOKminass] = PREC_assign;
     5534: 6375:    precedence[TOKcatass] = PREC_assign;
     5534: 6376:    precedence[TOKmulass] = PREC_assign;
     5534: 6377:    precedence[TOKdivass] = PREC_assign;
     5534: 6378:    precedence[TOKmodass] = PREC_assign;
     5534: 6379:    precedence[TOKpowass] = PREC_assign;
     5534: 6380:    precedence[TOKshlass] = PREC_assign;
     5534: 6381:    precedence[TOKshrass] = PREC_assign;
     5534: 6382:    precedence[TOKushrass] = PREC_assign;
     5534: 6383:    precedence[TOKandass] = PREC_assign;
     5534: 6384:    precedence[TOKorass] = PREC_assign;
     5534: 6385:    precedence[TOKxorass] = PREC_assign;
        -: 6386:
     5534: 6387:    precedence[TOKcomma] = PREC_expr;
     5534: 6388:    precedence[TOKdeclaration] = PREC_expr;
     5534: 6389:}
        -: 6390:
        -: 6391:

September 06, 2010
On 3 September 2010 23:48, Walter Bright <walter at digitalmars.com> wrote:
> I built dmd with coverage analysis (gcov on linux) and ran the test suite. This is one of the result files - there are definitely gaps in the suite.

There were some very large gaps in interpret.c.
This isn't entirely a test suite issue, though -- there's a big block
of unreachable code. ForeachStatement::interpret() and
ForeachRangeStatement::interpret() should be completely deleted. Like
'while', they are turned into 'for' in the semantic pass.
I've made a few tests for the other major gaps. This is by no means
comprehensive, but it should nearly halve the number of uncovered
lines.

Add these tests to the end of interpret3.d
-------------

// Interpreter code coverage tests
int cov1(int a)
{
   a %= 15382;
   a /= 5;
   a = ~ a;
   bool c = (a==0);
   bool b = true && c;
   assert(b==0);
   b = false && c;
   assert(b==0);
   b = false || c;
   assert(b==0);
   a ^= 0x45349;
   a = ~ a;
   a &= 0xFF3F;
   a >>>= 1;
   a = a ^ 0x7393;
   a = a >> 1;
   a = a >>> 1;
   a = a | 0x010101;
   return a;
}
static assert(cov1(534564) == 71589);

int cov2()
{
    int i = 0;
    do{
        goto DOLABEL;
    DOLABEL:
        if (i!=0) {
            goto IFLABEL;
    IFLABEL:
            switch(i) {
            case 3:
                break;
            case 6:
                goto SWITCHLABEL;
    SWITCHLABEL:
                i = 27;
                goto case 3;
            }
            return i;
        }
        i = 6;
    } while(true);
    return 88; // unreachable
}

static assert(cov2()==27);

template CovTuple(T...)
{
  alias T CovTuple;
}

alias CovTuple!(int, long) TCov3;

int cov3(TCov3 t)
{
    TCov3 s;
    s = t;
    assert(s[0] == 1);
    assert(s[1] == 2);
    return 7;
}

static assert(cov3(1, 2) == 7);

template compiles(int T)
{
   bool compiles = true;
}

int badassert1(int z)
{
   assert(z == 5, "xyz");
   return 1;
}

int badslice1(int[] z)
{
  return z[0..3].length;
}

int badslice2(int[] z)
{
  return z[0..badassert1(1)].length;
}

int badslice3(int[] z)
{
  return z[badassert1(1)..2].length;
}

static assert(!is(typeof(compiles!(badassert1(67)))));
static assert(is(typeof(compiles!(badassert1(5)))));
static assert(!is(typeof(compiles!(badslice1([1,2])))));
static assert(!is(typeof(compiles!(badslice2([1,2])))));
static assert(!is(typeof(compiles!(badslice3([1,2,3])))));
September 06, 2010

Don Clugston wrote:
> On 3 September 2010 23:48, Walter Bright <walter at digitalmars.com> wrote:
> 
>> I built dmd with coverage analysis (gcov on linux) and ran the test suite.
>> This is one of the result files - there are definitely gaps in the suite.
>> 
>
> There were some very large gaps in interpret.c.
> This isn't entirely a test suite issue, though -- there's a big block
> of unreachable code. ForeachStatement::interpret() and
> ForeachRangeStatement::interpret() should be completely deleted. Like
> 'while', they are turned into 'for' in the semantic pass.
> I've made a few tests for the other major gaps. This is by no means
> comprehensive, but it should nearly halve the number of uncovered
> lines.
>
> Add these tests to the end of interpret3.d
>
> 

Thanks, done. I agree the unreachable code should be deleted or #ifdef'd out. One thing a coverage analyzer is good at is identifying unreachable cruft.
September 06, 2010
On 6 September 2010 22:19, Walter Bright <walter at digitalmars.com> wrote:
>
>
> Don Clugston wrote:
>>
>> On 3 September 2010 23:48, Walter Bright <walter at digitalmars.com> wrote:
>>
>>>
>>> I built dmd with coverage analysis (gcov on linux) and ran the test
>>> suite.
>>> This is one of the result files - there are definitely gaps in the suite.
>>>
>>
>> There were some very large gaps in interpret.c.
>> This isn't entirely a test suite issue, though -- there's a big block
>> of unreachable code. ForeachStatement::interpret() and
>> ForeachRangeStatement::interpret() should be completely deleted. Like
>> 'while', they are turned into 'for' in the semantic pass.
>> I've made a few tests for the other major gaps. This is by no means
>> comprehensive, but it should nearly halve the number of uncovered
>> lines.
>>
>> Add these tests to the end of interpret3.d
>>
>>
>
> Thanks, done. I agree the unreachable code should be deleted or #ifdef'd out. One thing a coverage analyzer is good at is identifying unreachable cruft.

Yes. Some of the coverage results are really interesting. Actually, I find coverage is fantastic for debugging, as well. How painful would it be to get a -cov dmd build on Windows?
September 06, 2010

Don Clugston wrote:
>
> How painful would it be to get a -cov dmd build on Windows?
>
> 

I'd have to fix dmc to do that!