Annotation of GNUtools/cc/cp-spew.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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