Annotation of gcc/cp-spew.c, revision 1.1

1.1     ! root        1: /* Type Analyzer for GNU C++.
        !             2:    Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
        !             3:    Hacked... nay, bludgeoned... by Mark Eichin ([email protected])
        !             4: 
        !             5: This file is part of GNU CC.
        !             6: 
        !             7: GNU CC is free software; you can redistribute it and/or modify
        !             8: it under the terms of the GNU General Public License as published by
        !             9: the Free Software Foundation; either version 2, or (at your option)
        !            10: any later version.
        !            11: 
        !            12: GNU CC is distributed in the hope that it will be useful,
        !            13: but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            15: GNU General Public License for more details.
        !            16: 
        !            17: You should have received a copy of the GNU General Public License
        !            18: along with GNU CC; see the file COPYING.  If not, write to
        !            19: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
        !            20: 
        !            21: 
        !            22: /* This file is the type analyzer for GNU C++.  */
        !            23: 
        !            24: #include "config.h"
        !            25: #include <stdio.h>
        !            26: #include "input.h"
        !            27: #include "tree.h"
        !            28: #include "cp-lex.h"
        !            29: #include "cp-parse.h"
        !            30: #include "cp-tree.h"
        !            31: #include "flags.h"
        !            32: #include "obstack.h"
        !            33: #include <assert.h>
        !            34: 
        !            35: /* This takes a token stream that hasn't decided much about types and
        !            36:    tries to figure out as much as it can, with excessive lookahead and
        !            37:    backtracking. */
        !            38: 
        !            39: /* fifo of tokens recognized and available to parser. */
        !            40: struct token  {
        !            41:   /* The values for YYCHAR will fit in a short.  */
        !            42:   short                yychar;
        !            43:   short                end_of_file;
        !            44:   YYSTYPE      yylval;
        !            45: };
        !            46: 
        !            47: static int do_aggr ();
        !            48: static struct token frob_identifier ();
        !            49: static struct token hack_scope ();
        !            50: static tree hack_ptype ();
        !            51: static tree hack_more_ids ();
        !            52: 
        !            53: /* From cp-lex.c: */
        !            54: /* the declaration found for the last IDENTIFIER token read in.
        !            55:    yylex must look this up to detect typedefs, which get token type TYPENAME,
        !            56:    so it is left around in case the identifier is not a typedef but is
        !            57:    used in a context which makes it a reference to a variable.  */
        !            58: extern tree lastiddecl;                /* let our brains leak out here too */
        !            59: extern int     yychar;         /*  the lookahead symbol                */
        !            60: extern YYSTYPE yylval;         /*  the semantic value of the           */
        !            61:                                /*  lookahead symbol                    */
        !            62: extern int end_of_file;
        !            63: 
        !            64: struct obstack token_obstack;
        !            65: int first_token;
        !            66:   
        !            67: /* #define SPEW_DEBUG */
        !            68: #ifdef SPEW_DEBUG
        !            69: static int spew_debug = 0;
        !            70: static int yylex_ctr = 0;
        !            71: #endif
        !            72: 
        !            73: static char follows_typename[END_OF_SAVED_INPUT];
        !            74: static char follows_identifier[END_OF_SAVED_INPUT];
        !            75: 
        !            76: /* Initialize token_obstack. Called once, from init_lex.  */
        !            77: void
        !            78: init_spew ()
        !            79: {
        !            80:   static char *chars_following_identifier = ".+-|/%^!?:";
        !            81:   short *ps;
        !            82:   char *pc;
        !            83:   static short toks_follow_ids[] =
        !            84:     { POINTSAT_LEFT_RIGHT, ASSIGN, RANGE, OROR, ANDAND, MIN_MAX, EQCOMPARE,
        !            85:       ARITHCOMPARE, LSHIFT, RSHIFT, UNARY, PLUSPLUS, MINUSMINUS, POINTSAT,
        !            86:       POINTSAT_STAR, DOT_STAR, CONSTANT, STRING, SIZEOF, ENUM, IF,
        !            87:       ELSE, WHILE, DO, FOR, SWITCH, CASE, DEFAULT, BREAK, CONTINUE,
        !            88:       RETURN, GOTO, ASM, TYPEOF, ALIGNOF, HEADOF, CLASSOF, ATTRIBUTE,
        !            89:       AGGR, VISSPEC, DELETE, RAISE, RERAISE, TRY, EXCEPT, CATCH,
        !            90:       THROW, ANSI_TRY, ANSI_THROW, EXTERN_LANG_STRING, ALL,
        !            91:       END_OF_SAVED_INPUT, -1 };
        !            92:   static char *chars_following_typename = "(";
        !            93:   static short toks_follow_types[] =
        !            94:     { IDENTIFIER, TYPENAME, SCOPED_TYPENAME, SCSPEC, TYPESPEC, TYPE_QUAL,
        !            95:       ELLIPSIS, THIS, OPERATOR, DYNAMIC, TEMPLATE, SCOPE, START_DECLARATOR,
        !            96:       TYPENAME_COLON, PAREN_STAR_PAREN, TYPENAME_ELLIPSIS, PTYPENAME,
        !            97:       PRE_PARSED_FUNCTION_DECL, PRE_PARSED_CLASS_DECL, -1 };
        !            98: 
        !            99:   gcc_obstack_init(&token_obstack);
        !           100: 
        !           101:   /* Initialize the arrays saying what tokens are definitely
        !           102:      (or possibly) valid following typenames and identifiers.  */
        !           103:   while (*chars_following_identifier)
        !           104:     follows_identifier[*chars_following_identifier++] = 1;
        !           105:   for (ps = toks_follow_ids; *ps != -1; ps++)
        !           106:     follows_identifier[*ps] = 1;
        !           107:   for (ps = toks_follow_types; *ps != -1; ps++)
        !           108:     follows_typename[*ps] = 1;
        !           109: }
        !           110: 
        !           111: #ifdef SPEW_DEBUG
        !           112: /* Use functions for debugging...  */
        !           113: 
        !           114: /* Return the number of tokens available on the fifo. */
        !           115: static int
        !           116: num_tokens ()
        !           117: {
        !           118:   return (obstack_object_size(&token_obstack)/sizeof(struct token))
        !           119:     - first_token;
        !           120: }
        !           121: 
        !           122: /* Fetch the token N down the line from the head of the fifo. */
        !           123: static struct token*
        !           124: nth_token (n)
        !           125:      int n;
        !           126: {
        !           127:   /* could just have this do slurp_ implicitly, but this way is easier
        !           128:    * to debug... */
        !           129:   assert (n < num_tokens());
        !           130:   return ((struct token*)obstack_base(&token_obstack))+n+first_token;
        !           131: }
        !           132: 
        !           133: /* Add a token to the token fifo. */
        !           134: static void
        !           135: add_token (t)
        !           136:      struct token* t;
        !           137: {
        !           138:   obstack_grow(&token_obstack,t,sizeof (struct token));
        !           139: }
        !           140: 
        !           141: /* Consume the next token out of the fifo.  */
        !           142: static void
        !           143: consume_token()
        !           144: {
        !           145:   if (num_tokens() == 1)
        !           146:     {
        !           147:       obstack_free(&token_obstack, obstack_base (&token_obstack));
        !           148:       first_token = 0;
        !           149:     }
        !           150:   else
        !           151:     first_token++;
        !           152: }
        !           153: 
        !           154: #else
        !           155: /* ...otherwise use macros.  */
        !           156: 
        !           157: #define num_tokens() \
        !           158:   ((obstack_object_size(&token_obstack)/sizeof(struct token)) - first_token)
        !           159: 
        !           160: #define nth_token(N) \
        !           161:   (((struct token*)obstack_base(&token_obstack))+(N)+first_token)
        !           162: 
        !           163: #define add_token(T) obstack_grow(&token_obstack, (T), sizeof (struct token))
        !           164: 
        !           165: #define consume_token() \
        !           166:   (num_tokens() == 1                                                   \
        !           167:    ? (obstack_free (&token_obstack, obstack_base (&token_obstack)),    \
        !           168:       (first_token = 0))                                               \
        !           169:    : first_token++)
        !           170: #endif
        !           171: 
        !           172: /* Pull in enough tokens from real_yylex that the queue is N long.  */
        !           173: 
        !           174: static void
        !           175: scan_tokens (n)
        !           176:      int n;
        !           177: {
        !           178:   int i;
        !           179:   struct token *tmp;
        !           180: 
        !           181:   /* We cannot read past certain tokens, so make sure we don't.  */
        !           182:   i = num_tokens ();
        !           183:   if (i > n)
        !           184:     return;
        !           185:   while (i-- > 0)
        !           186:     {
        !           187:       tmp = nth_token (i);
        !           188:       /* Never read past these characters: they might separate
        !           189:         the current input stream from one we save away later.  */
        !           190:       if (tmp->yychar == '{' || tmp->yychar == ':')
        !           191:        goto pad_tokens;
        !           192:     }
        !           193: 
        !           194:   while (num_tokens() <= n)
        !           195:     {
        !           196:       obstack_blank(&token_obstack,sizeof (struct token));
        !           197:       tmp = ((struct token *)obstack_next_free (&token_obstack))-1;
        !           198:       tmp->yychar = real_yylex();
        !           199:       tmp->end_of_file = end_of_file;
        !           200:       tmp->yylval = yylval;
        !           201:       end_of_file = 0;
        !           202:       if (tmp->yychar == '{'
        !           203:          || tmp->yychar == ':'
        !           204:          || tmp->yychar == ';')
        !           205:        {
        !           206:        pad_tokens:
        !           207:          while (num_tokens () <= n)
        !           208:            {
        !           209:              obstack_blank(&token_obstack,sizeof (struct token));
        !           210:              tmp = ((struct token *)obstack_next_free (&token_obstack))-1;
        !           211:              tmp->yychar = EMPTY;
        !           212:              tmp->end_of_file = 0;
        !           213:            }
        !           214:        }
        !           215:     }
        !           216: }
        !           217: 
        !           218: /* Create room for N tokens at the front of the fifo.  This is used
        !           219:    to insert new tokens into the stream ahead of the current token.  */
        !           220: 
        !           221: static void
        !           222: shift_tokens (n)
        !           223:      int n;
        !           224: {
        !           225:   if (first_token >= n)
        !           226:     first_token -= n;
        !           227:   else
        !           228:     {
        !           229:       int old_token_count = num_tokens ();
        !           230:       char *tmp;
        !           231: 
        !           232:       obstack_blank (&token_obstack, (n-first_token) * sizeof (struct token));
        !           233:       tmp = (char *)alloca ((num_tokens () + (n-first_token))
        !           234:                            * sizeof (struct token));
        !           235:       /* This move does not rely on the system being able to handle
        !           236:         overlapping moves.  */
        !           237:       bcopy (nth_token (0), tmp, old_token_count * sizeof (struct token));
        !           238:       bcopy (tmp, nth_token (n), old_token_count * sizeof (struct token));
        !           239:       first_token = 0;
        !           240:     }
        !           241: }
        !           242: 
        !           243: int
        !           244: probe_obstack (h, obj, nlevels)
        !           245:      struct obstack *h;
        !           246:      tree obj;
        !           247:      unsigned int nlevels;
        !           248: {
        !           249:   register struct _obstack_chunk*  lp; /* below addr of any objects in this chunk */
        !           250:   register struct _obstack_chunk*  plp;        /* point to previous chunk if any */
        !           251: 
        !           252:   lp = (h)->chunk;
        !           253:   /* We use >= rather than > since the object cannot be exactly at
        !           254:      the beginning of the chunk but might be an empty object exactly
        !           255:      at the end of an adjacent chunk. */
        !           256:   for (; nlevels > 0 && lp != 0 && ((tree)lp >= obj || (tree)lp->limit < obj);
        !           257:        nlevels -= 1)
        !           258:     {
        !           259:       plp = lp->prev;
        !           260:       lp = plp;      
        !           261:     }
        !           262:   return nlevels > 0 && lp != 0;
        !           263: }
        !           264: 
        !           265: /* from cp-lex.c: */
        !           266: /* Value is 1 if we should try to make the next identifier look like a
        !           267:    typename (when it may be a local variable or a class variable).
        !           268:    Value is 0 if we treat this name in a default fashion.
        !           269:    Value is -1 if we must not see a type name.  */
        !           270: extern int looking_for_typename;
        !           271: 
        !           272: extern struct obstack *current_obstack, *saveable_obstack;
        !           273: 
        !           274: int
        !           275: yylex()
        !           276: {
        !           277:   struct token tmp_token;
        !           278:   tree t2;
        !           279:   tree dk, trrr;
        !           280: 
        !           281:  retry:
        !           282: #ifdef SPEW_DEBUG
        !           283:   if (spew_debug)
        !           284:   {
        !           285:     yylex_ctr ++;
        !           286:     fprintf(stderr, "\t\t## %d ##",yylex_ctr);
        !           287:   }
        !           288: #endif
        !           289:   
        !           290:   /* if we've got tokens, send them */
        !           291:   if (num_tokens())
        !           292:     {
        !           293:       tree tmp;
        !           294:       tmp_token= *nth_token(0);
        !           295: 
        !           296:       /* TMP_TOKEN.YYLVAL.TTYPE may have been allocated on the wrong obstack.
        !           297:         If we don't find it in CURRENT_OBSTACK's current or immediately
        !           298:         previous chunk, assume it was and copy it to the current obstack.  */
        !           299:       if ((tmp_token.yychar == CONSTANT
        !           300:           || tmp_token.yychar == STRING)
        !           301:          && ! TREE_PERMANENT (tmp_token.yylval.ttype)
        !           302:          && ! probe_obstack (current_obstack, tmp_token.yylval.ttype, 2)
        !           303:          && ! probe_obstack (saveable_obstack, tmp_token.yylval.ttype, 2))
        !           304:        tmp_token.yylval.ttype = copy_node (tmp_token.yylval.ttype);
        !           305:     }
        !           306:   else
        !           307:     {
        !           308:       /* if not, grab the next one and think about it */
        !           309:       tmp_token.yychar = real_yylex();
        !           310:       tmp_token.yylval = yylval;
        !           311:       add_token(&tmp_token);
        !           312:     }
        !           313: 
        !           314:   /* many tokens just need to be returned. At first glance, all we
        !           315:    * have to do is send them back up, but some of them are needed to
        !           316:    * figure out local context. */
        !           317:   switch(tmp_token.yychar)
        !           318:     {
        !           319:     case EMPTY:
        !           320:       /* This is a lexical no-op.  */
        !           321:       consume_token ();
        !           322: #ifdef SPEW_DEBUG    
        !           323:       if (spew_debug)
        !           324:        debug_yychar (tmp_token.yychar);
        !           325: #endif
        !           326:       goto retry;
        !           327: 
        !           328:     case IDENTIFIER:
        !           329:       /* Note: this calls arbitrate_lookup.  */
        !           330:       trrr = lookup_name (tmp_token.yylval.ttype, -1);
        !           331:       if (trrr)
        !           332:        {
        !           333:          tmp_token.yychar = identifier_type (trrr);
        !           334:          switch (tmp_token.yychar)
        !           335:            {
        !           336:            case TYPENAME:
        !           337:              lastiddecl = IDENTIFIER_TYPEDECL_VALUE (tmp_token.yylval.ttype);
        !           338:              break;
        !           339:            case IDENTIFIER:
        !           340:              lastiddecl = trrr;
        !           341:              break;
        !           342:            case PTYPENAME:
        !           343:              /* This is for cases like
        !           344:                    template<class A> X<A>::operator[] ...
        !           345:                 since "X" is (presumably) a PTYPENAME; we might want to
        !           346:                 avoid seeing the entire thing as a type name, but X<A>
        !           347:                 must be one.
        !           348: 
        !           349:                 It might not work right if the thing after the ::
        !           350:                 can be a typename nested in X<A>, but I don't think the
        !           351:                 PT code would be up to dealing with that anyways.  --KR  */
        !           352:              if (looking_for_typename == -1)
        !           353:                {
        !           354:                  scan_tokens (2);
        !           355:                  if (nth_token(1)->yychar == '<')
        !           356:                    looking_for_typename = 0;
        !           357:                }
        !           358:              break;
        !           359:            default:
        !           360:              abort ();
        !           361:            }
        !           362:        }
        !           363:       else
        !           364:        lastiddecl = trrr;
        !           365:       /* and fall through to... */
        !           366:     case TYPENAME:
        !           367:     case PTYPENAME:
        !           368:       /* if (new_token) add_token (&tmp_token); */
        !           369:       *nth_token(0) = tmp_token;
        !           370:       tmp_token = frob_identifier ();
        !           371:       if (looking_for_typename < 0)
        !           372:        {
        !           373:          tmp_token.yychar = IDENTIFIER;
        !           374:          lastiddecl = 0;
        !           375:          looking_for_typename = 0;
        !           376:        }
        !           377:       else if (lastiddecl && TREE_CODE (lastiddecl) == TYPE_DECL)
        !           378:        {
        !           379:          scan_tokens (2);
        !           380:          if (nth_token(0)->yychar == IDENTIFIER
        !           381:              && nth_token (1)->yychar != SCOPE)
        !           382:            looking_for_typename = -1;
        !           383:          else
        !           384:            looking_for_typename = 0;
        !           385:          goto finish_typename_processing;
        !           386:        }
        !           387:       else
        !           388:        looking_for_typename = 0;
        !           389:       break;
        !           390: 
        !           391:     case TYPESPEC:
        !           392:     case SCSPEC:
        !           393:       consume_token ();
        !           394:     finish_typename_processing:
        !           395:       /* Now see if we should insert a START_DECLARATOR token.
        !           396:          Here are the cases caught:
        !           397: 
        !           398:         typespec ( * ID ) (    // ptr to function
        !           399:         typespec ( & ID ) (    // ref to function
        !           400:         typespec ( * ID ) [    // array of pointers
        !           401:         typespec ( & ID ) [    // array of references
        !           402: 
        !           403:         This is a terrible kludge.  */
        !           404: 
        !           405:       scan_tokens (2);
        !           406:       if (nth_token (0)->yychar == '('
        !           407:          && (nth_token (1)->yychar == '*'
        !           408:              || nth_token (1)->yychar == '&'))
        !           409:        {
        !           410:          scan_tokens (5);
        !           411:          if (nth_token (3)->yychar == ')'
        !           412:              && (nth_token (4)->yychar == '('
        !           413:                  || nth_token (4)->yychar == '['
        !           414:                  || nth_token (4)->yychar == LEFT_RIGHT)
        !           415:              && (nth_token (2)->yychar == IDENTIFIER
        !           416:                  || nth_token (2)->yychar == TYPENAME))
        !           417:            {
        !           418:              shift_tokens (1);
        !           419:              nth_token (0)->yychar = START_DECLARATOR;
        !           420:            }
        !           421:        }
        !           422:       break;
        !           423: 
        !           424: #if 0
        !           425:     case '(':
        !           426:       /* Handle casts.  We are looking for one of:
        !           427:          `( TYPENAME' followed by `)', or
        !           428:         `( TYPENAME *' followed by one of `[,*,&,)', or
        !           429:         `( TYPENAME &' followed by one of `[,*,&,)', or
        !           430:         `( TYPENAME [' followed by `]'.  We are punting
        !           431:         generality on scanning casts to array types.  */
        !           432:       scan_tokens (4);
        !           433:       if (nth_token (1)->yychar == IDENTIFIER)
        !           434:        {
        !           435:          tree type = identifier_typedecl_value (nth_token (1)->yylval.ttype);
        !           436:          if (type)
        !           437:            switch (nth_token (2)->yychar)
        !           438:              {
        !           439:              default:
        !           440:                break;
        !           441:              }
        !           442:        }
        !           443:       break;
        !           444: 
        !           445:     case SCOPE:
        !           446:       /* if (new_token) add_token (&tmp_token); */
        !           447:       *nth_token(0) = tmp_token;
        !           448:       tmp_token = hack_scope ();
        !           449:       break;
        !           450: #endif
        !           451: 
        !           452:     case AGGR:
        !           453:       *nth_token(0) = tmp_token;
        !           454:       do_aggr ();
        !           455:       /* fall through to output... */
        !           456:     case ENUM:
        !           457:       /* Set this again, in case we are rescanning.  */
        !           458:       looking_for_typename = 1;
        !           459:       /* fall through... */
        !           460:     default:
        !           461: #ifdef SPEW_DEBUG    
        !           462:       if (spew_debug)
        !           463:        debug_yychar(tmp_token.yychar);
        !           464: #endif
        !           465:       consume_token();
        !           466:       yylval = tmp_token.yylval;
        !           467:       yychar = tmp_token.yychar;
        !           468:       end_of_file = tmp_token.end_of_file;
        !           469:       return tmp_token.yychar;
        !           470:     }
        !           471: 
        !           472:   if (tmp_token.yychar == SCOPED_TYPENAME)
        !           473:     {
        !           474: #if 0
        !           475:       t2 = resolve_scope_to_name (NULL_TREE, tmp_token.yylval.ttype);
        !           476:       if (t2)
        !           477:        {
        !           478:          tmp_token.yylval.ttype = t2;
        !           479:          tmp_token.yychar = TYPENAME;
        !           480:        }
        !           481:       else
        !           482:        {
        !           483:          /* unwind? */
        !           484:        }
        !           485:     }
        !           486:   else
        !           487:     {
        !           488:       /* couldn't get here, as is... */
        !           489: #endif
        !           490:       tmp_token.yychar = TYPENAME;
        !           491:     }
        !           492: 
        !           493:   yylval = tmp_token.yylval;
        !           494:   yychar = tmp_token.yychar;
        !           495:   end_of_file = tmp_token.end_of_file;
        !           496: #ifdef SPEW_DEBUG    
        !           497:   if (spew_debug)
        !           498:     debug_yychar(yychar);
        !           499: #endif
        !           500: /*  consume_token(); */ /* already eaten by frob_identifier?... */
        !           501:   return yychar;
        !           502: }
        !           503: 
        !           504: /* token[0] == AGGR (struct/union/enum)
        !           505:  * thus, token[1] is either a TYPENAME or a TYPENAME_DEFN
        !           506:  * if token[2] == '{' or ':' then it's TYPENAME_DEFN
        !           507:  */
        !           508: static int
        !           509: do_aggr ()
        !           510: {
        !           511:   int yc1, yc2;
        !           512:   
        !           513:   scan_tokens (2);
        !           514:   yc1 = nth_token (1)->yychar;
        !           515:   if (yc1 != TYPENAME && yc1 != IDENTIFIER && yc1 != PTYPENAME)
        !           516:     return 0;
        !           517:   yc2 = nth_token (2)->yychar;
        !           518:   if (yc2 == '{' || yc2 == ':')
        !           519:     {
        !           520:       switch (yc1)
        !           521:        {
        !           522:        case TYPENAME:
        !           523:          nth_token (1)->yychar = TYPENAME_DEFN;
        !           524:          break;
        !           525:        case PTYPENAME:
        !           526:          nth_token (1)->yychar = PTYPENAME_DEFN;
        !           527:          break;
        !           528:        case IDENTIFIER:
        !           529:          nth_token (1)->yychar = IDENTIFIER_DEFN;
        !           530:          break;
        !           531:        default:
        !           532:          abort ();
        !           533:        }
        !           534:     }
        !           535:   return 0;
        !           536: }  
        !           537: 
        !           538: static struct token
        !           539: frob_identifier ()
        !           540: {
        !           541:   /* we could have a type, if it is followed by :: (if so, suck it all up); */
        !           542:   /* we could have a ptypename; */
        !           543:   /* we could have a normal identifier. */
        !           544:   tree t1;
        !           545:   struct token rt;
        !           546:   
        !           547:   scan_tokens(1);
        !           548:   rt = *nth_token(0);
        !           549: 
        !           550: #if 0
        !           551:   if (nth_token(1)->yychar == '<')
        !           552:     {
        !           553:       t1 = hack_ptype();       /* suck up the whole thing */
        !           554:       if (t1)
        !           555:        {
        !           556:          rt.yylval.ttype = t1;
        !           557:          rt.yychar = TYPENAME;
        !           558:          *nth_token(0) = rt;
        !           559:        }
        !           560:       /* else fall out bottom */
        !           561:     }  
        !           562: #endif
        !           563: 
        !           564:   if (nth_token(1)->yychar == SCOPE)
        !           565:     {
        !           566:       t1 = hack_more_ids(0);
        !           567:       if (t1 && TREE_CODE(t1) == SCOPE_REF)
        !           568:        {
        !           569:          rt.yylval.ttype = t1;
        !           570:          rt.yychar = SCOPED_TYPENAME ;
        !           571:          return rt;
        !           572:        }
        !           573:       else
        !           574:        {
        !           575:          /* deal with types (enums?) in classes... */
        !           576:          struct token *tok;
        !           577:          tree ta, tb;
        !           578:          scan_tokens(3);
        !           579: 
        !           580:          /* Have to check for a type conversion operator
        !           581:             to a nested type.  */
        !           582:          if (nth_token (2)->yychar == OPERATOR)
        !           583:            tok = nth_token (3);
        !           584:          else
        !           585:            tok = nth_token(2);
        !           586: 
        !           587:          if (tok->yychar == IDENTIFIER || tok->yychar == TYPENAME)
        !           588:            {
        !           589:              ta = build_parse_node (SCOPE_REF,
        !           590:                                     nth_token(0)->yylval.ttype,
        !           591:                                     tok->yylval.ttype);
        !           592:              tb = resolve_scope_to_name (NULL_TREE, ta);
        !           593: 
        !           594:              if (tb)
        !           595:                {
        !           596:                  if (nth_token (2)->yychar == OPERATOR)
        !           597:                    {
        !           598:                      /* Have to keep these tokens around
        !           599:                         so we can finish parsing the declaration.
        !           600:                         What do we do for
        !           601: 
        !           602:                         int foo::operator bar::baz (); 
        !           603: 
        !           604:                         where bar is a nested class in foo?  */
        !           605:                      nth_token (3)->yychar = TYPENAME;
        !           606:                      nth_token (3)->yylval.ttype = tb;
        !           607:                    }
        !           608:                  else
        !           609:                    {
        !           610:                      consume_token (); /* base type */
        !           611:                      consume_token (); /* SCOPE */
        !           612:                      consume_token (); /* member type */
        !           613:                      rt.yychar = TYPENAME;
        !           614:                      rt.yylval.ttype = tb;
        !           615:                      rt.end_of_file = tok->end_of_file;
        !           616:                      return rt;
        !           617:                    }
        !           618:                  
        !           619:                }
        !           620:            }      
        !           621:          /* else fall out bottom */
        !           622:        }
        !           623:     }
        !           624:             
        !           625:   consume_token();
        !           626:   return rt;
        !           627: }
        !           628: 
        !           629: /* When this function is called, nth_token(0) is the current
        !           630:    token we are scanning.  This means that the next token we'll
        !           631:    scan is nth_token (1).  Usually the next token we'll scan
        !           632:    is nth_token (0) (and the current token is in [yylval,yychar]).  */
        !           633: tree
        !           634: arbitrate_lookup (name, exp_decl, type_decl)
        !           635:      tree name, exp_decl, type_decl;
        !           636: {
        !           637:   int ch;
        !           638: 
        !           639:   scan_tokens (3);
        !           640:   ch = nth_token (1)->yychar;
        !           641: 
        !           642:   switch (ch)
        !           643:     {
        !           644:     case '(':
        !           645:     case LEFT_RIGHT:
        !           646:       /* If we guessed wrong here, `build_functional_cast' can fix it.  */
        !           647:       return type_decl;
        !           648: 
        !           649:     case '=':
        !           650:       if (global_bindings_p ())
        !           651:        /* Probably a default parameter.  */
        !           652:        return type_decl;
        !           653:       /* Probably not an initialization.  */
        !           654:       return exp_decl;
        !           655: 
        !           656:     case '[':
        !           657:       /* This needs special help because an expression inside the
        !           658:         brackets means nothing.  */
        !           659:       {
        !           660:        int i;
        !           661: 
        !           662:        for (i = 0; i < 42; i++)
        !           663:          {
        !           664:            int ith_yychar;
        !           665: 
        !           666:            scan_tokens (3+i);
        !           667:            ith_yychar = nth_token (2+i)->yychar;
        !           668: 
        !           669:            /* If we hit an undefined identifier, assume
        !           670:               the decl in aribtration is its type specifier.  */
        !           671:            if (ith_yychar == IDENTIFIER
        !           672:                && lookup_name (nth_token (2+i)->yylval.ttype, 0) == 0)
        !           673:              return type_decl;
        !           674:            else if (ith_yychar == ']')
        !           675:              {
        !           676:                /* There are only a few things we expect after a ']'
        !           677:                   in a declarator.  */
        !           678:                i += 1;
        !           679:                scan_tokens (4+i);
        !           680:                ith_yychar = nth_token (2+i)->yychar;
        !           681: 
        !           682:                /* These are inconclusive.  */
        !           683:                if (ith_yychar == LEFT_RIGHT
        !           684:                    || ith_yychar == '('
        !           685:                    || ith_yychar == '['
        !           686:                    || ith_yychar == ',')
        !           687:                  continue;
        !           688:                /* stmt or decl?  We'll probably never know.  */
        !           689:                else if (ith_yychar == ';')
        !           690:                  goto warn_ambiguous;
        !           691: 
        !           692:                if (ith_yychar == '=')
        !           693:                  {
        !           694:                    if (nth_token (3+i)->yychar == '{')
        !           695:                      return type_decl;
        !           696:                    continue;
        !           697:                  }
        !           698: 
        !           699:                /* Whatever it is, it looks like we're processing an expr.  */
        !           700:                return exp_decl;
        !           701:              }
        !           702:          }
        !           703:        goto warn_ambiguous;
        !           704:       }
        !           705: 
        !           706:     case ',':
        !           707:     case ';':
        !           708:     case '&':
        !           709:     case '<':
        !           710:     case '*':
        !           711:     case ']':
        !           712:     case ')':
        !           713:     case '>':
        !           714:       /* see if the next token looks like it wants to be part
        !           715:         of a declaration list or an expression list.  */
        !           716:       {
        !           717:        int i;
        !           718: 
        !           719:        /* Some heuristics: if we are inside a function definition,
        !           720:           prefer the local declaration.  */
        !           721:        if (! global_bindings_p ())
        !           722:          {
        !           723:            if (IDENTIFIER_LOCAL_VALUE (name) == exp_decl)
        !           724:              return exp_decl;
        !           725:            if (IDENTIFIER_LOCAL_VALUE (name) != type_decl
        !           726:                && IDENTIFIER_CLASS_VALUE (name) == exp_decl)
        !           727:              return exp_decl;
        !           728:          }
        !           729:        /* If these symbols follow in a list, we know it's a list of
        !           730:           expressions.  */
        !           731:        if (follows_identifier[nth_token (2)->yychar])
        !           732:          return exp_decl;
        !           733: 
        !           734:        /* Look for the first identifier or other distinguishing token
        !           735:           we find in the next several tokens.  */
        !           736:        for (i = 0; i < 42; i++)
        !           737:          {
        !           738:            int ith_yychar;
        !           739: 
        !           740:            scan_tokens (3+i);
        !           741:            ith_yychar = nth_token (2+i)->yychar;
        !           742: 
        !           743:            if (ith_yychar == IDENTIFIER)
        !           744:              {
        !           745:                tree as_type = lookup_name (nth_token (2+i)->yylval.ttype, 1);
        !           746:                if (as_type && TREE_CODE (as_type) != TYPE_DECL)
        !           747:                  return exp_decl;
        !           748:                /* An undeclared identifier or a typename means we're
        !           749:                   probably looking at a typename.  */
        !           750:                return type_decl;
        !           751:              }
        !           752:            else if (ith_yychar == EMPTY
        !           753:                     || follows_identifier[ith_yychar])
        !           754:              return exp_decl;
        !           755:            else if (follows_typename[ith_yychar])
        !           756:              return type_decl;
        !           757:            /* stmt or decl?  We'll probably never know.  */
        !           758:            else if (ith_yychar == ';')
        !           759:              goto warn_ambiguous;
        !           760:          }
        !           761:        goto warn_ambiguous;
        !           762:       }
        !           763: 
        !           764:     default:
        !           765:       if (follows_identifier[ch])
        !           766:        return exp_decl;
        !           767:       if (follows_typename[ch])
        !           768:        return type_decl;
        !           769: 
        !           770:       /* Fall through...  */
        !           771:     warn_ambiguous:
        !           772:       warning ("name `%s' could be type or expression; compiler assuming type",
        !           773:               IDENTIFIER_POINTER (DECL_NAME (type_decl)));
        !           774:       return type_decl;
        !           775:     }
        !           776: }
        !           777: 
        !           778: /* now returns decl_node */
        !           779: 
        !           780: #if 0
        !           781: static tree
        !           782: hack_ptype()
        !           783: {
        !           784:   /* when we get here, we know that [0] is a ptype and [1] is '<'.
        !           785:    * now we loop over simple parameters. */
        !           786:   struct token this_param;
        !           787:   int n = 2;
        !           788:   tree tplist = 0;
        !           789:   tree tc;
        !           790:   scan_tokens(n+1);
        !           791:   
        !           792:   while((this_param = *nth_token(n)).yychar != '>')
        !           793:     {
        !           794:       /* if it is a type, add it to the list */
        !           795:       tree thistype;
        !           796:     
        !           797:       switch(this_param.yychar)
        !           798:        {
        !           799:        case IDENTIFIER:
        !           800:        case TYPENAME:
        !           801:        case TYPESPEC:
        !           802:          break;
        !           803:        default:
        !           804:          return 0;
        !           805:        }
        !           806: 
        !           807:       thistype = this_param.yylval.ttype;
        !           808:       thistype = lookup_name(thistype, 1);
        !           809:       thistype = TREE_TYPE (thistype);
        !           810:         
        !           811:       if (tplist)
        !           812:        tplist = chainon (tplist, build_tree_list (NULL_TREE, thistype));
        !           813:       else
        !           814:        tplist = build_tree_list(NULL_TREE, thistype);
        !           815:     
        !           816:     
        !           817:       /* then suck up the comma */
        !           818:       n++;
        !           819:       scan_tokens(n+1);
        !           820:       this_param = *nth_token(n);
        !           821:       if (this_param.yychar == ',')
        !           822:        {
        !           823:          n++;
        !           824:          scan_tokens(n+1);
        !           825:          continue;
        !           826:        }
        !           827:       if (this_param.yychar == '>')
        !           828:        break;
        !           829:       return 0;
        !           830:     }
        !           831: 
        !           832:   /* once we're done, lookup_template_class -> identifier */
        !           833:   tc = lookup_template_class (nth_token(0)->yylval.ttype,tplist);
        !           834:   /* then lookup_name on that to get a type, if there is one */
        !           835:   tc = lookup_name (tc, 1);
        !           836:   if (tc)
        !           837:     {
        !           838:       int i;
        !           839:       /* don't actually eat the trailing '>'... we can replace it! */
        !           840:       for (i=0; i<n; i++)
        !           841:        consume_token();
        !           842:       /*    IDENTIFER_TYPE_VALUE (DECL_NAME (tc)) = */
        !           843:       return DECL_NAME (tc);
        !           844:     }
        !           845:   return NULL_TREE;
        !           846: }
        !           847: #endif
        !           848: 
        !           849: static tree
        !           850: hack_more_ids (n)
        !           851:      int n;
        !           852: {
        !           853:   /*
        !           854:    * The recursion should probably do consume_tokens(), since once we've started
        !           855:    * down an IDENTIFIER SCOPE ... chain, we don't need to back-track - we just
        !           856:    * get as much as we can, make SCOPE_REF's out of it, and return it.
        !           857:    */
        !           858:   struct token this_iter, this2_iter;
        !           859:   int tmp_y;
        !           860:   
        !           861:   scan_tokens(n+1);
        !           862:   this_iter = *nth_token(n);
        !           863: 
        !           864:   tmp_y = nth_token(n)->yychar;
        !           865:   if (tmp_y == IDENTIFIER || tmp_y == TYPENAME)
        !           866:     {
        !           867:       scan_tokens(n+2+2);
        !           868:       if (nth_token(n+1)->yychar == SCOPE)
        !           869:        {
        !           870:          if (nth_token(n+1+2)->yychar == SCOPE)
        !           871:            {
        !           872:              tree hmi;
        !           873:        
        !           874:              consume_token();  /* last IDENTIFIER (this_iter) */
        !           875:              consume_token();  /* last SCOPE */
        !           876:              this2_iter = *nth_token(n);
        !           877:        
        !           878:              hmi = hack_more_ids (n);
        !           879:        
        !           880:              if (hmi)
        !           881:                return build_parse_node (SCOPE_REF, this_iter.yylval.ttype, hmi);
        !           882:              consume_token(); /* last IDENTIFIER (this2_iter) */
        !           883:              return build_parse_node (SCOPE_REF, this_iter.yylval.ttype,
        !           884:                                       this2_iter.yylval.ttype);
        !           885:            }
        !           886:          else
        !           887:            {
        !           888:              /* consume_token();       */      /* last IDENTIFIER */
        !           889:              /* leave whatever else we got */
        !           890:              /* return this_iter.yylval.ttype; */
        !           891:              return NULL_TREE;
        !           892:            }
        !           893:        }
        !           894:     }
        !           895:   return NULL_TREE;            /* @@ may need to backtrack */
        !           896: }
        !           897: 
        !           898: #if 0
        !           899: static struct token
        !           900: hack_scope ()
        !           901: {
        !           902:   /* we've got a :: - what follows is either a global var or a type. */
        !           903:   /* hmm, template names can be in the global scope too... */
        !           904:   tree t1;
        !           905:   struct token rt;
        !           906:   
        !           907:   scan_tokens(1);
        !           908:   if (nth_token(1)->yychar == IDENTIFIER)
        !           909:     {
        !           910:       /* @@ this is probably not right, but doesn't get hit yet */
        !           911:       t1 = build_parse_node (SCOPE_REF,
        !           912:                             NULL_TREE, /* to get "global" scope */
        !           913:                             hack_more_ids(0)); /* do some prefetching */
        !           914:       rt.yylval.ttype = t1;
        !           915:       rt.yychar =              /*SCOPED_*/TYPENAME;
        !           916:       return rt;
        !           917:     }
        !           918:   else
        !           919:     {
        !           920:       rt = *nth_token(0);
        !           921:       consume_token();
        !           922:       return rt;
        !           923:     }
        !           924: }
        !           925: #endif
        !           926:   
        !           927: /*
        !           928:  * Generations:
        !           929:  *     
        !           930:  * PINST: PTYPE { saved_arg_count = arg_count($1) }
        !           931:  *        '<' { arg_c = 0; } PARGS '>'
        !           932:  *        ;
        !           933:  * PARG: TYPE
        !           934:  *       | VALUE
        !           935:  *       ;
        !           936:  * (of course the arg counting doesn't work for recursion... Do it right.)
        !           937:  * PARGS: PARG { assert(arg_c == saved_arg_count); }
        !           938:  *        | PARG ',' PARGS     { arg_c++; }
        !           939:  *        ;
        !           940:  * ATYPE: PINST
        !           941:  *        | TYPEID
        !           942:  *        ;
        !           943:  * TYPE: ATYPE
        !           944:  *       | ATYPE { basetype = $1; } '::' TYPEKIDS
        !           945:  *       ;
        !           946:  * TYPEKIDS: TYPE { assert ($1 is a member of basetype); }
        !           947:  *       | TYPEKIDS { basetype += $1} TYPE { assert( $3 is in basetype ); }
        !           948:  *       ;
        !           949:  *
        !           950:  *
        !           951:  * state0: ; ATYPE
        !           952:  *     TYPE '<': ac = args($0), base = CALL state1, state3     
        !           953:  *     TYPE '::': base=$0, state3
        !           954:  *     else return TYPE
        !           955:  * state1: ; begin PARGS
        !           956:  *     if(ac < list length) punt
        !           957:  *     PARG ",": add to list, state1
        !           958:  *     PARG ">": add to list, return
        !           959:  *     else unravel
        !           960:  * state3: ; begin TYPEKIDS
        !           961:  *     TYPE: 
        !           962:  */
        !           963:   
        !           964:   
        !           965: #ifdef SPEW_DEBUG    
        !           966: 
        !           967: /*
        !           968:  * debug_yychar takes a yychar (token number) value and prints its
        !           969:  * name. This only works if cp-tab.c is compiled with YYDEBUG != 0.
        !           970:  */
        !           971: static int
        !           972: debug_yychar (yy)
        !           973:      int yy;
        !           974: {
        !           975:   extern char *debug_yytranslate ();
        !           976:   
        !           977:   int i;
        !           978:   
        !           979:   if(yy<256) {
        !           980:     fprintf (stderr, "<%d: %c >\n", yy, yy);
        !           981:     return 0;
        !           982:   }
        !           983:   fprintf (stderr, "<%d:%s>\n", yy, debug_yytranslate (yy));
        !           984:   return 1;
        !           985: }
        !           986: 
        !           987: #endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.