parser - more cleanups
[rune.git] / librune / parse2.c
1 /*
2  * PARSE2.C     - Misc parser support, including declarator handling
3  *
4  * (c)Copyright 1993-2014, Matthew Dillon, All Rights Reserved.  See the  
5  *    COPYRIGHT file at the base of the distribution.
6  */
7
8 #include "defs.h"
9
10 static int FinishDecl(Parse *p, int t, Declaration *d, Type *type);
11
12 /*
13  * XXX handle scope overrides
14  */
15 int
16 ParseScopeQual(Parse *p, int t, Scope *scope)
17 {
18         scope->s_Flags = 0;
19         scope->s_AlignOverride = 0;
20
21         while (t & TOKF_SCOPE_QUAL) {
22                 scope->s_Flags |= 1 << (t & TOKF_SCOPE_MASK);
23                 if (t == TOK_ALIGN) {
24                         t = LexToken(&p->p_Token);
25                         t = LexSkipToken(&p->p_Token, TOK_OPAREN);
26                         t = SimpleIntToken(&p->p_Token,
27                                            &scope->s_AlignOverride);
28                         t = LexSkipToken(&p->p_Token, TOK_INTEGER);
29                         t = LexSkipToken(&p->p_Token, TOK_CPAREN);
30                 } else {
31                         t = LexToken(&p->p_Token);
32                 }
33         }
34         return(t);
35 }
36
37 /*
38  * XXX handle illegal storage qualifier combinations & overrides
39  */
40 int
41 ParseStorageQual(Parse *p, int t, int *pmask)
42 {
43         int mask = 0;
44
45         while (t & TOKF_STOR_QUAL) {
46                 mask |= 1 << (t & TOKF_STOR_MASK);
47                 t = LexToken(&p->p_Token);
48         }
49         *pmask = mask;
50         return(t);
51 }
52
53 /*
54  * declaration: type decl(idReq) [= exp]
55  *
56  * Note: we only handle the procedural reference portion of a procedure
57  * definition here.  We do not handle the procedure body.  See
58  * ParseDeclarationStmt().  We also handle aliases here.
59  *
60  * idRequired may be 0, 1, or 2.
61  *
62  *      0:      No identifier is required
63  *      1:      An identifier is required
64  *      2:      An identifier is required, a dotted identifier sequence is
65  *              optional, and global scope is implied if only a single
66  *              identifier is used.
67  */
68 int
69 ParseDeclaration(Parse *p, int t, Declaration **pd, int idRequired, int dop, Scope *scope)
70 {
71         Declaration *d;
72         int sqflags = 0;
73         int rqflags = 0;
74         int isAlias = 0;
75         int isCast = 0;
76         int isOper = 0;
77         int isMeth = 0;
78         string_t id = NULL;
79         string_t opid = NULL;
80         Type *type;
81         Scope tscope = *scope;
82
83         /*
84          * Handle alias declarations.
85          */
86         if (t == TOK_ALIAS) {
87                 isAlias = 1;
88                 t = LexToken(&p->p_Token);
89         }
90
91         /*
92          * Handle procedure-related special cases
93          */
94         switch(t) {
95         case TOK_CAST:
96                 t = LexToken(&p->p_Token);
97                 tscope.s_Flags |= SCOPE_CAST;
98                 isCast = 1;
99                 break;
100         case TOK_OPERATOR:
101                 t = LexToken(&p->p_Token);
102                 if (t != TOK_DSTRING) {
103                         t = LexError(&p->p_Token,
104                                      TOK_ERR_EXPECTED_QUOTED_OPERATOR);
105                 } else {
106                         /*
107                          * Add the operator to the operator hash.  Don't
108                          * hash the quotes, just the contents of the quotes.
109                          */
110                         opid = StrTableAlloc(p->p_Token.t_Ptr + 1,
111                                              p->p_Token.t_Len - 2, 0);
112                         t = LexToken(&p->p_Token);
113                 }
114                 isOper = 1;
115                 break;
116         case TOK_METHOD:
117                 t = LexToken(&p->p_Token);
118                 isMeth = 1;
119                 if (tscope.s_Flags & SCOPE_GLOBAL)
120                         rqflags |= SF_GMETHOD;
121                 else
122                         rqflags |= SF_METHOD;
123                 break;
124         }
125
126         /*
127          * Allow the LVALUE scope to be specified after the operator
128          * (to make operator declarations using lvalue look nicer).
129          *
130          * 'lvalue' is also a storage qualifier, and requires outer scoping.  
131          * e.g. if you have something like 'lvalue const int *x', lvalue
132          * applies to the declaration itself, the pointer, whereas const
133          * applies to what is being pointed to.
134          */
135         if (t == TOK_LVALUE) {
136                 tscope.s_Flags |= SCOPE_LVALUE;
137                 t = LexToken(&p->p_Token);
138         }
139         if (tscope.s_Flags & SCOPE_LVALUE)
140                 rqflags |= SF_LVALUE;
141
142
143         /*
144          * Parse storage qualifiers and the base type
145          */
146         t = ParseStorageQual(p, t, &sqflags);
147         t = ParseType(p, t, &type, sqflags);
148
149         /*
150          * Parse the declarators and identifier(s).  Deal with implied global
151          * scope, and adjust 'dop' properly.
152          */
153         if (type) {
154                 SemGroup *sg = p->p_CurSemGroup;
155                 t = ParseDeclType(p, t, &type, &sg,
156                                   tscope.s_Flags & SCOPE_CLANG,
157                                   rqflags, &id, idRequired);
158                 if (idRequired == 2 && sg == p->p_CurSemGroup)
159                         tscope.s_Flags |= SCOPE_GLOBAL;
160                 if ((tscope.s_Flags & SCOPE_GLOBAL) && (dop & DOPF_STORAGE))
161                         dop = DOP_GLOBAL_STORAGE;
162                 if (isAlias)
163                         dop = DOP_ALIAS;
164                 d = AllocDeclaration(sg, dop, &tscope);
165                 t = FinishDecl(p, t, d, type);
166         } else {
167                 d = NULL;
168         }
169
170         /*
171          * Make sure procedural keywords are only used with procedures,
172          * and hash the operator id (if any).
173          */
174         if (d) {
175                 if (d->d_Op != DOP_PROC && (isCast || isOper || isMeth)) {
176                         t = LexError(&p->p_Token,
177                                      TOK_ERR_OPERATOR_NOT_PROCEDURE);
178                 } else if (opid) {
179                         HashOper(d, opid);
180                 }
181         }
182
183 #if 0
184         /*
185          * If this is a method procedure we have to add an argument called
186          * 'this' that represents an lvalue of the class the procedure resides
187          * in.  XXX not needed any more.
188          */
189         if (isMeth) {
190         }
191 #endif
192
193         /*
194          * Handle any assigned expression
195          */
196         if (t == TOK_ASS) {
197                 switch(d->d_Op) {
198                 case DOP_ALIAS:
199                         t = LexToken(&p->p_Token);
200                         t = ParseExp(p, t, &d->d_AliasDecl.ed_AssExp);
201                         break;
202                 case DOP_TYPEDEF:
203                         t = LexToken(&p->p_Token);
204                         t = ParseExp(p, t, &d->d_TypedefDecl.ed_AssExp);
205                         break;
206                 case DOP_ARGS_STORAGE:
207                 case DOP_STACK_STORAGE:
208                 case DOP_GLOBAL_STORAGE:
209                 case DOP_GROUP_STORAGE:
210                         t = LexToken(&p->p_Token);
211                         t = ParseExp(p, t, &d->d_StorDecl.ed_AssExp);
212                         break;
213                 }
214         } else if (isAlias) {
215                 /*
216                  * Assignment is required for aliases
217                  */
218                 t = LexError(&p->p_Token, TOK_ERR_SYNTAX);
219         }
220         if (t & TOKF_ERROR) {
221                 if (d) {
222                         FreeDeclaration(p, d);
223                         d = NULL;
224                 }
225                 if (id)
226                         RelStrTable(&id);
227         } else {
228                 if (id) {
229                         /*
230                          * note: HashDecl() eats our reference on id.
231                          */
232                         if (HashDecl(d, id) > 0 &&
233                             !(d->d_Op == DOP_PROC &&
234                             d->d_ProcDecl.ed_OperId != NULL))
235                         {
236                                 t = LexError(&p->p_Token, TOK_ERR_DUPLICATE_ID);
237                         }
238                 }
239         }
240         if (pd)
241                 *pd = d;
242         return(t);
243 }
244
245 /*
246  * ( declaration [, declaration]* )
247  */
248 int
249 ParseDeclarationList(Parse *p, int t, int scopeFlags, int idRequired, int dop)
250 {
251         t = LexSkipToken(&p->p_Token, TOK_OPAREN);
252         if (t != TOK_CPAREN) {
253                 for (;;) {
254                         Scope scope;
255
256                         if (t == TOK_DOT) {
257                                 if (p->p_CurSemGroup->sg_Flags & SGF_PROCARGS) {
258                                         t = LexSkipToken(&p->p_Token, TOK_DOT);
259                                         t = LexSkipToken(&p->p_Token, TOK_DOT);
260                                         t = LexSkipToken(&p->p_Token, TOK_DOT);
261                                         p->p_CurSemGroup->sg_Flags |= SGF_VARARGS;
262                                 } else {
263                                         t = LexError(&p->p_Token,
264                                                      TOK_ERR_SYNTAX);
265                                 }
266                                 break;
267                         }
268                         t = ParseScopeQual(p, t, &scope);
269                         scope.s_Flags |= scopeFlags;
270                         t = ParseDeclaration(p, t, NULL,
271                                              idRequired, dop, &scope);
272                         if (t != TOK_COMMA)
273                                 break;
274                         t = LexToken(&p->p_Token);
275                 }
276         }
277         t = LexSkipToken(&p->p_Token, TOK_CPAREN);
278         return(t);
279 }
280
281 /*
282  * type:
283  *      id [ . id ]*
284  *      ( declaration [, declaration]* )
285  */
286 int
287 ParseType(Parse *p, int t, Type **ptype, int sqflags)
288 {
289         *ptype = NULL;
290
291         if (t == TOK_STORAGE) {
292                 int bytes = 0;
293
294                 t = LexToken(&p->p_Token);
295                 t = LexSkipToken(&p->p_Token, TOK_OPAREN);
296                 t = SimpleIntToken(&p->p_Token, &bytes);
297                 t = LexSkipToken(&p->p_Token, TOK_INTEGER);
298                 t = LexSkipToken(&p->p_Token, TOK_CPAREN);
299                 *ptype = AllocStorageType(bytes);
300                 if (sqflags) {
301                         *ptype = TypeToQualType(*ptype,
302                                                 NULL,
303                                                 (*ptype)->ty_SQFlags|sqflags,
304                                                 NULL);
305                 }
306                 return(t);
307         } 
308
309         if (t == TOK_OPAREN) {
310                 /*
311                  * parse a compound type.
312                  */
313                 p->p_CurSemGroup = AllocSemGroup(p, p->p_CurSemGroup, NULL);
314                 t = ParseDeclarationList(p, t, 0, 0, DOP_GROUP_STORAGE);
315                 if ((t & TOKF_ERROR) == 0) {
316                         *ptype = AllocCompoundType(p->p_CurSemGroup);
317                         if (sqflags) {
318                                 *ptype = TypeToQualType(*ptype, NULL,
319                                                         (*ptype)->ty_SQFlags |
320                                                          sqflags,
321                                                         NULL);
322                         }
323                 } else {
324                         t = LexError(&p->p_Token, TOK_ERR_EXPECTED_CPAREN);
325                         /* mark semgroup for free after pop */
326                 }
327                 p->p_CurSemGroup = p->p_CurSemGroup->sg_Parent;
328         } else if (t & TOKF_ID) {
329                 /*
330                  * parse a normal type, which is a semantic identifier path
331                  * like "a.b.c.d".
332                  */
333                 string_t *ary;
334                 int count;
335                 int lt;
336
337                 t = ParseDotIdAry(p, t, &ary, &count, &lt);
338                 if (lt != TOK_CLASSID)
339                         t = LexError(&p->p_Token, TOK_ERR_EXPECTED_CLASSID);
340                 if ((t & TOKF_ERROR) == 0) {
341                         *ptype = AllocUnresolvedType(
342                                 p->p_Import->st_ImportStmt.es_SemGroup,
343                                 p->p_CurSemGroup,
344                                 ary,
345                                 1);
346                 }
347                 /* XXX cleanup memory */
348         } else {
349                 t = LexError(&p->p_Token, TOK_ERR_EXPECTED_TYPE);
350         }
351         if ((t & TOKF_ERROR) == 0) {
352                 if (sqflags) {
353                         *ptype = TypeToQualType(*ptype, NULL,
354                                                 (*ptype)->ty_SQFlags | sqflags,
355                                                 NULL);
356                 }
357         }
358         return(t);
359 }
360
361 /*
362  * ParseDotIdAry() - parse a sequence of dot-separated identifiers.
363  */
364 int
365 ParseDotIdAry(Parse *p, int t, string_t **pary, int *pcount, int *ltp)
366 {
367         string_t *ary;
368         token_t save;
369         int count;
370
371         /*
372          * First token must be an identifier
373          */
374         if ((t & TOKF_ID) == 0)
375                 t = LexError(&p->p_Token, TOK_ERR_EXPECTED_ID);
376
377         /*
378          * First count the number of identifiers.
379          */
380         save = p->p_Token;
381         count = 0;
382         *ltp = 0;
383
384         while ((t & TOKF_ERROR) == 0) {
385                 ++count;                        /* count ID */
386                 *ltp = t;
387                 t = LexToken(&p->p_Token);      /* skip id */
388                 if (t != TOK_DOT)
389                         break;
390                 t = LexToken(&p->p_Token);      /* skip dot */
391                 if ((t & TOKF_ID) == 0)
392                         t = LexError(&p->p_Token, TOK_ERR_EXPECTED_ID);
393         }
394
395         /*
396          * If no error occured, allocate the array and load it with the
397          * identifiers.
398          */
399         if ((t & TOKF_ERROR) == 0) {
400                 int i;
401
402                 p->p_Token = save;
403                 t = save.t_Type;
404                 ary = zalloc(sizeof(string_t) * (count + 1));
405                 for (i = 0; i < count; ++i) {
406                         ary[i] = StrTableToken(&p->p_Token);
407                         t = LexToken(&p->p_Token);              /* skip id */
408                         if (i + 1 < count)
409                                 t = LexToken(&p->p_Token);      /* skip dot */
410                 }
411                 *pary = ary;
412                 *pcount = count;
413         } else {
414                 *pary = NULL;
415                 *pcount = 0;
416         }
417         return(t);
418 }
419
420 string_t *
421 DupDotIdAry(string_t *ary)
422 {
423         int i;
424         string_t *nary;
425
426         for (i = 0; ary[i]; ++i)
427                 ;
428         nary = zalloc(sizeof(string_t) * (i + 1));
429         for (i = 0; ary[i]; ++i)
430                 nary[i] = StrTableDup(ary[i]);
431         return(nary);
432 }
433
434 void
435 FreeDotIdAry(string_t *ary)
436 {
437         int i;
438
439         for (i = 0; ary[i]; ++i)
440                 RelStrTable(&ary[i]);
441         zfree(ary, sizeof(string_t) * (i + 1));
442 }
443
444 /*
445  * ParseDeclType() -    Parse declarators for declaration given base type
446  *
447  *      Parse the declarators for the specified base type, returning an
448  *      appropriate qualified type.  If an identifier is part of the 
449  *      declarator sequence the identifier will be returned.  If idRequired
450  *      is 1, an identifier is required.  If idRequired is 2, multiple
451  *      dot-separated identifiers are allowed (and the last is returned),
452  *      and psg will be set to the SemGroup representing the class they
453  *      reference.  For example, 'int FILE.setMode(int mode) { .. }'
454  *      will set *psg to FILE's SemGroup.  This eventually goes into
455  *      d_MyGroup, while d_OrigSemGroup retains the original semgroup.
456  *
457  *      Note that multi-identifiers have library scope only and must already
458  *      exist (not be forward referenced).
459  *
460  * declaration: type decl
461  *
462  * decl:        [ declarator ]*
463  *
464  * declarator:
465  *      id[.id]*                identifier(s) (if not already specified)
466  *      ( declaration_list)     procedure-returning
467  *      [ exp ]                 array of
468  *      *                       pointer to
469  *      [ storage_qual ]*       qualified with
470  *
471  * NOTE! Types are built up from left-to-right prior to the identifier or
472  * procedure args, then right-to-left.  For example:
473  *
474  *      const char * const a[2][10]     - an array 2 of an array 10 of
475  *                                        a constant pointer to a constant
476  *                                        character.
477  *
478  *      int func * (int, int)           - a pointer to a procedure taking
479  *                                        two arguments and returning an int.
480  *
481  * NOTE! Certain storage qualifiers in an underlying type will migrate to
482  *       an array type.
483  *
484  * NOTE! scopeFlags propogates SCOPE_CLANG, which effects pointers
485  *      (XXX and should effect alignment too??)
486  */
487 int
488 ParseDeclType(Parse *p, int t, Type **ptype, SemGroup **psg,
489               int scopeFlags, int rqflags, string_t *id,
490               int idRequired)
491 {
492         for (;;) {
493                 if (t == TOK_OPAREN) {
494                         /*
495                          * parse procedure argument-type, which is a compound
496                          * type.  Note that we leave our semantic linkages
497                          * intact to simplify the type resolver (see
498                          * resolve.c), but set the DOP to something we can
499                          * recognize later.  The nesting level will be fixed
500                          * up later.
501                          */
502                         p->p_CurSemGroup = AllocSemGroup(p,
503                                                          p->p_CurSemGroup,
504                                                          NULL);
505                         p->p_CurSemGroup->sg_Flags |= SGF_PROCARGS;
506                         t = ParseDeclarationList(p, t, scopeFlags,
507                                                  0, DOP_ARGS_STORAGE);
508                         if (*id)
509                                 t = ParseDeclType(p, t, ptype,
510                                             NULL, scopeFlags, 0, id,
511                                             idRequired > 1 ? 1 : idRequired);
512                         *ptype = TypeToProcType(*ptype,
513                                             AllocArgsType(p->p_CurSemGroup));
514                         p->p_CurSemGroup = p->p_CurSemGroup->sg_Parent;
515
516                         /*
517                          * anything after proc args must be parsed as if
518                          * we had specified an identifier.
519                          */
520                         if (*id == NULL)
521                                 *id = StrTableAlloc("_dummy_", 7, 0);
522                 } else if (t == TOK_AT) {
523                         /*
524                          * A reference type (bound via a superclass)
525                          */
526                         t = LexToken(&p->p_Token);
527                         if (*id) {
528                                 t = ParseDeclType(p, t, ptype,
529                                                   psg, scopeFlags, 0, id,
530                                                   idRequired);
531                         }
532                         *ptype = TypeToRefType(*ptype);
533                 } else if (t == TOK_OPER && p->p_Token.t_Ptr[0] == '*') {
534                         /*
535                          * We have to deal with pointer-to declarators.
536                          * Regenerate the token using only the first character
537                          * if it is a '*'.
538                          */
539                         t = LexRedactToken(&p->p_Token, 1);
540                         t = LexToken(&p->p_Token);
541                         if (*id) {
542                                 t = ParseDeclType(p, t, ptype,
543                                                   psg, scopeFlags, 0, id,
544                                                   idRequired);
545                         }
546                         if (scopeFlags & SCOPE_CLANG)
547                                 *ptype = TypeToCPtrType(*ptype);
548                         else
549                                 *ptype = TypeToPtrType(*ptype);
550                 } else if (t == TOK_OBRACKET) {
551                         /*
552                          * Array
553                          */
554                         Exp *exp = NULL;
555
556                         t = LexToken(&p->p_Token);
557                         t = ParseExp(p, t, &exp);
558                         t = LexSkipToken(&p->p_Token, TOK_CBRACKET);
559                         if (*id) {
560                                 t = ParseDeclType(p, t, ptype,
561                                                   psg, scopeFlags, 0, id,
562                                                   idRequired);
563                         }
564                         *ptype = TypeToAryType(*ptype, exp, *psg);
565                 } else if (t & TOKF_SCOPE_QUAL) {
566                         t = LexError(&p->p_Token, TOK_ERR_SYNTAX);
567                 } else if (t & TOKF_STOR_QUAL) {
568                         int sqflags;
569
570                         t = ParseStorageQual(p, t, &sqflags);
571                         if (*id) {
572                                 t = ParseDeclType(p, t, ptype,
573                                                   psg, scopeFlags, 0, id,
574                                                   idRequired);
575                         }
576                         *ptype = TypeToQualType(*ptype,
577                                                 NULL,
578                                                 (*ptype)->ty_SQFlags | sqflags,
579                                                 NULL);
580                 } else if (t & TOKF_ID) {
581                         if (*id)        /* terminator */
582                                 break;
583                         *id = StrTableToken(&p->p_Token);
584                         t = LexToken(&p->p_Token);
585                         if (idRequired < 2 && t == TOK_DOT) {
586                                 t = LexError(&p->p_Token,
587                                              TOK_ERR_NO_DOTTED_ID_HERE);
588                         }
589                         while (t == TOK_DOT) {
590                                 /*
591                                  * Lookup *id based on the current psg.  This
592                                  * is about the only FindDeclPath() call that
593                                  * occurs during parse time.  All the rest
594                                  * occur at resolve time.  There is no
595                                  * skip-back SemGroup at parse time (i.e.
596                                  * first arg is NULL).
597                                  *
598                                  * At the moment we only allow private scope.
599                                  * This is because we need pre-resolution
600                                  * structural linkages to stay within their
601                                  * import paradigm, allowing us to save and
602                                  * restore/relocate the associated memory pool
603                                  * as an intermediate pre-parsed file format.
604                                  * It also allows us to resolve things
605                                  * incrementally and save/restore after those
606                                  * steps as well.
607                                  *
608                                  * At some future date I intend to allow
609                                  * library scope, (SCOPE_PRIVATE|SCOPE_LIBRARY),
610                                  * which will necessitate saving and restoring
611                                  * dependant files as a single entity.
612                                  * XXX
613                                  */
614                                 Declaration *d;
615                                 int vis = SCOPE_LIBRARY|SCOPE_PRIVATE;
616                                 int eno = TOK_ERR_PARSE_CLASS_NOT_FOUND;
617                                 string_t ary[] = { *id, NULL };
618
619                                 d = FindDeclPath(NULL, NULL, *psg,
620                                                  NULL, ary, 0, &vis, -1,
621                                                  &eno);
622                                 if (d) {
623                                         switch(d->d_Op) {
624                                         case DOP_CLASS:
625                                                 *psg =
626                                                     d->d_ClassDecl.ed_SemGroup;
627                                                 break;
628                                         case DOP_IMPORT:
629                                                 *psg =
630                                                     d->d_ImportDecl.ed_SemGroup;
631                                                 break;
632                                         default:
633                                                 t = LexError(&p->p_Token,
634                                                     TOK_ERR_PARSE_ID_NOT_CLASS);
635                                                 break;
636                                         }
637                                 } else {
638                                         t = LexError(&p->p_Token, eno);
639                                 }
640                                 if (t & TOKF_ERROR)
641                                         break;
642
643                                 /*
644                                  * Retrieve the next identifier
645                                  */
646                                 t = LexToken(&p->p_Token);
647                                 if ((t & TOKF_ID) == 0) {
648                                         t = LexError(&p->p_Token,
649                                                      TOK_ERR_EXPECTED_ID);
650                                         break;
651                                 }
652                                 ReplaceStrTable(id, StrTableToken(&p->p_Token));
653                                 t = LexToken(&p->p_Token);
654                         }
655                 } else if (
656                         t == TOK_CPAREN ||
657                         t == TOK_SEMI ||
658                         t == TOK_COMMA ||
659                         t == TOK_ASS ||
660                         t == TOK_OBRACE
661                 ) {
662                         break;          /* terminator */
663                 } else {
664                         t = LexError(&p->p_Token, TOK_ERR_EXPECTED_DECLARATOR);
665                 }
666                 if (t & TOKF_ERROR)
667                         break;
668         }
669
670         /*
671          * A Method procedure silently passes the lvalue object as the first
672          * argument to the procedure.  A global method procedure silently
673          * passes the type of the object as the first argument to the
674          * procedure (as a typedef).  The argument is called this.  If the
675          * procedure declares a 'this' argument for the first argument, we
676          * assume that the programmer has constructed this special argument
677          * manually (which the programmer must do if he wants an lvalue
678          * pointer or reference to the class).
679          */
680         if (rqflags & (SF_METHOD|SF_GMETHOD)) {
681                 Type *type;
682                 Type *ctype;
683                 Stmt *st;
684                 SemGroup *sg;
685                 Declaration *nd;
686
687                 type = *ptype;
688                 dassert_parse(p, 0, type->ty_Op == TY_PROC);
689
690                 nd = getHead(&type->ty_ProcType.et_ArgsType->
691                                 ty_ArgsType.et_SemGroup->sg_DeclList);
692                 if (nd && nd->d_Id != String_This)
693                         nd = NULL;
694                 /*
695                  * XXX should really use TypeToProcType() or write a
696                  * ProcTypeToMethodProcType() call.
697                  */
698                 sg = *psg;
699                 st = sg->sg_Stmt;
700                 if (st->st_Op != ST_Class) {
701                         fprintf(stderr,
702                                 "Method calls must be placed in a class\n");
703                         dassert_parse(p, 0, st->st_Op == ST_Class);
704                 }
705
706                 ctype = AllocClassType(&sg->sg_ClassList,
707                                        st->st_ClassStmt.es_Super,
708                                        sg,
709                                        SCOPE_ALL_VISIBLE);
710
711                 if (rqflags & SF_METHOD) {
712                         type = TypeToQualType(type,
713                                               NULL,
714                                               type->ty_SQFlags | SF_METHOD,
715                                               NULL);
716                 } else {
717                         dassert(rqflags & SF_GMETHOD);
718                         type = TypeToQualType(type,
719                                               NULL,
720                                               type->ty_SQFlags | SF_GMETHOD,
721                                               NULL);
722                 }
723                 if (nd == NULL) {
724                         Scope tscope = INIT_SCOPE(SCOPE_ALL_VISIBLE);
725
726                         sg = type->ty_ProcType.et_ArgsType->
727                                 ty_ArgsType.et_SemGroup;
728                         if (rqflags & SF_METHOD) {
729                                 nd = AllocDeclaration(sg,
730                                                       DOP_ARGS_STORAGE,
731                                                       &tscope);
732                                 nd->d_StorDecl.ed_Type =
733                                         TypeToQualType(ctype, NULL,
734                                                        ctype->ty_SQFlags |
735                                                         SF_LVALUE,
736                                                        NULL);
737                                 nd->d_ScopeFlags |= SCOPE_LVALUE;
738                         } else {
739                                 nd = AllocDeclaration(sg, DOP_TYPEDEF, &tscope);
740                                 nd->d_TypedefDecl.ed_Type = ctype;
741                         }
742                         HashDecl(nd, StrTableDup(String_This));
743                         removeNode(&nd->d_Node);
744                         addHead(&sg->sg_DeclList, &nd->d_Node);
745                 }
746                 *ptype = type;
747                 rqflags &= ~(SF_METHOD | SF_GMETHOD);
748         }
749         if (rqflags) {
750                 Type *type = *ptype;
751                 if (type->ty_Op == TY_PROC) {
752                         type = type->ty_ProcType.et_RetType;
753                         (*ptype)->ty_ProcType.et_RetType =
754                                 TypeToQualType(type,
755                                                NULL,
756                                                type->ty_SQFlags | rqflags,
757                                                NULL);
758                 } else {
759                         *ptype = TypeToQualType(type,
760                                                 NULL,
761                                                 type->ty_SQFlags | rqflags,
762                                                 NULL);
763                 }
764         }
765         return(t);
766 }
767
768 static int
769 FinishDecl(Parse *p, int t, Declaration *d, Type *type)
770 {
771         /*
772          * Install the type and adjust the declaration accordingly.
773          */
774         if (d->d_Op == DOP_ALIAS) {
775                 d->d_StorDecl.ed_Type = type;
776         } else if (d->d_Op == DOP_TYPEDEF) {
777                 if (type->ty_Op == TY_PROC)
778                         t = LexError(&p->p_Token, TOK_ERR_ILLEGAL_TYPEDEF);
779                 else
780                         d->d_TypedefDecl.ed_Type = type;
781         } else if (type->ty_Op == TY_PROC) {
782                 d->d_Op = DOP_PROC;
783                 d->d_ProcDecl.ed_Type = type;
784         } else {
785                 dassert_decl(d, d->d_Op & DOPF_STORAGE);
786                 d->d_StorDecl.ed_Type = type;
787         }
788
789         /*
790          * Install d_ImportSemGroup.
791          */
792         d->d_ImportSemGroup = p->p_Import->st_ImportStmt.es_SemGroup;
793
794         return(t);
795 }