1 /**
2  * Compiler implementation of the
3  * $(LINK2 http://www.dlang.org, D programming language).
4  *
5  * Copyright:   Copyright (C) 1985-1998 by Symantec
6  *              Copyright (C) 2000-2021 by The D Language Foundation, All Rights Reserved
7  * Authors:     $(LINK2 http://www.digitalmars.com, Walter Bright)
8  * License:     $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
9  * Source:      https://github.com/dlang/dmd/blob/master/src/dmd/backend/dtype.d
10  */
11 
12 module dmd.backend.dtype;
13 
14 version (SCPP)
15 {
16     version = COMPILE;
17     version = SCPP_HTOD;
18 }
19 version (HTOD)
20 {
21     version = COMPILE;
22     version = SCPP_HTOD;
23 }
24 version (MARS)
25     version = COMPILE;
26 
27 
28 version (COMPILE)
29 {
30 import core.stdc.stdio;
31 import core.stdc.stdlib;
32 import core.stdc.string;
33 
34 import dmd.backend.cdef;
35 import dmd.backend.cc;
36 import dmd.backend.dlist;
37 import dmd.backend.el;
38 import dmd.backend.global;
39 import dmd.backend.mem;
40 import dmd.backend.oper;
41 import dmd.backend.ty;
42 import dmd.backend.type;
43 
44 version (SCPP_HTOD)
45 {
46     import dtoken;
47     import msgs2;
48     import parser;
49     import precomp;
50 }
51 
52 extern (C++):
53 
54 nothrow:
55 
56 alias MEM_PH_MALLOC = mem_malloc;
57 alias MEM_PH_CALLOC = mem_calloc;
58 alias MEM_PH_FREE = mem_free;
59 alias MEM_PH_STRDUP = mem_strdup;
60 alias MEM_PARF_MALLOC = mem_malloc;
61 alias MEM_PARF_CALLOC = mem_calloc;
62 alias MEM_PARF_REALLOC = mem_realloc;
63 alias MEM_PARF_FREE = mem_free;
64 alias MEM_PARF_STRDUP = mem_strdup;
65 
66 version (SCPP_HTOD)
67     struct_t* struct_calloc();
68 else
69     struct_t* struct_calloc() { return cast(struct_t*) mem_calloc(struct_t.sizeof); }
70 
71 int REGSIZE();
72 
73 private __gshared
74 {
75     type *type_list;          // free list of types
76     param_t *param_list;      // free list of params
77 
78     int type_num,type_max;   /* gather statistics on # of types      */
79 }
80 
81 __gshared
82 {
83     type*[TYMAX] tstypes;
84     type*[TYMAX] tsptr2types;
85 
86     type* tstrace,tsclib,tsjlib,tsdlib,
87             tslogical;
88     type* tspvoid,tspcvoid;
89     type* tsptrdiff, tssize;
90 }
91 
92 /*******************************
93  * Compute size of type in bytes.
94  * Mark size as known after error message if it is not known.
95  * Instantiate templates as needed to compute size.
96  * Params:
97  *      t = type
98  * Returns:
99  *      size
100  */
101 
102 version (SCPP_HTOD)
103 {
104 targ_size_t type_size(type* t)
105 {
106     switch (tybasic(t.Tty))
107     {
108         case TYarray:
109             if (t.Tflags & TFsizeunknown)
110             {
111                 synerr(EM_unknown_size,"array".ptr);    /* size of array is unknown     */
112                 t.Tflags &= ~TFsizeunknown;
113             }
114             type_size(t.Tnext);
115             break;
116 
117         case TYstruct:
118             auto ts = t.Ttag.Stype;    // find main instance
119                                        // (for const struct X)
120             if (ts.Tflags & TFsizeunknown)
121             {
122                 template_instantiate_forward(ts.Ttag);
123                 if (ts.Tflags & TFsizeunknown)
124                     synerr(EM_unknown_size,ts.Tty & TYstruct ? prettyident(ts.Ttag) : "struct");
125                 ts.Tflags &= ~TFsizeunknown;
126             }
127             break;
128 
129         case TYenum:
130             if (t.Ttag.Senum.SEflags & SENforward)
131                 synerr(EM_unknown_size, prettyident(t.Ttag));
132             type_size(t.Tnext);
133             break;
134 
135         default:
136             break;
137     }
138     return type_size(cast(const)t);
139 }
140 }
141 
142 /***********************
143  * Compute size of type in bytes.
144  * Params:
145  *      t = type
146  * Returns:
147  *      size
148  */
149 targ_size_t type_size(const type *t)
150 {   targ_size_t s;
151     tym_t tyb;
152 
153     type_debug(t);
154     tyb = tybasic(t.Tty);
155 
156     debug if (tyb >= TYMAX)
157         /*type_print(t),*/
158         printf("tyb = x%x\n", tyb);
159 
160     assert(tyb < TYMAX);
161     s = _tysize[tyb];
162     if (s == cast(targ_size_t) -1)
163     {
164         switch (tyb)
165         {
166             // in case program plays games with function pointers
167             case TYffunc:
168             case TYfpfunc:
169             case TYfsfunc:
170             case TYf16func:
171             case TYhfunc:
172             case TYnfunc:       /* in case program plays games with function pointers */
173             case TYnpfunc:
174             case TYnsfunc:
175             case TYifunc:
176             case TYjfunc:
177 version (SCPP_HTOD)
178 {
179             case TYmfunc:
180                 if (config.ansi_c)
181                     synerr(EM_unknown_size,"function".ptr); /* size of function is not known */
182 }
183                 s = 1;
184                 break;
185             case TYarray:
186             {
187                 if (t.Tflags & TFsizeunknown)
188                 {
189 version (SCPP_HTOD)
190 {
191                     synerr(EM_unknown_size,"array".ptr);    /* size of array is unknown     */
192 }
193                 }
194                 if (t.Tflags & TFvla)
195                 {
196                     s = _tysize[pointertype];
197                     break;
198                 }
199                 s = type_size(t.Tnext);
200                 uint u = cast(uint)t.Tdim * cast(uint) s;
201 version (SCPP_HTOD)
202 {
203                 type_chksize(u);
204 }
205 else version (MARS)
206 {
207                 if (t.Tdim && ((u / t.Tdim) != s || cast(int)u < 0))
208                     assert(0);          // overflow should have been detected in front end
209 }
210 else
211 {
212                 static assert(0);
213 }
214                 s = u;
215                 break;
216             }
217             case TYstruct:
218             {
219                 auto ts = t.Ttag.Stype;     // find main instance
220                                             // (for const struct X)
221                 assert(ts.Ttag);
222                 s = ts.Ttag.Sstruct.Sstructsize;
223                 break;
224             }
225 version (SCPP_HTOD)
226 {
227             case TYenum:
228                 if (t.Ttag.Senum.SEflags & SENforward)
229                     synerr(EM_unknown_size, prettyident(cast(Symbol*)t.Ttag));
230                 s = type_size(t.Tnext);
231                 break;
232 }
233             case TYvoid:
234 version (SCPP_HTOD) static if (TARGET_WINDOS)   // GNUC allows it, so we will, too
235 {
236                 synerr(EM_void_novalue);        // voids have no value
237 }
238                 s = 1;
239                 break;
240 
241             case TYref:
242 version (MARS)
243 {
244                 s = tysize(TYnptr);
245                 break;
246 }
247 version (SCPP_HTOD)
248 {
249             case TYmemptr:
250             case TYvtshape:
251                 s = tysize(tym_conv(t));
252                 break;
253 
254             case TYident:
255                 synerr(EM_unknown_size, t.Tident);
256                 s = 1;
257                 break;
258 }
259 
260             default:
261                 debug WRTYxx(t.Tty);
262                 assert(0);
263         }
264     }
265     return s;
266 }
267 
268 /********************************
269  * Return the size of a type for alignment purposes.
270  */
271 
272 uint type_alignsize(type *t)
273 {   targ_size_t sz;
274 
275 L1:
276     type_debug(t);
277 
278     sz = tyalignsize(t.Tty);
279     if (sz == cast(targ_size_t)-1)
280     {
281         switch (tybasic(t.Tty))
282         {
283             case TYarray:
284                 if (t.Tflags & TFsizeunknown)
285                     goto err1;
286                 t = t.Tnext;
287                 goto L1;
288             case TYstruct:
289                 t = t.Ttag.Stype;         // find main instance
290                                             // (for const struct X)
291                 if (t.Tflags & TFsizeunknown)
292                     goto err1;
293                 sz = t.Ttag.Sstruct.Salignsize;
294                 if (sz > t.Ttag.Sstruct.Sstructalign + 1)
295                     sz = t.Ttag.Sstruct.Sstructalign + 1;
296                 break;
297 
298             case TYldouble:
299                 assert(0);
300 
301             default:
302             err1:                   // let type_size() handle error messages
303                 sz = type_size(t);
304                 break;
305         }
306     }
307 
308     //printf("type_alignsize() = %d\n", sz);
309     return cast(uint)sz;
310 }
311 
312 /***********************************
313  * Compute special zero sized struct.
314  * Params:
315  *      t = type of parameter
316  *      tyf = function type
317  * Returns:
318  *      true if it is
319  */
320 bool type_zeroSize(type *t, tym_t tyf)
321 {
322     if (tyf != TYjfunc && config.exe & (EX_FREEBSD | EX_OSX))
323     {
324         /* Use clang convention for 0 size structs
325          */
326         if (t && tybasic(t.Tty) == TYstruct)
327         {
328             type *ts = t.Ttag.Stype;     // find main instance
329                                            // (for const struct X)
330             if (ts.Tflags & TFsizeunknown)
331             {
332 version (SCPP_HTOD)
333 {
334                 template_instantiate_forward(ts.Ttag);
335                 if (ts.Tflags & TFsizeunknown)
336                     synerr(EM_unknown_size,ts.Tty & TYstruct ? prettyident(ts.Ttag) : "struct");
337                 ts.Tflags &= ~TFsizeunknown;
338 }
339             }
340             if (ts.Ttag.Sstruct.Sflags & STR0size)
341 //{ printf("0size\n"); type_print(t); *(char*)0=0;
342                 return true;
343 //}
344         }
345     }
346     return false;
347 }
348 
349 /*********************************
350  * Compute the size of a single parameter.
351  * Params:
352  *      t = type of parameter
353  *      tyf = function type
354  * Returns:
355  *      size in bytes
356  */
357 uint type_parameterSize(type *t, tym_t tyf)
358 {
359     if (type_zeroSize(t, tyf))
360         return 0;
361     return cast(uint)type_size(t);
362 }
363 
364 /*****************************
365  * Compute the total size of parameters for function call.
366  * Used for stdcall name mangling.
367  * Note that hidden parameters do not contribute to size.
368  * Params:
369  *   t = function type
370  * Returns:
371  *   total stack usage in bytes
372  */
373 
374 uint type_paramsize(type *t)
375 {
376     targ_size_t sz = 0;
377     if (tyfunc(t.Tty))
378     {
379         for (param_t *p = t.Tparamtypes; p; p = p.Pnext)
380         {
381             const size_t n = type_parameterSize(p.Ptype, tybasic(t.Tty));
382             sz += _align(REGSIZE,n);       // align to REGSIZE boundary
383         }
384     }
385     return cast(uint)sz;
386 }
387 
388 /*****************************
389  * Create a type & initialize it.
390  * Input:
391  *      ty = TYxxxx
392  * Returns:
393  *      pointer to newly created type.
394  */
395 
396 type *type_alloc(tym_t ty)
397 {   type *t;
398 
399     assert(tybasic(ty) != TYtemplate);
400     if (type_list)
401     {   t = type_list;
402         type_list = t.Tnext;
403     }
404     else
405         t = cast(type *) mem_fmalloc(type.sizeof);
406     *t = type();
407     t.Tty = ty;
408 version (SRCPOS_4TYPES)
409 {
410     if (PARSER && config.fulltypes)
411         t.Tsrcpos = getlinnum();
412 }
413 debug
414 {
415     t.id = type.IDtype;
416     type_num++;
417     if (type_num > type_max)
418         type_max = type_num;
419 }
420     //printf("type_alloc() = %p ",t); WRTYxx(t.Tty); printf("\n");
421     //if (t == (type*)0xB6B744) *(char*)0=0;
422     return t;
423 }
424 
425 /*************************************
426  * Allocate a TYtemplate.
427  */
428 
429 version (SCPP_HTOD)
430 {
431 type *type_alloc_template(Symbol *s)
432 {   type *t;
433 
434     t = cast(type *) mem_fmalloc(typetemp_t.sizeof);
435     memset(t, 0, typetemp_t.sizeof);
436     t.Tty = TYtemplate;
437     if (s.Stemplate.TMprimary)
438         s = s.Stemplate.TMprimary;
439     (cast(typetemp_t *)t).Tsym = s;
440 version (SRCPOS_4TYPES)
441 {
442     if (PARSER && config.fulltypes)
443         t.Tsrcpos = getlinnum();
444 }
445 debug
446 {
447     t.id = type.IDtype;
448     type_num++;
449     if (type_num > type_max)
450         type_max = type_num;
451     //printf("Alloc'ing template type %p ",t); WRTYxx(t.Tty); printf("\n");
452 }
453     return t;
454 }
455 }
456 
457 /*****************************
458  * Fake a type & initialize it.
459  * Input:
460  *      ty = TYxxxx
461  * Returns:
462  *      pointer to newly created type.
463  */
464 
465 type *type_fake(tym_t ty)
466 {   type *t;
467 
468 version (MARS)
469     assert(ty != TYstruct);
470 
471     t = type_alloc(ty);
472     if (typtr(ty) || tyfunc(ty))
473     {   t.Tnext = type_alloc(TYvoid);  /* fake with pointer to void    */
474         t.Tnext.Tcount = 1;
475     }
476     return t;
477 }
478 
479 /*****************************
480  * Allocate a type of ty with a Tnext of tn.
481  */
482 
483 type *type_allocn(tym_t ty,type *tn)
484 {   type *t;
485 
486     //printf("type_allocn(ty = x%x, tn = %p)\n", ty, tn);
487     assert(tn);
488     type_debug(tn);
489     t = type_alloc(ty);
490     t.Tnext = tn;
491     tn.Tcount++;
492     //printf("\tt = %p\n", t);
493     return t;
494 }
495 
496 /******************************
497  * Allocate a TYmemptr type.
498  */
499 
500 version (SCPP_HTOD)
501 {
502 type *type_allocmemptr(Classsym *stag,type *tn)
503 {   type *t;
504 
505     symbol_debug(stag);
506     assert(stag.Sclass == SCstruct || tybasic(stag.Stype.Tty) == TYident);
507     t = type_allocn(TYmemptr,tn);
508     t.Ttag = stag;
509     //printf("type_allocmemptr() = %p\n", t);
510     //type_print(t);
511     return t;
512 }
513 }
514 
515 /********************************
516  * Allocate a pointer type.
517  * Returns:
518  *      Tcount already incremented
519  */
520 
521 type *type_pointer(type *tnext)
522 {
523     type *t = type_allocn(TYnptr, tnext);
524     t.Tcount++;
525     return t;
526 }
527 
528 /********************************
529  * Allocate a dynamic array type.
530  * Returns:
531  *      Tcount already incremented
532  */
533 
534 type *type_dyn_array(type *tnext)
535 {
536     type *t = type_allocn(TYdarray, tnext);
537     t.Tcount++;
538     return t;
539 }
540 
541 /********************************
542  * Allocate a static array type.
543  * Returns:
544  *      Tcount already incremented
545  */
546 
547 extern (C) type *type_static_array(targ_size_t dim, type *tnext)
548 {
549     type *t = type_allocn(TYarray, tnext);
550     t.Tdim = dim;
551     t.Tcount++;
552     return t;
553 }
554 
555 /********************************
556  * Allocate an associative array type,
557  * which are key=value pairs
558  * Returns:
559  *      Tcount already incremented
560  */
561 
562 type *type_assoc_array(type *tkey, type *tvalue)
563 {
564     type *t = type_allocn(TYaarray, tvalue);
565     t.Tkey = tkey;
566     tkey.Tcount++;
567     t.Tcount++;
568     return t;
569 }
570 
571 /********************************
572  * Allocate a delegate type.
573  * Returns:
574  *      Tcount already incremented
575  */
576 
577 type *type_delegate(type *tnext)
578 {
579     type *t = type_allocn(TYdelegate, tnext);
580     t.Tcount++;
581     return t;
582 }
583 
584 /***********************************
585  * Allocation a function type.
586  * Params:
587  *      tyf      = function type
588  *      ptypes   = types of the function parameters
589  *      variadic = if ... function
590  *      tret     = return type
591  * Returns:
592  *      Tcount already incremented
593  */
594 extern (C)
595 type *type_function(tym_t tyf, type*[] ptypes, bool variadic, type *tret)
596 {
597     param_t *paramtypes = null;
598     foreach (p; ptypes)
599     {
600         param_append_type(&paramtypes, p);
601     }
602     type *t = type_allocn(tyf, tret);
603     t.Tflags |= TFprototype;
604     if (!variadic)
605         t.Tflags |= TFfixed;
606     t.Tparamtypes = paramtypes;
607     t.Tcount++;
608     return t;
609 }
610 
611 /***************************************
612  * Create an enum type.
613  * Input:
614  *      name    name of enum
615  *      tbase   "base" type of enum
616  * Returns:
617  *      Tcount already incremented
618  */
619 type *type_enum(const(char)* name, type *tbase)
620 {
621     Symbol *s = symbol_calloc(name);
622     s.Sclass = SCenum;
623     s.Senum = cast(enum_t *) MEM_PH_CALLOC(enum_t.sizeof);
624     s.Senum.SEflags |= SENforward;        // forward reference
625 
626     type *t = type_allocn(TYenum, tbase);
627     t.Ttag = cast(Classsym *)s;            // enum tag name
628     t.Tcount++;
629     s.Stype = t;
630     t.Tcount++;
631     return t;
632 }
633 
634 /**************************************
635  * Create a struct/union/class type.
636  * Params:
637  *      name = name of struct (this function makes its own copy of the string)
638  *      is0size = if struct has no fields (even if Sstructsize is 1)
639  * Returns:
640  *      Tcount already incremented
641  */
642 type *type_struct_class(const(char)* name, uint alignsize, uint structsize,
643         type *arg1type, type *arg2type, bool isUnion, bool isClass, bool isPOD, bool is0size)
644 {
645     Symbol *s = symbol_calloc(name);
646     s.Sclass = SCstruct;
647     s.Sstruct = struct_calloc();
648     s.Sstruct.Salignsize = alignsize;
649     s.Sstruct.Sstructalign = cast(ubyte)alignsize;
650     s.Sstruct.Sstructsize = structsize;
651     s.Sstruct.Sarg1type = arg1type;
652     s.Sstruct.Sarg2type = arg2type;
653 
654     if (!isPOD)
655         s.Sstruct.Sflags |= STRnotpod;
656     if (isUnion)
657         s.Sstruct.Sflags |= STRunion;
658     if (isClass)
659     {   s.Sstruct.Sflags |= STRclass;
660         assert(!isUnion && isPOD);
661     }
662     if (is0size)
663         s.Sstruct.Sflags |= STR0size;
664 
665     type *t = type_alloc(TYstruct);
666     t.Ttag = cast(Classsym *)s;            // structure tag name
667     t.Tcount++;
668     s.Stype = t;
669     t.Tcount++;
670     return t;
671 }
672 
673 /*****************************
674  * Free up data type.
675  */
676 
677 void type_free(type *t)
678 {   type *tn;
679     tym_t ty;
680 
681     while (t)
682     {
683         //printf("type_free(%p, Tcount = %d)\n", t, t.Tcount);
684         type_debug(t);
685         assert(cast(int)t.Tcount != -1);
686         if (--t.Tcount)                /* if usage count doesn't go to 0 */
687             break;
688         ty = tybasic(t.Tty);
689         if (tyfunc(ty))
690         {   param_free(&t.Tparamtypes);
691             list_free(&t.Texcspec, cast(list_free_fp)&type_free);
692             goto L1;
693         }
694 version (SCPP_HTOD)
695 {
696         if (ty == TYtemplate)
697         {
698             param_free(&t.Tparamtypes);
699             goto L1;
700         }
701         if (ty == TYident)
702         {
703             MEM_PH_FREE(t.Tident);
704             goto L1;
705         }
706 }
707         if (t.Tflags & TFvla && t.Tel)
708         {
709             el_free(t.Tel);
710             goto L1;
711         }
712 version (SCPP_HTOD)
713 {
714         if (t.Talternate && typtr(ty))
715         {
716             type_free(t.Talternate);
717             goto L1;
718         }
719 }
720 version (MARS)
721 {
722         if (t.Tkey && typtr(ty))
723             type_free(t.Tkey);
724 }
725       L1:
726 
727 debug
728 {
729         type_num--;
730         //printf("Free'ing type %p ",t); WRTYxx(t.Tty); printf("\n");
731         t.id = 0;                      /* no longer a valid type       */
732 }
733 
734         tn = t.Tnext;
735         t.Tnext = type_list;
736         type_list = t;                  /* link into free list          */
737         t = tn;
738     }
739 }
740 
741 version (STATS)
742 {
743 /* count number of free types available on type list */
744 void type_count_free()
745     {
746     type *t;
747     int count;
748 
749     for(t=type_list;t;t=t.Tnext)
750         count++;
751     printf("types on free list %d with max of %d\n",count,type_max);
752     }
753 }
754 
755 /**********************************
756  * Initialize type package.
757  */
758 
759 private type * type_allocbasic(tym_t ty)
760 {   type *t;
761 
762     t = type_alloc(ty);
763     t.Tmangle = mTYman_c;
764     t.Tcount = 1;              /* so it is not inadvertently free'd    */
765     return t;
766 }
767 
768 void type_init()
769 {
770     tstypes[TYbool]    = type_allocbasic(TYbool);
771     tstypes[TYwchar_t] = type_allocbasic(TYwchar_t);
772     tstypes[TYdchar]   = type_allocbasic(TYdchar);
773     tstypes[TYvoid]    = type_allocbasic(TYvoid);
774     tstypes[TYnullptr] = type_allocbasic(TYnullptr);
775     tstypes[TYchar16]  = type_allocbasic(TYchar16);
776     tstypes[TYuchar]   = type_allocbasic(TYuchar);
777     tstypes[TYschar]   = type_allocbasic(TYschar);
778     tstypes[TYchar]    = type_allocbasic(TYchar);
779     tstypes[TYshort]   = type_allocbasic(TYshort);
780     tstypes[TYushort]  = type_allocbasic(TYushort);
781     tstypes[TYint]     = type_allocbasic(TYint);
782     tstypes[TYuint]    = type_allocbasic(TYuint);
783     tstypes[TYlong]    = type_allocbasic(TYlong);
784     tstypes[TYulong]   = type_allocbasic(TYulong);
785     tstypes[TYllong]   = type_allocbasic(TYllong);
786     tstypes[TYullong]  = type_allocbasic(TYullong);
787     tstypes[TYfloat]   = type_allocbasic(TYfloat);
788     tstypes[TYdouble]  = type_allocbasic(TYdouble);
789     tstypes[TYdouble_alias]  = type_allocbasic(TYdouble_alias);
790     tstypes[TYldouble] = type_allocbasic(TYldouble);
791     tstypes[TYifloat]  = type_allocbasic(TYifloat);
792     tstypes[TYidouble] = type_allocbasic(TYidouble);
793     tstypes[TYildouble] = type_allocbasic(TYildouble);
794     tstypes[TYcfloat]   = type_allocbasic(TYcfloat);
795     tstypes[TYcdouble]  = type_allocbasic(TYcdouble);
796     tstypes[TYcldouble] = type_allocbasic(TYcldouble);
797 
798     if (I64)
799     {
800         TYptrdiff = TYllong;
801         TYsize = TYullong;
802         tsptrdiff = tstypes[TYllong];
803         tssize = tstypes[TYullong];
804     }
805     else
806     {
807         TYptrdiff = TYint;
808         TYsize = TYuint;
809         tsptrdiff = tstypes[TYint];
810         tssize = tstypes[TYuint];
811     }
812 
813     // Type of trace function
814     tstrace = type_fake(I16 ? TYffunc : TYnfunc);
815     tstrace.Tmangle = mTYman_c;
816     tstrace.Tcount++;
817 
818     chartype = (config.flags3 & CFG3ju) ? tstypes[TYuchar] : tstypes[TYchar];
819 
820     // Type of far library function
821     tsclib = type_fake(LARGECODE ? TYfpfunc : TYnpfunc);
822     tsclib.Tmangle = mTYman_c;
823     tsclib.Tcount++;
824 
825     tspvoid = type_allocn(pointertype,tstypes[TYvoid]);
826     tspvoid.Tmangle = mTYman_c;
827     tspvoid.Tcount++;
828 
829     // Type of far library function
830     tsjlib =    type_fake(TYjfunc);
831     tsjlib.Tmangle = mTYman_c;
832     tsjlib.Tcount++;
833 
834     tsdlib = tsjlib;
835 
836 version (SCPP_HTOD)
837 {
838     tspcvoid = type_alloc(mTYconst | TYvoid);
839     tspcvoid = newpointer(tspcvoid);
840     tspcvoid.Tmangle = mTYman_c;
841     tspcvoid.Tcount++;
842 }
843 
844     // Type of logical expression
845     tslogical = (config.flags4 & CFG4bool) ? tstypes[TYbool] : tstypes[TYint];
846 
847     for (int i = 0; i < TYMAX; i++)
848     {
849         if (tstypes[i])
850         {   tsptr2types[i] = type_allocn(pointertype,tstypes[i]);
851             tsptr2types[i].Tcount++;
852         }
853     }
854 }
855 
856 /**********************************
857  * Free type_list.
858  */
859 
860 void type_term()
861 {
862 static if (TERMCODE)
863 {
864     type *tn;
865     param_t *pn;
866     int i;
867 
868     for (i = 0; i < tstypes.length; i++)
869     {   type *t = tsptr2types[i];
870 
871         if (t)
872         {   assert(!(t.Tty & (mTYconst | mTYvolatile | mTYimmutable | mTYshared)));
873             assert(!(t.Tflags));
874             assert(!(t.Tmangle));
875             type_free(t);
876         }
877         type_free(tstypes[i]);
878     }
879 
880     type_free(tsclib);
881     type_free(tspvoid);
882     type_free(tspcvoid);
883     type_free(tsjlib);
884     type_free(tstrace);
885 
886     while (type_list)
887     {   tn = type_list.Tnext;
888         mem_ffree(type_list);
889         type_list = tn;
890     }
891 
892     while (param_list)
893     {   pn = param_list.Pnext;
894         mem_ffree(param_list);
895         param_list = pn;
896     }
897 
898 debug
899 {
900     printf("Max # of types = %d\n",type_max);
901     if (type_num != 0)
902         printf("type_num = %d\n",type_num);
903 /*    assert(type_num == 0);*/
904 }
905 
906 }
907 }
908 
909 /*******************************
910  * Type type information.
911  */
912 
913 /**************************
914  * Make copy of a type.
915  */
916 
917 type *type_copy(type *t)
918 {   type *tn;
919     param_t *p;
920 
921     type_debug(t);
922 version (SCPP_HTOD)
923 {
924     if (tybasic(t.Tty) == TYtemplate)
925     {
926         tn = type_alloc_template((cast(typetemp_t *)t).Tsym);
927     }
928     else
929         tn = type_alloc(t.Tty);
930 }
931 else
932         tn = type_alloc(t.Tty);
933 
934     *tn = *t;
935     switch (tybasic(tn.Tty))
936     {
937 version (SCPP_HTOD)
938 {
939             case TYtemplate:
940                 (cast(typetemp_t *)tn).Tsym = (cast(typetemp_t *)t).Tsym;
941                 goto L1;
942 
943             case TYident:
944                 tn.Tident = cast(char *)MEM_PH_STRDUP(t.Tident);
945                 break;
946 }
947 
948             case TYarray:
949                 if (tn.Tflags & TFvla)
950                     tn.Tel = el_copytree(tn.Tel);
951                 break;
952 
953             default:
954                 if (tyfunc(tn.Tty))
955                 {
956                 L1:
957                     tn.Tparamtypes = null;
958                     for (p = t.Tparamtypes; p; p = p.Pnext)
959                     {   param_t *pn;
960 
961                         pn = param_append_type(&tn.Tparamtypes,p.Ptype);
962                         if (p.Pident)
963                         {
964                             pn.Pident = cast(char *)MEM_PH_STRDUP(p.Pident);
965                         }
966                         assert(!p.Pelem);
967                     }
968                 }
969                 else
970                 {
971 version (SCPP_HTOD)
972 {
973                 if (tn.Talternate && typtr(tn.Tty))
974                     tn.Talternate.Tcount++;
975 }
976 version (MARS)
977 {
978                 if (tn.Tkey && typtr(tn.Tty))
979                     tn.Tkey.Tcount++;
980 }
981                 }
982                 break;
983     }
984     if (tn.Tnext)
985     {   type_debug(tn.Tnext);
986         tn.Tnext.Tcount++;
987     }
988     tn.Tcount = 0;
989     return tn;
990 }
991 
992 /************************************
993  */
994 
995 version (SCPP_HTOD)
996 {
997 
998 elem *type_vla_fix(type **pt)
999 {
1000     type *t;
1001     elem *e = null;
1002 
1003     for (t = *pt; t; t = t.Tnext)
1004     {
1005         type_debug(t);
1006         if (tybasic(t.Tty) == TYarray && t.Tflags & TFvla && t.Tel)
1007         {   Symbol *s;
1008             elem *ec;
1009 
1010             s = symbol_genauto(tstypes[TYuint]);
1011             ec = el_var(s);
1012             ec = el_bint(OPeq, tstypes[TYuint], ec, t.Tel);
1013             e = el_combine(e, ec);
1014             t.Tel = el_var(s);
1015         }
1016     }
1017     return e;
1018 }
1019 
1020 }
1021 
1022 /****************************
1023  * Modify the tym_t field of a type.
1024  */
1025 
1026 type *type_setty(type **pt,uint newty)
1027 {   type *t;
1028 
1029     t = *pt;
1030     type_debug(t);
1031     if (cast(tym_t)newty != t.Tty)
1032     {   if (t.Tcount > 1)              /* if other people pointing at t */
1033         {   type *tn;
1034 
1035             tn = type_copy(t);
1036             tn.Tcount++;
1037             type_free(t);
1038             t = tn;
1039             *pt = t;
1040         }
1041         t.Tty = newty;
1042     }
1043     return t;
1044 }
1045 
1046 /******************************
1047  * Set type field of some object to t.
1048  */
1049 
1050 type *type_settype(type **pt, type *t)
1051 {
1052     if (t)
1053     {   type_debug(t);
1054         t.Tcount++;
1055     }
1056     type_free(*pt);
1057     return *pt = t;
1058 }
1059 
1060 /****************************
1061  * Modify the Tmangle field of a type.
1062  */
1063 
1064 type *type_setmangle(type **pt,mangle_t mangle)
1065 {   type *t;
1066 
1067     t = *pt;
1068     type_debug(t);
1069     if (mangle != type_mangle(t))
1070     {
1071         if (t.Tcount > 1)              // if other people pointing at t
1072         {   type *tn;
1073 
1074             tn = type_copy(t);
1075             tn.Tcount++;
1076             type_free(t);
1077             t = tn;
1078             *pt = t;
1079         }
1080         t.Tmangle = mangle;
1081     }
1082     return t;
1083 }
1084 
1085 /******************************
1086  * Set/clear const and volatile bits in *pt according to the settings
1087  * in cv.
1088  */
1089 
1090 type *type_setcv(type **pt,tym_t cv)
1091 {   uint ty;
1092 
1093     type_debug(*pt);
1094     ty = (*pt).Tty & ~(mTYconst | mTYvolatile | mTYimmutable | mTYshared);
1095     return type_setty(pt,ty | (cv & (mTYconst | mTYvolatile | mTYimmutable | mTYshared)));
1096 }
1097 
1098 /*****************************
1099  * Set dimension of array.
1100  */
1101 
1102 type *type_setdim(type **pt,targ_size_t dim)
1103 {   type *t = *pt;
1104 
1105     type_debug(t);
1106     if (t.Tcount > 1)                  /* if other people pointing at t */
1107     {   type *tn;
1108 
1109         tn = type_copy(t);
1110         tn.Tcount++;
1111         type_free(t);
1112         t = tn;
1113     }
1114     t.Tflags &= ~TFsizeunknown; /* we have determined its size */
1115     t.Tdim = dim;              /* index of array               */
1116     return *pt = t;
1117 }
1118 
1119 
1120 /*****************************
1121  * Create a 'dependent' version of type t.
1122  */
1123 
1124 type *type_setdependent(type *t)
1125 {
1126     type_debug(t);
1127     if (t.Tcount > 0 &&                        /* if other people pointing at t */
1128         !(t.Tflags & TFdependent))
1129     {
1130         t = type_copy(t);
1131     }
1132     t.Tflags |= TFdependent;
1133     return t;
1134 }
1135 
1136 /************************************
1137  * Determine if type t is a dependent type.
1138  */
1139 
1140 int type_isdependent(type *t)
1141 {
1142     Symbol *stempl;
1143     type *tstart;
1144 
1145     //printf("type_isdependent(%p)\n", t);
1146     //type_print(t);
1147     for (tstart = t; t; t = t.Tnext)
1148     {
1149         type_debug(t);
1150         if (t.Tflags & TFdependent)
1151             goto Lisdependent;
1152         if (tyfunc(t.Tty)
1153                 || tybasic(t.Tty) == TYtemplate
1154                 )
1155         {
1156             for (param_t *p = t.Tparamtypes; p; p = p.Pnext)
1157             {
1158                 if (p.Ptype && type_isdependent(p.Ptype))
1159                     goto Lisdependent;
1160                 if (p.Pelem && el_isdependent(p.Pelem))
1161                     goto Lisdependent;
1162             }
1163         }
1164         else if (type_struct(t) &&
1165                  (stempl = t.Ttag.Sstruct.Stempsym) != null)
1166         {
1167             for (param_t *p = t.Ttag.Sstruct.Sarglist; p; p = p.Pnext)
1168             {
1169                 if (p.Ptype && type_isdependent(p.Ptype))
1170                     goto Lisdependent;
1171                 if (p.Pelem && el_isdependent(p.Pelem))
1172                     goto Lisdependent;
1173             }
1174         }
1175     }
1176     //printf("\tis not dependent\n");
1177     return 0;
1178 
1179 Lisdependent:
1180     //printf("\tis dependent\n");
1181     // Dependence on a dependent type makes this type dependent as well
1182     tstart.Tflags |= TFdependent;
1183     return 1;
1184 }
1185 
1186 
1187 /*******************************
1188  * Recursively check if type u is embedded in type t.
1189  * Returns:
1190  *      != 0 if embedded
1191  */
1192 
1193 int type_embed(type *t,type *u)
1194 {   param_t *p;
1195 
1196     for (; t; t = t.Tnext)
1197     {
1198         type_debug(t);
1199         if (t == u)
1200             return 1;
1201         if (tyfunc(t.Tty))
1202         {
1203             for (p = t.Tparamtypes; p; p = p.Pnext)
1204                 if (type_embed(p.Ptype,u))
1205                     return 1;
1206         }
1207     }
1208     return 0;
1209 }
1210 
1211 
1212 /***********************************
1213  * Determine if type is a VLA.
1214  */
1215 
1216 int type_isvla(type *t)
1217 {
1218     while (t)
1219     {
1220         if (tybasic(t.Tty) != TYarray)
1221             break;
1222         if (t.Tflags & TFvla)
1223             return 1;
1224         t = t.Tnext;
1225     }
1226     return 0;
1227 }
1228 
1229 
1230 /**********************************
1231  * Pretty-print a type.
1232  */
1233 
1234 void type_print(const type *t)
1235 {
1236   type_debug(t);
1237   printf("Tty="); WRTYxx(t.Tty);
1238   printf(" Tmangle=%d",t.Tmangle);
1239   printf(" Tflags=x%x",t.Tflags);
1240   printf(" Tcount=%d",t.Tcount);
1241   if (!(t.Tflags & TFsizeunknown) &&
1242         tybasic(t.Tty) != TYvoid &&
1243         tybasic(t.Tty) != TYident &&
1244         tybasic(t.Tty) != TYtemplate &&
1245         tybasic(t.Tty) != TYmfunc &&
1246         tybasic(t.Tty) != TYarray)
1247       printf(" Tsize=%lld", cast(long)type_size(t));
1248   printf(" Tnext=%p",t.Tnext);
1249   switch (tybasic(t.Tty))
1250   {     case TYstruct:
1251         case TYmemptr:
1252             printf(" Ttag=%p,'%s'",t.Ttag,t.Ttag.Sident.ptr);
1253             //printf(" Sfldlst=%p",t.Ttag.Sstruct.Sfldlst);
1254             break;
1255 
1256         case TYarray:
1257             printf(" Tdim=%lld", cast(long)t.Tdim);
1258             break;
1259 
1260         case TYident:
1261             printf(" Tident='%s'",t.Tident);
1262             break;
1263         case TYtemplate:
1264             printf(" Tsym='%s'",(cast(typetemp_t *)t).Tsym.Sident.ptr);
1265             {
1266                 int i;
1267 
1268                 i = 1;
1269                 for (const(param_t)* p = t.Tparamtypes; p; p = p.Pnext)
1270                 {   printf("\nTP%d (%p): ",i++,p);
1271                     fflush(stdout);
1272 
1273 printf("Pident=%p,Ptype=%p,Pelem=%p,Pnext=%p ",p.Pident,p.Ptype,p.Pelem,p.Pnext);
1274                     param_debug(p);
1275                     if (p.Pident)
1276                         printf("'%s' ", p.Pident);
1277                     if (p.Ptype)
1278                         type_print(p.Ptype);
1279                     if (p.Pelem)
1280                         elem_print(p.Pelem);
1281                 }
1282             }
1283             break;
1284 
1285         default:
1286             if (tyfunc(t.Tty))
1287             {
1288                 int i;
1289 
1290                 i = 1;
1291                 for (const(param_t)* p = t.Tparamtypes; p; p = p.Pnext)
1292                 {   printf("\nP%d (%p): ",i++,p);
1293                     fflush(stdout);
1294 
1295 printf("Pident=%p,Ptype=%p,Pelem=%p,Pnext=%p ",p.Pident,p.Ptype,p.Pelem,p.Pnext);
1296                     param_debug(p);
1297                     if (p.Pident)
1298                         printf("'%s' ", p.Pident);
1299                     type_print(p.Ptype);
1300                 }
1301             }
1302             break;
1303   }
1304   printf("\n");
1305   if (t.Tnext) type_print(t.Tnext);
1306 }
1307 
1308 /*******************************
1309  * Pretty-print a param_t
1310  */
1311 
1312 void param_t_print(const param_t* p)
1313 {
1314     printf("Pident=%p,Ptype=%p,Pelem=%p,Psym=%p,Pnext=%p\n",p.Pident,p.Ptype,p.Pelem,p.Psym,p.Pnext);
1315     if (p.Pident)
1316         printf("\tPident = '%s'\n", p.Pident);
1317     if (p.Ptype)
1318     {   printf("\tPtype =\n");
1319         type_print(p.Ptype);
1320     }
1321     if (p.Pelem)
1322     {   printf("\tPelem =\n");
1323         elem_print(p.Pelem);
1324     }
1325     if (p.Pdeftype)
1326     {   printf("\tPdeftype =\n");
1327         type_print(p.Pdeftype);
1328     }
1329     if (p.Psym)
1330     {   printf("\tPsym = '%s'\n", p.Psym.Sident.ptr);
1331     }
1332     if (p.Pptpl)
1333     {   printf("\tPptpl = %p\n", p.Pptpl);
1334     }
1335 }
1336 
1337 void param_t_print_list(param_t* p)
1338 {
1339     for (; p; p = p.Pnext)
1340         p.print();
1341 }
1342 
1343 
1344 /**********************************
1345  * Hydrate a type.
1346  */
1347 
1348 version (SCPP_HTOD)
1349 {
1350 
1351 static if (HYDRATE)
1352 {
1353 void type_hydrate(type **pt)
1354 {
1355     type *t;
1356 
1357     assert(pt);
1358     while (isdehydrated(*pt))
1359     {
1360         t = cast(type *) ph_hydrate(cast(void**)pt);
1361         type_debug(t);
1362         switch (tybasic(t.Tty))
1363         {
1364             case TYstruct:
1365             case TYenum:
1366             case TYmemptr:
1367             case TYvtshape:
1368                 // Cannot assume symbol is hydrated, because entire HX file
1369                 // may not have been hydrated.
1370                 Classsym_hydrate(&t.Ttag);
1371                 symbol_debug(t.Ttag);
1372                 break;
1373             case TYident:
1374                 ph_hydrate(cast(void**)&t.Tident);
1375                 break;
1376             case TYtemplate:
1377                 symbol_hydrate(&(cast(typetemp_t *)t).Tsym);
1378                 param_hydrate(&t.Tparamtypes);
1379                 break;
1380             case TYarray:
1381                 if (t.Tflags & TFvla)
1382                     el_hydrate(&t.Tel);
1383                 break;
1384             default:
1385                 if (tyfunc(t.Tty))
1386                 {   param_hydrate(&t.Tparamtypes);
1387                     list_hydrate(&t.Texcspec, cast(list_free_fp)&type_hydrate);
1388                 }
1389                 else if (t.Talternate && typtr(t.Tty))
1390                     type_hydrate(&t.Talternate);
1391                 else if (t.Tkey && typtr(t.Tty))
1392                     type_hydrate(&t.Tkey);
1393                 break;
1394         }
1395         pt = &t.Tnext;
1396     }
1397 }
1398 }
1399 
1400 /**********************************
1401  * Dehydrate a type.
1402  */
1403 
1404 static if (DEHYDRATE)
1405 {
1406 void type_dehydrate(type **pt)
1407 {
1408     type *t;
1409 
1410     while ((t = *pt) != null && !isdehydrated(t))
1411     {
1412         ph_dehydrate(pt);
1413 version (DEBUG_XSYMGEN)
1414 {
1415         /* don't dehydrate types in HEAD when creating XSYM */
1416         if (xsym_gen && (t.Tflags & TFhydrated))
1417             return;
1418 }
1419         type_debug(t);
1420         switch (tybasic(t.Tty))
1421         {
1422             case TYstruct:
1423             case TYenum:
1424             case TYmemptr:
1425             case TYvtshape:
1426                 Classsym_dehydrate(&t.Ttag);
1427                 break;
1428             case TYident:
1429                 ph_dehydrate(&t.Tident);
1430                 break;
1431             case TYtemplate:
1432                 symbol_dehydrate(&(cast(typetemp_t *)t).Tsym);
1433                 param_dehydrate(&t.Tparamtypes);
1434                 break;
1435             case TYarray:
1436                 if (t.Tflags & TFvla)
1437                     el_dehydrate(&t.Tel);
1438                 break;
1439             default:
1440                 if (tyfunc(t.Tty))
1441                 {   param_dehydrate(&t.Tparamtypes);
1442                     list_dehydrate(&t.Texcspec, cast(list_free_fp)&type_dehydrate);
1443                 }
1444                 else if (t.Talternate && typtr(t.Tty))
1445                     type_dehydrate(&t.Talternate);
1446                 else if (t.Tkey && typtr(t.Tty))
1447                     type_dehydrate(&t.Tkey);
1448                 break;
1449         }
1450         pt = &t.Tnext;
1451     }
1452 }
1453 }
1454 
1455 }
1456 
1457 /****************************
1458  * Allocate a param_t.
1459  */
1460 
1461 param_t *param_calloc()
1462 {
1463     static param_t pzero;
1464     param_t *p;
1465 
1466     if (param_list)
1467     {
1468         p = param_list;
1469         param_list = p.Pnext;
1470     }
1471     else
1472     {
1473         p = cast(param_t *) mem_fmalloc(param_t.sizeof);
1474     }
1475     *p = pzero;
1476 
1477     debug p.id = param_t.IDparam;
1478 
1479     return p;
1480 }
1481 
1482 /***************************
1483  * Allocate a param_t of type t, and append it to parameter list.
1484  */
1485 
1486 param_t *param_append_type(param_t **pp,type *t)
1487 {   param_t *p;
1488 
1489     p = param_calloc();
1490     while (*pp)
1491     {   param_debug(*pp);
1492         pp = &((*pp).Pnext);   /* find end of list     */
1493     }
1494     *pp = p;                    /* append p to list     */
1495     type_debug(t);
1496     p.Ptype = t;
1497     t.Tcount++;
1498     return p;
1499 }
1500 
1501 /************************
1502  * Version of param_free() suitable for list_free().
1503  */
1504 
1505 void param_free_l(param_t *p)
1506 {
1507     param_free(&p);
1508 }
1509 
1510 /***********************
1511  * Free parameter list.
1512  * Output:
1513  *      paramlst = null
1514  */
1515 
1516 void param_free(param_t **pparamlst)
1517 {   param_t* p,pn;
1518 
1519     //debug_assert(PARSER);
1520     for (p = *pparamlst; p; p = pn)
1521     {   param_debug(p);
1522         pn = p.Pnext;
1523         type_free(p.Ptype);
1524         mem_free(p.Pident);
1525         el_free(p.Pelem);
1526         type_free(p.Pdeftype);
1527         if (p.Pptpl)
1528             param_free(&p.Pptpl);
1529 
1530         debug p.id = 0;
1531 
1532         p.Pnext = param_list;
1533         param_list = p;
1534     }
1535     *pparamlst = null;
1536 }
1537 
1538 /***********************************
1539  * Compute number of parameters
1540  */
1541 
1542 uint param_t_length(param_t* p)
1543 {
1544     uint nparams = 0;
1545 
1546     for (; p; p = p.Pnext)
1547         nparams++;
1548     return nparams;
1549 }
1550 
1551 /*************************************
1552  * Create template-argument-list blank from
1553  * template-parameter-list
1554  * Input:
1555  *      ptali   initial template-argument-list
1556  */
1557 
1558 param_t *param_t_createTal(param_t* p, param_t *ptali)
1559 {
1560 version (SCPP_HTOD)
1561 {
1562     param_t *ptalistart = ptali;
1563     param_t *pstart = p;
1564 }
1565     param_t *ptal = null;
1566     param_t **pp = &ptal;
1567 
1568     for (; p; p = p.Pnext)
1569     {
1570         *pp = param_calloc();
1571         if (p.Pident)
1572         {
1573             // Should find a way to just point rather than dup
1574             (*pp).Pident = cast(char *)MEM_PH_STRDUP(p.Pident);
1575         }
1576         if (ptali)
1577         {
1578             if (ptali.Ptype)
1579             {   (*pp).Ptype = ptali.Ptype;
1580                 (*pp).Ptype.Tcount++;
1581             }
1582             if (ptali.Pelem)
1583             {
1584                 elem *e = el_copytree(ptali.Pelem);
1585 version (SCPP_HTOD)
1586 {
1587                 if (p.Ptype)
1588                 {   type *t = p.Ptype;
1589                     t = template_tyident(t, ptalistart, pstart, 1);
1590                     e = poptelem3(typechk(e, t));
1591                     type_free(t);
1592                 }
1593 }
1594                 (*pp).Pelem = e;
1595             }
1596             (*pp).Psym = ptali.Psym;
1597             (*pp).Pflags = ptali.Pflags;
1598             assert(!ptali.Pptpl);
1599             ptali = ptali.Pnext;
1600         }
1601         pp = &(*pp).Pnext;
1602     }
1603     return ptal;
1604 }
1605 
1606 /**********************************
1607  * Look for Pident matching id
1608  */
1609 
1610 param_t *param_t_search(param_t* p, char *id)
1611 {
1612     for (; p; p = p.Pnext)
1613     {
1614         if (p.Pident && strcmp(p.Pident, id) == 0)
1615             break;
1616     }
1617     return p;
1618 }
1619 
1620 /**********************************
1621  * Look for Pident matching id
1622  */
1623 
1624 int param_t_searchn(param_t* p, char *id)
1625 {
1626     int n = 0;
1627 
1628     for (; p; p = p.Pnext)
1629     {
1630         if (p.Pident && strcmp(p.Pident, id) == 0)
1631             return n;
1632         n++;
1633     }
1634     return -1;
1635 }
1636 
1637 /*************************************
1638  * Search for member, create symbol as needed.
1639  * Used for symbol tables for VLA's such as:
1640  *      void func(int n, int a[n]);
1641  */
1642 
1643 Symbol *param_search(const(char)* name, param_t **pp)
1644 {   Symbol *s = null;
1645     param_t *p;
1646 
1647     p = (*pp).search(cast(char *)name);
1648     if (p)
1649     {
1650         s = p.Psym;
1651         if (!s)
1652         {
1653             s = symbol_calloc(p.Pident);
1654             s.Sclass = SCparameter;
1655             s.Stype = p.Ptype;
1656             s.Stype.Tcount++;
1657             p.Psym = s;
1658         }
1659     }
1660     return s;
1661 }
1662 
1663 /**********************************
1664  * Hydrate/dehydrate a type.
1665  */
1666 
1667 version (SCPP_HTOD)
1668 {
1669 static if (HYDRATE)
1670 {
1671 void param_hydrate(param_t **pp)
1672 {
1673     param_t *p;
1674 
1675     assert(pp);
1676     if (isdehydrated(*pp))
1677     {   while (*pp)
1678         {   assert(isdehydrated(*pp));
1679             p = cast(param_t *) ph_hydrate(cast(void**)pp);
1680             param_debug(p);
1681 
1682             type_hydrate(&p.Ptype);
1683             if (p.Ptype)
1684                 type_debug(p.Ptype);
1685             ph_hydrate(cast(void**)&p.Pident);
1686             if (CPP)
1687             {
1688                 el_hydrate(&p.Pelem);
1689                 if (p.Pelem)
1690                     elem_debug(p.Pelem);
1691                 type_hydrate(&p.Pdeftype);
1692                 if (p.Pptpl)
1693                     param_hydrate(&p.Pptpl);
1694                 if (p.Psym)
1695                     symbol_hydrate(&p.Psym);
1696                 if (p.PelemToken)
1697                     token_hydrate(&p.PelemToken);
1698             }
1699 
1700             pp = &p.Pnext;
1701         }
1702     }
1703 }
1704 }
1705 
1706 static if (DEHYDRATE)
1707 {
1708 void param_dehydrate(param_t **pp)
1709 {
1710     param_t *p;
1711 
1712     assert(pp);
1713     while ((p = *pp) != null && !isdehydrated(p))
1714     {   param_debug(p);
1715 
1716         ph_dehydrate(pp);
1717         if (p.Ptype && !isdehydrated(p.Ptype))
1718             type_debug(p.Ptype);
1719         type_dehydrate(&p.Ptype);
1720         ph_dehydrate(&p.Pident);
1721         if (CPP)
1722         {
1723             el_dehydrate(&p.Pelem);
1724             type_dehydrate(&p.Pdeftype);
1725             if (p.Pptpl)
1726                 param_dehydrate(&p.Pptpl);
1727             if (p.Psym)
1728                 symbol_dehydrate(&p.Psym);
1729             if (p.PelemToken)
1730                 token_dehydrate(&p.PelemToken);
1731         }
1732         pp = &p.Pnext;
1733     }
1734 }
1735 }
1736 }
1737 
1738 version (MARS)
1739 {
1740 
1741 int typematch(type *t1, type *t2, int relax);
1742 
1743 // Return TRUE if type lists match.
1744 private int paramlstmatch(param_t *p1,param_t *p2)
1745 {
1746         return p1 == p2 ||
1747             p1 && p2 && typematch(p1.Ptype,p2.Ptype,0) &&
1748             paramlstmatch(p1.Pnext,p2.Pnext)
1749             ;
1750 }
1751 
1752 /*************************************************
1753  * A cheap version of exp2.typematch() and exp2.paramlstmatch(),
1754  * so that we can get cpp_mangle() to work for MARS.
1755  * It's less complex because it doesn't do templates and
1756  * can rely on strict typechecking.
1757  * Returns:
1758  *      !=0 if types match.
1759  */
1760 
1761 int typematch(type *t1,type *t2,int relax)
1762 { tym_t t1ty, t2ty;
1763   tym_t tym;
1764 
1765   tym = ~(mTYimport | mTYnaked);
1766 
1767   return t1 == t2 ||
1768             t1 && t2 &&
1769 
1770             (
1771                 /* ignore name mangling */
1772                 (t1ty = (t1.Tty & tym)) == (t2ty = (t2.Tty & tym))
1773             )
1774                  &&
1775 
1776             (tybasic(t1ty) != TYarray || t1.Tdim == t2.Tdim ||
1777              t1.Tflags & TFsizeunknown || t2.Tflags & TFsizeunknown)
1778                  &&
1779 
1780             (tybasic(t1ty) != TYstruct
1781                 && tybasic(t1ty) != TYenum
1782                 && tybasic(t1ty) != TYmemptr
1783              || t1.Ttag == t2.Ttag)
1784                  &&
1785 
1786             typematch(t1.Tnext,t2.Tnext, 0)
1787                  &&
1788 
1789             (!tyfunc(t1ty) ||
1790              ((t1.Tflags & TFfixed) == (t2.Tflags & TFfixed) &&
1791                  paramlstmatch(t1.Tparamtypes,t2.Tparamtypes) ))
1792          ;
1793 }
1794 
1795 }
1796 
1797 }