xref: /netbsd-src/external/bsd/pcc/dist/pcc/cc/cxxcom/cxxcode.c (revision 3862d4bab153103b9c3d09043872889458100388)
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