1 /* Id: cxxcode.c,v 1.6 2014/05/03 09:57:57 ragge Exp */
2 /* $NetBSD: cxxcode.c,v 1.1.1.2 2014/07/24 19:25:40 plunky Exp $ */
3 /*
4 * Copyright (c) 2011 Anders Magnusson (ragge@ludd.luth.se).
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 # include "pass1.h"
29
30
31 struct symtab spole0 = { 0, 0, 0, 0, 0, 0, 0, "base", "base", };
32 struct symtab *spole = &spole0;
33 struct symtab *nscur = &spole0;
34 int elnk, nsptr;
35
36 static struct symtab *sfind(char *n, struct symtab *sp);
37 /*
38 * Declare a namespace.
39 */
40 void
dclns(NODE * attr,char * n)41 dclns(NODE *attr, char *n)
42 {
43 struct symtab *sp;
44 #ifdef GCC_COMPAT
45 struct attr *ap = gcc_attr_parse(attr);
46 #else
47 struct attr *ap = NULL;
48 #endif
49
50 if (cppdebug)printf("declaring namespace %s\n", n);
51 n = addname(n);
52
53 sp = sfind(n, nscur->sup);
54 while (sp != NULL) {
55 if (sp->sname == n && sp->sclass == NSPACE)
56 break;
57 sp = sfind(n, sp->snext);
58 }
59 if (sp == NULL) {
60 /* New namespace */
61 sp = getsymtab(n, 0);
62 sp->sclass = NSPACE;
63 INSSYM(sp);
64 }
65 nscur = sp;
66 if (cppdebug)printf("declaring namespace2 %s\n", nscur->sname);
67 sp->sap = attr_add(sp->sap, ap); /* XXX check attributes */
68 }
69
70 /*
71 * Generate a call tree to function named n.
72 */
73 static NODE *
callftn(char * n,...)74 callftn(char *n, ...)
75 {
76 struct symtab *sp = getsymtab(n, 0);
77 NODE *p, *a, *b;
78 va_list ap;
79
80 sp->stype = (FTN|VOID) | (PTR << TSHIFT);
81 va_start(ap, n);
82
83 a = va_arg(ap, NODE *);
84 if (a != NULL) {
85 do {
86 b = va_arg(ap, NODE *);
87 if (b != NULL)
88 a = buildtree(CM, a, b);
89 } while (b != NULL);
90 }
91
92 p = doacall(sp, nametree(sp), a, 0);
93 va_end(ap);
94 return p;
95 }
96
97 /*
98 * Sanitycheck "new" keyword.
99 */
100 NODE *
cxx_new(NODE * p)101 cxx_new(NODE *p)
102 {
103 NODE *q = p;
104 NODE *t1 = bcon(1);
105 int nw = NM_NEW;
106
107 while (p->n_op == LB) {
108 nw = NM_NWA;
109 t1 = buildtree(MUL, t1, eve(p->n_right));
110 p->n_right = bcon(0);
111 p = p->n_left;
112 }
113 if (p->n_op != TYPE)
114 uerror("new used illegally");
115 t1 = buildtree(MUL, t1,
116 xbcon(tsize(p->n_type, p->n_df, p->n_ap)/SZCHAR, NULL, INTPTR));
117 tfree(q);
118 return callftn(decoratename(NULL, nw), t1, NULL);
119 }
120
121 /*
122 * Handle "delete" keyword.
123 */
124 NODE *
cxx_delete(NODE * p,int del)125 cxx_delete(NODE *p, int del)
126 {
127 return callftn(decoratename(NULL, del), p, NULL);
128 }
129
130 /*
131 <operator-name> ::= nw # new
132 ::= na # new[]
133 ::= dl # delete
134 ::= da # delete[]
135 ::= ps # + (unary)
136 ::= ng # - (unary)
137 ::= ad # & (unary)
138 ::= de # * (unary)
139 ::= co # ~
140 ::= pl # +
141 ::= mi # -
142 ::= ml # *
143 ::= dv # /
144 ::= rm # %
145 ::= an # &
146 ::= or # |
147 ::= eo # ^
148 ::= aS # =
149 ::= pL # +=
150 ::= mI # -=
151 ::= mL # *=
152 ::= dV # /=
153 ::= rM # %=
154 ::= aN # &=
155 ::= oR # |=
156 ::= eO # ^=
157 ::= ls # <<
158 ::= rs # >>
159 ::= lS # <<=
160 ::= rS # >>=
161 ::= eq # ==
162 ::= ne # !=
163 ::= lt # <
164 ::= gt # >
165 ::= le # <=
166 ::= ge # >=
167 ::= nt # !
168 ::= aa # &&
169 ::= oo # ||
170 ::= pp # ++ (postfix in <expression> context)
171 ::= mm # -- (postfix in <expression> context)
172 ::= cm # ,
173 ::= pm # ->*
174 ::= pt # ->
175 ::= cl # ()
176 ::= ix # []
177 ::= qu # ?
178 ::= st # sizeof (a type)
179 ::= sz # sizeof (an expression)
180 ::= at # alignof (a type)
181 ::= az # alignof (an expression)
182 ::= cv <type> # (cast)
183 ::= v <digit> <source-name> # vendor extended operator
184 */
185
186 /*
187 <builtin-type> ::= v # void
188 ::= w # wchar_t
189 ::= b # bool
190 ::= c # char
191 ::= a # signed char
192 ::= h # unsigned char
193 ::= s # short
194 ::= t # unsigned short
195 ::= i # int
196 ::= j # unsigned int
197 ::= l # long
198 ::= m # unsigned long
199 ::= x # long long, __int64
200 ::= y # unsigned long long, __int64
201 ::= n # __int128
202 ::= o # unsigned __int128
203 ::= f # float
204 ::= d # double
205 ::= e # long double, __float80
206 ::= g # __float128
207 ::= z # ellipsis
208 ::= Dd # IEEE 754r decimal floating point (64 bits)
209 ::= De # IEEE 754r decimal floating point (128 bits)
210 ::= Df # IEEE 754r decimal floating point (32 bits)
211 ::= Dh # IEEE 754r half-precision floating point (16 bits)
212 ::= Di # char32_t
213 ::= Ds # char16_t
214 ::= Da # auto (in dependent new-expressions)
215 ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
216 ::= u <source-name> # vendor extended type
217 */
218
219 /* matches type numbering in manifest.h */
220 static char chmap[] = { 'v', 'b', 'c', 'h', 's', 't', 'i', 'j', 'l', 'm',
221 'x', 'y', 'f', 'd', 'e' };
222
223 static int
typch(int typ)224 typch(int typ)
225 {
226 int c = BTYPE(typ);
227 if (c == VOID)
228 c = 0;
229 return chmap[c];
230 }
231
232 #define MAXNM 255 /* max length of mangled name */
233 static char nmblk[MAXNM];
234 static int nmptr, subptr;
235
236 /* push character */
237 static void
nmch(int c)238 nmch(int c)
239 {
240 if (nmptr >= MAXNM)
241 cerror("Too long mangled name");
242 nmblk[nmptr++] = c;
243 }
244
245 /* Push length and string */
246 static void
pshsln(char * c)247 pshsln(char *c)
248 {
249 int i, j, ln = strlen(c);
250
251 #define cnt(v,n) for (v = 0; ln >= n; v++, ln -= n)
252 cnt(i,100);
253 cnt(j,10);
254 if (i) nmch(i+'0');
255 if (j || i) nmch(j+'0');
256 nmch(ln+'0');
257 for (; *c; c++)
258 nmch(*c);
259 }
260
261 /* Recurse to push namespace names */
262 static void
recnpsh(struct symtab * sp)263 recnpsh(struct symtab *sp)
264 {
265 if (sp == spole)
266 return;
267 if (sp == sp->sdown)
268 cerror("sp == sp->sdown");
269 if (sp->sdown)
270 recnpsh(sp->sdown);
271 pshsln(sp->sname);
272 }
273
274 static void
pshargs(union arglist * al)275 pshargs(union arglist *al)
276 {
277 TWORD t;
278
279
280 for (; al->type != TNULL; al++) {
281 t = al->type;
282 if (t == TELLIPSIS) {
283 nmch('z');
284 continue;
285 }
286 while (t > BTMASK) {
287 if (ISPTR(t))
288 nmch('P');
289 else
290 uerror("pshargs2: %lx\n", t);
291 t = DECREF(t);
292 }
293 if (t > LDOUBLE)
294 uerror("pshargs: %lx\n", t);
295 /* XXX - cannot emit const/volatile */
296 nmch(typch(t));
297 }
298 }
299
300 /*
301 * Do name mangling of a symbol table entry.
302 * The resulting name is saved in soname.
303 */
304 char *
decoratename(struct symtab * sp,int type)305 decoratename(struct symtab *sp, int type)
306 {
307 char *n;
308
309 #define QNM(m,s) case m: n = s; break
310 switch (type) {
311 QNM(NM_NEW,"_Znwm");
312 QNM(NM_NWA,"_Znam");
313 QNM(NM_DEL,"_ZdlPv");
314 QNM(NM_DLA,"_ZdaPv");
315 case NM_NORMAL: /* Defined in defid() */
316 break;
317 default:
318 uerror("missed mangling %d\n", type);
319 return "";
320 }
321 if (type != NM_NORMAL)
322 return addname(n);
323
324 /* special non-mangled cases:
325 * "C" linkage
326 * main() function
327 * variables outside namespaces and classes
328 */
329 if (elnk == LINK_C || strcmp(sp->sname, "main") == 0 ||
330 (sp->sdown == spole && !ISFTN(sp->stype))) {
331 n = exname(sp->sname);
332 return addname(n);
333 }
334 /* Compute the mangled name for other symbols */
335 nmptr = 0;
336 subptr = 0;
337 nmch('_'); nmch('Z');
338 if (sp->sdown != NULL) {
339 nmch('N');
340 recnpsh(sp->sdown);
341 }
342 pshsln(sp->sname);
343 if (sp->sdown != NULL)
344 nmch('E');
345 if (ISFTN(sp->stype) && sp->sdf->dfun)
346 pshargs(sp->sdf->dfun);
347 nmch(0);
348 return addname(nmblk);
349 }
350
351 /*
352 * find a symtab entry in the given link.
353 */
354 static struct symtab *
sfind(char * n,struct symtab * sp)355 sfind(char *n, struct symtab *sp)
356 {
357 while (sp) {
358 if (cppdebug)printf("sfind: checking %s against %s\n", n, sp->sname);
359 if (sp->sname == n)
360 return sp;
361 sp = sp->snext;
362 }
363 return NULL;
364 }
365
366 /* class or namespace? */
367 #define CLORNS(sp) (sp->sclass == STNAME || sp->sclass == CLNAME || \
368 sp->sclass == UNAME || sp->sclass == NSPACE)
369
370 /*
371 * find a symtab path entry in the given path.
372 * p is expected to be a link of NMNAMEs.
373 * It is supposed to return a sup value of the last found class.
374 */
375 static struct symtab *
pfind(NODE * p,struct symtab * sp)376 pfind(NODE *p, struct symtab *sp)
377 {
378 char *n;
379
380 if (cppdebug)printf("pfind: op %d searching %s\n", p->n_op, p->n_op == NAME ?
381 (char *)p->n_sp:(char *)p->n_right->n_sp);
382
383 if (p->n_op == NAME) {
384 n = (char *)p->n_sp;
385 if ((sp = sfind(n, sp)) == NULL)
386 return NULL;
387 if (cppdebug)printf("pfind: NAME class %d name %s\n", sp->sclass, sp->sname);
388 while (!CLORNS(sp)) {
389 if ((sp = sfind(n, sp->snext)) == NULL)
390 return NULL;
391 }
392 if (cppdebug)printf("pfind: FOUND %s\n", sp->sname);
393 sp = sp->sup;
394 } else {
395 n = (char *)p->n_right->n_sp;
396 if ((sp = sfind(n, sp)) == NULL)
397 return NULL;
398 if (cppdebug)printf("pfind: NMLIST class %d name %s\n", sp->sclass, sp->sname);
399 while (!CLORNS(sp)) {
400 if ((sp = sfind(n, sp->snext)) == NULL)
401 return NULL;
402 }
403 sp = pfind(p->n_left, sp->sup);
404 }
405 return sp;
406 }
407
408 /*
409 * Declare a variable.
410 */
411 struct symtab *
cxxdeclvar(NODE * p)412 cxxdeclvar(NODE *p)
413 {
414 struct symtab *sp;
415
416 if (blevel && p->n_op == NAME) {
417 sp = p->n_sp = lookup((char *)p->n_sp, 0);
418 } else {
419 sp = cxxlookup(p, SNORMAL);
420 }
421 return sp;
422 }
423
424 /*
425 * class is MOS if variable is member of a CLASS, NORMAL otherwise.
426 * A CLASS as member of a class has symbol type CLASS.
427 */
428 char *symclass[] = { "NORMAL", "CLASS", "LABEL", "MOS", "STRING" };
429
430 /*
431 * Do a name lookup. p can be either just a NAME or NMLIST.
432 * The first symbol instance on its level is returned, which may or
433 * may not be correct.
434 * If no symbol is found, return a new symtab entry.
435 * p should be a NAME after this with n_sp filled in accordingly.
436 * It's the responsibility of the declaration routine to add it to
437 * the symbol table.
438 * nfree() will be called on p after this function.
439 */
440 struct symtab *
cxxlookup(NODE * p,int flags)441 cxxlookup(NODE *p, int flags)
442 {
443 struct symtab *sp, *ns;
444 int ftyp = flags & SMASK;
445 NODE *q;
446 char *n, *s;
447
448 #define SPNAME(p) ((char *)(p->n_op == NAME ? p->n_sp : p->n_right->n_sp))
449 #ifdef PCC_DEBUG
450 if (cppdebug){ printf("cxxlookup %s\n", SPNAME(p)); symtree(); }
451 #endif
452
453 q = p;
454 if (p->n_op == NAME) {
455 s = (char *)p->n_sp;
456 if (blevel) {
457 sp = lookup(s, SNOCREAT); /* check if auto var */
458 if (sp == NULL) {
459 /* check if in classes */
460 for (ns = nscur; ns != spole; ns = ns->sdown)
461 if ((sp = sfind(s, ns->sup)))
462 break;
463 if (sp == NULL)
464 sp = sfind(s, spole->sup);
465 }
466 if (sp == NULL)
467 sp = lookup(s, 0); /* fallback */
468 } else {
469 ns = nscur;
470 sp = sfind(s, ns);
471 while (sp != NULL) {
472 if ((sp->sflags & SMASK) == ftyp)
473 break;
474 sp = sfind(s, sp->snext);
475 }
476 if (sp == NULL) {
477 sp = getsymtab(s, ftyp);
478 if ((flags & SNOCREAT) == 0) {
479 #ifdef PCC_DEBUG
480 if (cppdebug)printf("cxxlookup: adding %s %s %s at %s\n", symclass[ftyp], s, sp->soname, nscur ? nscur->sname : "base");
481 #endif
482 INSSYM(sp);
483 cxxsetname(sp);
484 }
485 }
486 }
487 } else {
488 /* Search through namespaces/classes for it */
489 n = SPNAME(p);
490 ns = pfind(p->n_left, spole->sup);
491 if (ns == NULL) {
492 uerror("undeclared class in chain");
493 return getsymtab(n, ftyp);
494 }
495 if ((sp = sfind(n, ns)) == NULL) {
496 sp = getsymtab(n, ftyp);
497 if ((flags & SNOCREAT) == 0) {
498 sp->snext = ns->snext;
499 ns->snext = sp;
500 }
501 }
502 }
503
504 /* make top node a NAME */
505 if (q->n_op != NAME) {
506 tfree(q->n_left);
507 p = q->n_right;
508 *q = *q->n_right;
509 nfree(p);
510 }
511 q->n_sp = sp;
512 return sp;
513 }
514
515 void
cxxsetname(struct symtab * sp)516 cxxsetname(struct symtab *sp)
517 {
518 if (elnk == LINK_C)
519 return; /* leave to target */
520 sp->soname = decoratename(sp, NM_NORMAL);
521 }
522
523 /*
524 * Create a symbol out of a struct.
525 * We call the symbol "__%THIS" to avoid interference.
526 */
527 struct symtab *
cxxstrvar(struct symtab * so)528 cxxstrvar(struct symtab *so)
529 {
530 struct symtab *sp;
531 NODE *p;
532
533 sp = lookup("__%THIS", 0);
534 p = block(NAME, 0, 0, INCREF(so->stype), so->sdf, so->sap);
535 p->n_sp = sp;
536 defid(p, PARAM);
537 nfree(p);
538 return sp;
539 }
540
541 /*
542 * Declare a struct (class) based on its name n.
543 * Assumed that nmcur is correctly pointing to either:
544 * - nothing (class at level 0)
545 * - current namespace
546 * - parent class
547 */
548 struct symtab *
cxxdclstr(char * n)549 cxxdclstr(char *n)
550 {
551 struct symtab *sp;
552
553 sp = sfind(n, nscur->sup);
554 while (sp && !CLORNS(sp))
555 sp = sfind(n, sp->snext);
556 if (sp == 0)
557 sp = getsymtab(n, STAGNAME);
558 // else
559 // uerror("class/namespace redefined");
560 // INSSYM(sp);
561 // nscur = sp;
562
563 if (cppdebug)printf("declaring2 struct %s %p nscur %s\n", n, sp, nscur->sname);
564 return sp;
565 }
566
567 #ifdef PCC_DEBUG
568 static void
symwalk(struct symtab * sp,int indent)569 symwalk(struct symtab *sp, int indent)
570 {
571 int i;
572
573 while (sp) {
574 for (i = 0; i < indent; i++)
575 printf(" ");
576 printf("%s (%p) %s\n", sp->sname, sp, scnames(sp->sclass));
577 if (sp->sup)
578 symwalk(sp->sup, indent+1);
579 sp = sp->snext;
580 }
581 }
582
583 void
symtree(void)584 symtree(void)
585 {
586 symwalk(spole, 0);
587 }
588 #endif
589
590 /*
591 * Compare a matching prototype for a function.
592 */
593 static int
cxxpcmp(struct symtab * sp,NODE * p)594 cxxpcmp(struct symtab *sp, NODE *p)
595 {
596 union arglist *a1, *a2;
597 int i;
598
599 if (!ISFTN(sp->stype) || p->n_df == NULL || sp->sdf == NULL)
600 return 0; /* no dimfun */
601 if ((a1 = sp->sdf->dfun) == NULL || (a2 = p->n_df->dfun) == NULL)
602 return 0; /* no argument */
603
604 for (i = 0; ; i++) {
605 if (a1[i].type == TNULL && a2[i].type == TNULL)
606 return 1; /* equal prototypes */
607 if (a1[i].type != a2[i].type)
608 return 1; /* unequal prototypes */
609 }
610 }
611
612 struct ckstr {
613 int rv;
614 union arglist *al;
615 };
616
617 static void
cxxckproto(NODE * p,void * arg)618 cxxckproto(NODE *p, void *arg)
619 {
620 struct ckstr *cp = arg;
621
622 if (cp->rv == -1)
623 return;
624
625 if (cp->al[0].type != p->n_type)
626 goto fail;
627 if (BTYPE(cp->al[0].type) > LDOUBLE)
628 uerror("cxxckproto");
629 cp->al++;
630 return;
631 fail:
632 cp->rv = -1;
633 }
634
635 /*
636 * Compare a matching prototype for an argument tree.
637 * Here we can expand to also do inexact matches.
638 * Return 0 if equal, -1 if failed.
639 */
640 static int
cxxptreecmp(struct symtab * sp,NODE * p)641 cxxptreecmp(struct symtab *sp, NODE *p)
642 {
643 struct ckstr ckstr;
644 union arglist *a1;
645
646 if (!ISFTN(sp->stype) || sp->sdf == NULL ||
647 (a1 = sp->sdf->dfun) == NULL)
648 return 0; /* no dimfun */
649
650 if (p == NULL && a1[0].type == TNULL)
651 return 1; /* arg-less */
652
653 ckstr.rv = 0;
654 ckstr.al = a1;
655 flist(p, cxxckproto, &ckstr);
656
657 if (ckstr.al[0].type != TNULL)
658 return -1; /* arg number error */
659 return ckstr.rv;
660 }
661
662 /*
663 * Search for (and declare) a function.
664 */
665 struct symtab *
cxxftnfind(NODE * p,int flags)666 cxxftnfind(NODE *p, int flags)
667 {
668 struct symtab *sp, *ns;
669 char *s;
670
671 if (p->n_op == NAME) {
672 s = (char *)p->n_sp;
673 /* Search for equally named functions */
674 sp = sfind(s, nscur->sup);
675 while (sp != NULL) {
676 if (cxxpcmp(sp, p)) {
677 if (sp->sclass != NSPACE ||
678 sp->sclass == EXTDEF) {
679 uerror("%s redefined", s);
680 return sp;
681 } else
682 break;
683 }
684 sp = sfind(s, sp->snext);
685 }
686 if (sp == NULL) {
687 sp = getsymtab(s, SNORMAL);
688 sp->stype = p->n_type;
689 sp->squal = p->n_qual;
690 sp->sdf = p->n_df;
691 sp->sap = p->n_ap;
692 INSSYM(sp);
693 if (nscur->sclass != NSPACE && nscur != &spole0)
694 uerror("inside struct");
695 }
696 sp->sclass = EXTDEF;
697 if (sp->soname == 0)
698 sp->soname = decoratename(sp, NM_NORMAL);
699 } else {
700 /*
701 * declared outside class, tree-style reference
702 * Must have been defined already
703 * This will be an external declaration (not spooled).
704 */
705 s = SPNAME(p);
706 if ((ns = pfind(p->n_left, spole->sup)) == NULL) {
707 uerror("undeclared class in chain");
708 goto undecl;
709 }
710 /* Search for an EXTERN or EXTDEF declaration within */
711 /* EXTDEF causes redeclaration. */
712 sp = sfind(s, ns);
713 while (sp != NULL) {
714 if (sp->sclass == EXTERN || sp->sclass == EXTDEF) {
715 if (cxxpcmp(sp, p->n_right)) {
716 if (sp->sclass == EXTDEF)
717 uerror("%s redefined", s);
718 break;
719 }
720 }
721 sp = sfind(s, sp->snext);
722 }
723 if (sp == NULL) {
724 uerror("%s undeclared", s);
725 goto undecl;
726 }
727 sp->sclass = EXTDEF;
728 }
729 return sp;
730
731 undecl:
732 return getsymtab(s, SNORMAL);
733 }
734
735 /*
736 * Reference to a struct as a :: name.
737 */
738 NODE *
cxxrstruct(int soru,NODE * attr,NODE * t,char * n)739 cxxrstruct(int soru, NODE *attr, NODE *t, char *n)
740 {
741 struct symtab *ns, *sp;
742
743 ns = pfind(t, spole->sup);
744 if (ns == NULL)
745 goto undecl;
746
747 tfree(t);
748 sp = sfind(n, ns);
749 while (sp != NULL) {
750 if (sp->sclass == soru)
751 return mkty(sp->stype, 0, sp->sap);
752 sp = sfind(n, sp->snext);
753 }
754 undecl:
755 uerror("%s undeclared", n);
756 return mkty(INT, 0, 0);
757 }
758
759 /*
760 * Search for correct matching function in a struct depending on
761 * argument list a. Return a call node for this function.
762 * Do not touch neither f nor a.
763 * return a name tree suitable for a function call.
764 * We know here that f is a struct reference.
765 */
766 NODE *
cxxmatchftn(NODE * f,NODE * a)767 cxxmatchftn(NODE *f, NODE *a)
768 {
769 struct attr *ap;
770 struct symtab *sp;
771 char *n = (char *)f->n_right->n_sp;
772
773 f = f->n_left;
774
775 if ((ap = attr_find(f->n_ap, ATTR_STRUCT)) == NULL) {
776 uerror("undefined class");
777 sp = getsymtab(n, 0);
778 } else
779 sp = ap->amlist;
780 sp = sfind(n, sp);
781 while (sp != NULL) {
782 if (ISFTN(sp->stype) && cxxptreecmp(sp, a) == 0)
783 break;
784 sp = sfind(n, sp->snext);
785 }
786 if (sp == NULL)
787 uerror("undefined class member");
788 return nametree(sp);
789 }
790
791 /*
792 * Add hidden argument f first in node list a. Return resulting a.
793 */
794 NODE *
cxxaddhidden(NODE * a,NODE * f)795 cxxaddhidden(NODE *a, NODE *f)
796 {
797 NODE *q;
798
799 if (a == NULL)
800 return f;
801 if (a->n_op != CM)
802 return block(CM, f, a, INT, 0, 0);
803 for (q = a; q->n_left->n_op == CM; q = q->n_left)
804 ;
805 q->n_left = block(CM, f, q->n_left, INT, 0, 0);
806 return a;
807 }
808
809 /*
810 * Watch out for references to static members.
811 */
812 NODE *
cxxstructref(NODE * p,int f,char * n)813 cxxstructref(NODE *p, int f, char *n)
814 {
815 struct symtab *sp = strmemb(p->n_ap);
816
817 if (sp == NULL)
818 cerror("ref to unknown struct");
819 sp = sfind(n, sp);
820 while (sp != NULL) {
821 if (!ISFTN(sp->stype)) {
822 if (sp->sclass == STATIC || sp->sclass == USTATIC) {
823 tfree(p);
824 return nametree(sp);
825 }
826 break;
827 }
828 sp = sfind(n, sp->snext);
829 }
830 return structref(p, f, n);
831 }
832