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-2020 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     __gshared type tzero;
399 
400     assert(tybasic(ty) != TYtemplate);
401     if (type_list)
402     {   t = type_list;
403         type_list = t.Tnext;
404     }
405     else
406         t = cast(type *) mem_fmalloc(type.sizeof);
407     tzero.Tty = ty;
408     *t = tzero;
409 version (SRCPOS_4TYPES)
410 {
411     if (PARSER && config.fulltypes)
412         t.Tsrcpos = getlinnum();
413 }
414 debug
415 {
416     t.id = type.IDtype;
417     type_num++;
418     if (type_num > type_max)
419         type_max = type_num;
420 }
421     //printf("type_alloc() = %p ",t); WRTYxx(t.Tty); printf("\n");
422     //if (t == (type*)0xB6B744) *(char*)0=0;
423     return t;
424 }
425 
426 /*************************************
427  * Allocate a TYtemplate.
428  */
429 
430 version (SCPP_HTOD)
431 {
432 type *type_alloc_template(Symbol *s)
433 {   type *t;
434 
435     t = cast(type *) mem_fmalloc(typetemp_t.sizeof);
436     memset(t, 0, typetemp_t.sizeof);
437     t.Tty = TYtemplate;
438     if (s.Stemplate.TMprimary)
439         s = s.Stemplate.TMprimary;
440     (cast(typetemp_t *)t).Tsym = s;
441 version (SRCPOS_4TYPES)
442 {
443     if (PARSER && config.fulltypes)
444         t.Tsrcpos = getlinnum();
445 }
446 debug
447 {
448     t.id = type.IDtype;
449     type_num++;
450     if (type_num > type_max)
451         type_max = type_num;
452     //printf("Alloc'ing template type %p ",t); WRTYxx(t.Tty); printf("\n");
453 }
454     return t;
455 }
456 }
457 
458 /*****************************
459  * Fake a type & initialize it.
460  * Input:
461  *      ty = TYxxxx
462  * Returns:
463  *      pointer to newly created type.
464  */
465 
466 type *type_fake(tym_t ty)
467 {   type *t;
468 
469 version (MARS)
470     assert(ty != TYstruct);
471 
472     t = type_alloc(ty);
473     if (typtr(ty) || tyfunc(ty))
474     {   t.Tnext = type_alloc(TYvoid);  /* fake with pointer to void    */
475         t.Tnext.Tcount = 1;
476     }
477     return t;
478 }
479 
480 /*****************************
481  * Allocate a type of ty with a Tnext of tn.
482  */
483 
484 type *type_allocn(tym_t ty,type *tn)
485 {   type *t;
486 
487     //printf("type_allocn(ty = x%x, tn = %p)\n", ty, tn);
488     assert(tn);
489     type_debug(tn);
490     t = type_alloc(ty);
491     t.Tnext = tn;
492     tn.Tcount++;
493     //printf("\tt = %p\n", t);
494     return t;
495 }
496 
497 /******************************
498  * Allocate a TYmemptr type.
499  */
500 
501 version (SCPP_HTOD)
502 {
503 type *type_allocmemptr(Classsym *stag,type *tn)
504 {   type *t;
505 
506     symbol_debug(stag);
507     assert(stag.Sclass == SCstruct || tybasic(stag.Stype.Tty) == TYident);
508     t = type_allocn(TYmemptr,tn);
509     t.Ttag = stag;
510     //printf("type_allocmemptr() = %p\n", t);
511     //type_print(t);
512     return t;
513 }
514 }
515 
516 /********************************
517  * Allocate a pointer type.
518  * Returns:
519  *      Tcount already incremented
520  */
521 
522 type *type_pointer(type *tnext)
523 {
524     type *t = type_allocn(TYnptr, tnext);
525     t.Tcount++;
526     return t;
527 }
528 
529 /********************************
530  * Allocate a dynamic array type.
531  * Returns:
532  *      Tcount already incremented
533  */
534 
535 type *type_dyn_array(type *tnext)
536 {
537     type *t = type_allocn(TYdarray, tnext);
538     t.Tcount++;
539     return t;
540 }
541 
542 /********************************
543  * Allocate a static array type.
544  * Returns:
545  *      Tcount already incremented
546  */
547 
548 extern (C) type *type_static_array(targ_size_t dim, type *tnext)
549 {
550     type *t = type_allocn(TYarray, tnext);
551     t.Tdim = dim;
552     t.Tcount++;
553     return t;
554 }
555 
556 /********************************
557  * Allocate an associative array type,
558  * which are key=value pairs
559  * Returns:
560  *      Tcount already incremented
561  */
562 
563 type *type_assoc_array(type *tkey, type *tvalue)
564 {
565     type *t = type_allocn(TYaarray, tvalue);
566     t.Tkey = tkey;
567     tkey.Tcount++;
568     t.Tcount++;
569     return t;
570 }
571 
572 /********************************
573  * Allocate a delegate type.
574  * Returns:
575  *      Tcount already incremented
576  */
577 
578 type *type_delegate(type *tnext)
579 {
580     type *t = type_allocn(TYdelegate, tnext);
581     t.Tcount++;
582     return t;
583 }
584 
585 /***********************************
586  * Allocation a function type.
587  * Params:
588  *      tyf      = function type
589  *      ptypes   = types of the function parameters
590  *      variadic = if ... function
591  *      tret     = return type
592  * Returns:
593  *      Tcount already incremented
594  */
595 extern (C)
596 type *type_function(tym_t tyf, type*[] ptypes, bool variadic, type *tret)
597 {
598     param_t *paramtypes = null;
599     foreach (p; ptypes)
600     {
601         param_append_type(&paramtypes, p);
602     }
603     type *t = type_allocn(tyf, tret);
604     t.Tflags |= TFprototype;
605     if (!variadic)
606         t.Tflags |= TFfixed;
607     t.Tparamtypes = paramtypes;
608     t.Tcount++;
609     return t;
610 }
611 
612 /***************************************
613  * Create an enum type.
614  * Input:
615  *      name    name of enum
616  *      tbase   "base" type of enum
617  * Returns:
618  *      Tcount already incremented
619  */
620 type *type_enum(const(char)* name, type *tbase)
621 {
622     Symbol *s = symbol_calloc(name);
623     s.Sclass = SCenum;
624     s.Senum = cast(enum_t *) MEM_PH_CALLOC(enum_t.sizeof);
625     s.Senum.SEflags |= SENforward;        // forward reference
626 
627     type *t = type_allocn(TYenum, tbase);
628     t.Ttag = cast(Classsym *)s;            // enum tag name
629     t.Tcount++;
630     s.Stype = t;
631     t.Tcount++;
632     return t;
633 }
634 
635 /**************************************
636  * Create a struct/union/class type.
637  * Params:
638  *      name = name of struct (this function makes its own copy of the string)
639  *      is0size = if struct has no fields (even if Sstructsize is 1)
640  * Returns:
641  *      Tcount already incremented
642  */
643 type *type_struct_class(const(char)* name, uint alignsize, uint structsize,
644         type *arg1type, type *arg2type, bool isUnion, bool isClass, bool isPOD, bool is0size)
645 {
646     Symbol *s = symbol_calloc(name);
647     s.Sclass = SCstruct;
648     s.Sstruct = struct_calloc();
649     s.Sstruct.Salignsize = alignsize;
650     s.Sstruct.Sstructalign = cast(ubyte)alignsize;
651     s.Sstruct.Sstructsize = structsize;
652     s.Sstruct.Sarg1type = arg1type;
653     s.Sstruct.Sarg2type = arg2type;
654 
655     if (!isPOD)
656         s.Sstruct.Sflags |= STRnotpod;
657     if (isUnion)
658         s.Sstruct.Sflags |= STRunion;
659     if (isClass)
660     {   s.Sstruct.Sflags |= STRclass;
661         assert(!isUnion && isPOD);
662     }
663     if (is0size)
664         s.Sstruct.Sflags |= STR0size;
665 
666     type *t = type_alloc(TYstruct);
667     t.Ttag = cast(Classsym *)s;            // structure tag name
668     t.Tcount++;
669     s.Stype = t;
670     t.Tcount++;
671     return t;
672 }
673 
674 /*****************************
675  * Free up data type.
676  */
677 
678 void type_free(type *t)
679 {   type *tn;
680     tym_t ty;
681 
682     while (t)
683     {
684         //printf("type_free(%p, Tcount = %d)\n", t, t.Tcount);
685         type_debug(t);
686         assert(cast(int)t.Tcount != -1);
687         if (--t.Tcount)                /* if usage count doesn't go to 0 */
688             break;
689         ty = tybasic(t.Tty);
690         if (tyfunc(ty))
691         {   param_free(&t.Tparamtypes);
692             list_free(&t.Texcspec, cast(list_free_fp)&type_free);
693             goto L1;
694         }
695 version (SCPP_HTOD)
696 {
697         if (ty == TYtemplate)
698         {
699             param_free(&t.Tparamtypes);
700             goto L1;
701         }
702         if (ty == TYident)
703         {
704             MEM_PH_FREE(t.Tident);
705             goto L1;
706         }
707 }
708         if (t.Tflags & TFvla && t.Tel)
709         {
710             el_free(t.Tel);
711             goto L1;
712         }
713 version (SCPP_HTOD)
714 {
715         if (t.Talternate && typtr(ty))
716         {
717             type_free(t.Talternate);
718             goto L1;
719         }
720 }
721 version (MARS)
722 {
723         if (t.Tkey && typtr(ty))
724             type_free(t.Tkey);
725 }
726       L1:
727 
728 debug
729 {
730         type_num--;
731         //printf("Free'ing type %p ",t); WRTYxx(t.Tty); printf("\n");
732         t.id = 0;                      /* no longer a valid type       */
733 }
734 
735         tn = t.Tnext;
736         t.Tnext = type_list;
737         type_list = t;                  /* link into free list          */
738         t = tn;
739     }
740 }
741 
742 version (STATS)
743 {
744 /* count number of free types available on type list */
745 void type_count_free()
746     {
747     type *t;
748     int count;
749 
750     for(t=type_list;t;t=t.Tnext)
751         count++;
752     printf("types on free list %d with max of %d\n",count,type_max);
753     }
754 }
755 
756 /**********************************
757  * Initialize type package.
758  */
759 
760 private type * type_allocbasic(tym_t ty)
761 {   type *t;
762 
763     t = type_alloc(ty);
764     t.Tmangle = mTYman_c;
765     t.Tcount = 1;              /* so it is not inadvertently free'd    */
766     return t;
767 }
768 
769 void type_init()
770 {
771     tstypes[TYbool]    = type_allocbasic(TYbool);
772     tstypes[TYwchar_t] = type_allocbasic(TYwchar_t);
773     tstypes[TYdchar]   = type_allocbasic(TYdchar);
774     tstypes[TYvoid]    = type_allocbasic(TYvoid);
775     tstypes[TYnullptr] = type_allocbasic(TYnullptr);
776     tstypes[TYchar16]  = type_allocbasic(TYchar16);
777     tstypes[TYuchar]   = type_allocbasic(TYuchar);
778     tstypes[TYschar]   = type_allocbasic(TYschar);
779     tstypes[TYchar]    = type_allocbasic(TYchar);
780     tstypes[TYshort]   = type_allocbasic(TYshort);
781     tstypes[TYushort]  = type_allocbasic(TYushort);
782     tstypes[TYint]     = type_allocbasic(TYint);
783     tstypes[TYuint]    = type_allocbasic(TYuint);
784     tstypes[TYlong]    = type_allocbasic(TYlong);
785     tstypes[TYulong]   = type_allocbasic(TYulong);
786     tstypes[TYllong]   = type_allocbasic(TYllong);
787     tstypes[TYullong]  = type_allocbasic(TYullong);
788     tstypes[TYfloat]   = type_allocbasic(TYfloat);
789     tstypes[TYdouble]  = type_allocbasic(TYdouble);
790     tstypes[TYdouble_alias]  = type_allocbasic(TYdouble_alias);
791     tstypes[TYldouble] = type_allocbasic(TYldouble);
792     tstypes[TYifloat]  = type_allocbasic(TYifloat);
793     tstypes[TYidouble] = type_allocbasic(TYidouble);
794     tstypes[TYildouble] = type_allocbasic(TYildouble);
795     tstypes[TYcfloat]   = type_allocbasic(TYcfloat);
796     tstypes[TYcdouble]  = type_allocbasic(TYcdouble);
797     tstypes[TYcldouble] = type_allocbasic(TYcldouble);
798 
799     if (I64)
800     {
801         TYptrdiff = TYllong;
802         TYsize = TYullong;
803         tsptrdiff = tstypes[TYllong];
804         tssize = tstypes[TYullong];
805     }
806     else
807     {
808         TYptrdiff = TYint;
809         TYsize = TYuint;
810         tsptrdiff = tstypes[TYint];
811         tssize = tstypes[TYuint];
812     }
813 
814     // Type of trace function
815     tstrace = type_fake(I16 ? TYffunc : TYnfunc);
816     tstrace.Tmangle = mTYman_c;
817     tstrace.Tcount++;
818 
819     chartype = (config.flags3 & CFG3ju) ? tstypes[TYuchar] : tstypes[TYchar];
820 
821     // Type of far library function
822     tsclib = type_fake(LARGECODE ? TYfpfunc : TYnpfunc);
823     tsclib.Tmangle = mTYman_c;
824     tsclib.Tcount++;
825 
826     tspvoid = type_allocn(pointertype,tstypes[TYvoid]);
827     tspvoid.Tmangle = mTYman_c;
828     tspvoid.Tcount++;
829 
830     // Type of far library function
831     tsjlib =    type_fake(TYjfunc);
832     tsjlib.Tmangle = mTYman_c;
833     tsjlib.Tcount++;
834 
835     tsdlib = tsjlib;
836 
837 version (SCPP_HTOD)
838 {
839     tspcvoid = type_alloc(mTYconst | TYvoid);
840     tspcvoid = newpointer(tspcvoid);
841     tspcvoid.Tmangle = mTYman_c;
842     tspcvoid.Tcount++;
843 }
844 
845     // Type of logical expression
846     tslogical = (config.flags4 & CFG4bool) ? tstypes[TYbool] : tstypes[TYint];
847 
848     for (int i = 0; i < TYMAX; i++)
849     {
850         if (tstypes[i])
851         {   tsptr2types[i] = type_allocn(pointertype,tstypes[i]);
852             tsptr2types[i].Tcount++;
853         }
854     }
855 }
856 
857 /**********************************
858  * Free type_list.
859  */
860 
861 void type_term()
862 {
863 static if (TERMCODE)
864 {
865     type *tn;
866     param_t *pn;
867     int i;
868 
869     for (i = 0; i < tstypes.length; i++)
870     {   type *t = tsptr2types[i];
871 
872         if (t)
873         {   assert(!(t.Tty & (mTYconst | mTYvolatile | mTYimmutable | mTYshared)));
874             assert(!(t.Tflags));
875             assert(!(t.Tmangle));
876             type_free(t);
877         }
878         type_free(tstypes[i]);
879     }
880 
881     type_free(tsclib);
882     type_free(tspvoid);
883     type_free(tspcvoid);
884     type_free(tsjlib);
885     type_free(tstrace);
886 
887     while (type_list)
888     {   tn = type_list.Tnext;
889         mem_ffree(type_list);
890         type_list = tn;
891     }
892 
893     while (param_list)
894     {   pn = param_list.Pnext;
895         mem_ffree(param_list);
896         param_list = pn;
897     }
898 
899 debug
900 {
901     printf("Max # of types = %d\n",type_max);
902     if (type_num != 0)
903         printf("type_num = %d\n",type_num);
904 /*    assert(type_num == 0);*/
905 }
906 
907 }
908 }
909 
910 /*******************************
911  * Type type information.
912  */
913 
914 /**************************
915  * Make copy of a type.
916  */
917 
918 type *type_copy(type *t)
919 {   type *tn;
920     param_t *p;
921 
922     type_debug(t);
923 version (SCPP_HTOD)
924 {
925     if (tybasic(t.Tty) == TYtemplate)
926     {
927         tn = type_alloc_template((cast(typetemp_t *)t).Tsym);
928     }
929     else
930         tn = type_alloc(t.Tty);
931 }
932 else
933         tn = type_alloc(t.Tty);
934 
935     *tn = *t;
936     switch (tybasic(tn.Tty))
937     {
938 version (SCPP_HTOD)
939 {
940             case TYtemplate:
941                 (cast(typetemp_t *)tn).Tsym = (cast(typetemp_t *)t).Tsym;
942                 goto L1;
943 
944             case TYident:
945                 tn.Tident = cast(char *)MEM_PH_STRDUP(t.Tident);
946                 break;
947 }
948 
949             case TYarray:
950                 if (tn.Tflags & TFvla)
951                     tn.Tel = el_copytree(tn.Tel);
952                 break;
953 
954             default:
955                 if (tyfunc(tn.Tty))
956                 {
957                 L1:
958                     tn.Tparamtypes = null;
959                     for (p = t.Tparamtypes; p; p = p.Pnext)
960                     {   param_t *pn;
961 
962                         pn = param_append_type(&tn.Tparamtypes,p.Ptype);
963                         if (p.Pident)
964                         {
965                             pn.Pident = cast(char *)MEM_PH_STRDUP(p.Pident);
966                         }
967                         assert(!p.Pelem);
968                     }
969                 }
970                 else
971                 {
972 version (SCPP_HTOD)
973 {
974                 if (tn.Talternate && typtr(tn.Tty))
975                     tn.Talternate.Tcount++;
976 }
977 version (MARS)
978 {
979                 if (tn.Tkey && typtr(tn.Tty))
980                     tn.Tkey.Tcount++;
981 }
982                 }
983                 break;
984     }
985     if (tn.Tnext)
986     {   type_debug(tn.Tnext);
987         tn.Tnext.Tcount++;
988     }
989     tn.Tcount = 0;
990     return tn;
991 }
992 
993 /************************************
994  */
995 
996 version (SCPP_HTOD)
997 {
998 
999 elem *type_vla_fix(type **pt)
1000 {
1001     type *t;
1002     elem *e = null;
1003 
1004     for (t = *pt; t; t = t.Tnext)
1005     {
1006         type_debug(t);
1007         if (tybasic(t.Tty) == TYarray && t.Tflags & TFvla && t.Tel)
1008         {   Symbol *s;
1009             elem *ec;
1010 
1011             s = symbol_genauto(tstypes[TYuint]);
1012             ec = el_var(s);
1013             ec = el_bint(OPeq, tstypes[TYuint], ec, t.Tel);
1014             e = el_combine(e, ec);
1015             t.Tel = el_var(s);
1016         }
1017     }
1018     return e;
1019 }
1020 
1021 }
1022 
1023 /****************************
1024  * Modify the tym_t field of a type.
1025  */
1026 
1027 type *type_setty(type **pt,uint newty)
1028 {   type *t;
1029 
1030     t = *pt;
1031     type_debug(t);
1032     if (cast(tym_t)newty != t.Tty)
1033     {   if (t.Tcount > 1)              /* if other people pointing at t */
1034         {   type *tn;
1035 
1036             tn = type_copy(t);
1037             tn.Tcount++;
1038             type_free(t);
1039             t = tn;
1040             *pt = t;
1041         }
1042         t.Tty = newty;
1043     }
1044     return t;
1045 }
1046 
1047 /******************************
1048  * Set type field of some object to t.
1049  */
1050 
1051 type *type_settype(type **pt, type *t)
1052 {
1053     if (t)
1054     {   type_debug(t);
1055         t.Tcount++;
1056     }
1057     type_free(*pt);
1058     return *pt = t;
1059 }
1060 
1061 /****************************
1062  * Modify the Tmangle field of a type.
1063  */
1064 
1065 type *type_setmangle(type **pt,mangle_t mangle)
1066 {   type *t;
1067 
1068     t = *pt;
1069     type_debug(t);
1070     if (mangle != type_mangle(t))
1071     {
1072         if (t.Tcount > 1)              // if other people pointing at t
1073         {   type *tn;
1074 
1075             tn = type_copy(t);
1076             tn.Tcount++;
1077             type_free(t);
1078             t = tn;
1079             *pt = t;
1080         }
1081         t.Tmangle = mangle;
1082     }
1083     return t;
1084 }
1085 
1086 /******************************
1087  * Set/clear const and volatile bits in *pt according to the settings
1088  * in cv.
1089  */
1090 
1091 type *type_setcv(type **pt,tym_t cv)
1092 {   uint ty;
1093 
1094     type_debug(*pt);
1095     ty = (*pt).Tty & ~(mTYconst | mTYvolatile | mTYimmutable | mTYshared);
1096     return type_setty(pt,ty | (cv & (mTYconst | mTYvolatile | mTYimmutable | mTYshared)));
1097 }
1098 
1099 /*****************************
1100  * Set dimension of array.
1101  */
1102 
1103 type *type_setdim(type **pt,targ_size_t dim)
1104 {   type *t = *pt;
1105 
1106     type_debug(t);
1107     if (t.Tcount > 1)                  /* if other people pointing at t */
1108     {   type *tn;
1109 
1110         tn = type_copy(t);
1111         tn.Tcount++;
1112         type_free(t);
1113         t = tn;
1114     }
1115     t.Tflags &= ~TFsizeunknown; /* we have determined its size */
1116     t.Tdim = dim;              /* index of array               */
1117     return *pt = t;
1118 }
1119 
1120 
1121 /*****************************
1122  * Create a 'dependent' version of type t.
1123  */
1124 
1125 type *type_setdependent(type *t)
1126 {
1127     type_debug(t);
1128     if (t.Tcount > 0 &&                        /* if other people pointing at t */
1129         !(t.Tflags & TFdependent))
1130     {
1131         t = type_copy(t);
1132     }
1133     t.Tflags |= TFdependent;
1134     return t;
1135 }
1136 
1137 /************************************
1138  * Determine if type t is a dependent type.
1139  */
1140 
1141 int type_isdependent(type *t)
1142 {
1143     Symbol *stempl;
1144     type *tstart;
1145 
1146     //printf("type_isdependent(%p)\n", t);
1147     //type_print(t);
1148     for (tstart = t; t; t = t.Tnext)
1149     {
1150         type_debug(t);
1151         if (t.Tflags & TFdependent)
1152             goto Lisdependent;
1153         if (tyfunc(t.Tty)
1154                 || tybasic(t.Tty) == TYtemplate
1155                 )
1156         {
1157             for (param_t *p = t.Tparamtypes; p; p = p.Pnext)
1158             {
1159                 if (p.Ptype && type_isdependent(p.Ptype))
1160                     goto Lisdependent;
1161                 if (p.Pelem && el_isdependent(p.Pelem))
1162                     goto Lisdependent;
1163             }
1164         }
1165         else if (type_struct(t) &&
1166                  (stempl = t.Ttag.Sstruct.Stempsym) != null)
1167         {
1168             for (param_t *p = t.Ttag.Sstruct.Sarglist; p; p = p.Pnext)
1169             {
1170                 if (p.Ptype && type_isdependent(p.Ptype))
1171                     goto Lisdependent;
1172                 if (p.Pelem && el_isdependent(p.Pelem))
1173                     goto Lisdependent;
1174             }
1175         }
1176     }
1177     //printf("\tis not dependent\n");
1178     return 0;
1179 
1180 Lisdependent:
1181     //printf("\tis dependent\n");
1182     // Dependence on a dependent type makes this type dependent as well
1183     tstart.Tflags |= TFdependent;
1184     return 1;
1185 }
1186 
1187 
1188 /*******************************
1189  * Recursively check if type u is embedded in type t.
1190  * Returns:
1191  *      != 0 if embedded
1192  */
1193 
1194 int type_embed(type *t,type *u)
1195 {   param_t *p;
1196 
1197     for (; t; t = t.Tnext)
1198     {
1199         type_debug(t);
1200         if (t == u)
1201             return 1;
1202         if (tyfunc(t.Tty))
1203         {
1204             for (p = t.Tparamtypes; p; p = p.Pnext)
1205                 if (type_embed(p.Ptype,u))
1206                     return 1;
1207         }
1208     }
1209     return 0;
1210 }
1211 
1212 
1213 /***********************************
1214  * Determine if type is a VLA.
1215  */
1216 
1217 int type_isvla(type *t)
1218 {
1219     while (t)
1220     {
1221         if (tybasic(t.Tty) != TYarray)
1222             break;
1223         if (t.Tflags & TFvla)
1224             return 1;
1225         t = t.Tnext;
1226     }
1227     return 0;
1228 }
1229 
1230 
1231 /**********************************
1232  * Pretty-print a type.
1233  */
1234 
1235 void type_print(const type *t)
1236 {
1237   type_debug(t);
1238   printf("Tty="); WRTYxx(t.Tty);
1239   printf(" Tmangle=%d",t.Tmangle);
1240   printf(" Tflags=x%x",t.Tflags);
1241   printf(" Tcount=%d",t.Tcount);
1242   if (!(t.Tflags & TFsizeunknown) &&
1243         tybasic(t.Tty) != TYvoid &&
1244         tybasic(t.Tty) != TYident &&
1245         tybasic(t.Tty) != TYtemplate &&
1246         tybasic(t.Tty) != TYmfunc &&
1247         tybasic(t.Tty) != TYarray)
1248       printf(" Tsize=%lld", cast(long)type_size(t));
1249   printf(" Tnext=%p",t.Tnext);
1250   switch (tybasic(t.Tty))
1251   {     case TYstruct:
1252         case TYmemptr:
1253             printf(" Ttag=%p,'%s'",t.Ttag,t.Ttag.Sident.ptr);
1254             //printf(" Sfldlst=%p",t.Ttag.Sstruct.Sfldlst);
1255             break;
1256 
1257         case TYarray:
1258             printf(" Tdim=%lld", cast(long)t.Tdim);
1259             break;
1260 
1261         case TYident:
1262             printf(" Tident='%s'",t.Tident);
1263             break;
1264         case TYtemplate:
1265             printf(" Tsym='%s'",(cast(typetemp_t *)t).Tsym.Sident.ptr);
1266             {
1267                 int i;
1268 
1269                 i = 1;
1270                 for (const(param_t)* p = t.Tparamtypes; p; p = p.Pnext)
1271                 {   printf("\nTP%d (%p): ",i++,p);
1272                     fflush(stdout);
1273 
1274 printf("Pident=%p,Ptype=%p,Pelem=%p,Pnext=%p ",p.Pident,p.Ptype,p.Pelem,p.Pnext);
1275                     param_debug(p);
1276                     if (p.Pident)
1277                         printf("'%s' ", p.Pident);
1278                     if (p.Ptype)
1279                         type_print(p.Ptype);
1280                     if (p.Pelem)
1281                         elem_print(p.Pelem);
1282                 }
1283             }
1284             break;
1285 
1286         default:
1287             if (tyfunc(t.Tty))
1288             {
1289                 int i;
1290 
1291                 i = 1;
1292                 for (const(param_t)* p = t.Tparamtypes; p; p = p.Pnext)
1293                 {   printf("\nP%d (%p): ",i++,p);
1294                     fflush(stdout);
1295 
1296 printf("Pident=%p,Ptype=%p,Pelem=%p,Pnext=%p ",p.Pident,p.Ptype,p.Pelem,p.Pnext);
1297                     param_debug(p);
1298                     if (p.Pident)
1299                         printf("'%s' ", p.Pident);
1300                     type_print(p.Ptype);
1301                 }
1302             }
1303             break;
1304   }
1305   printf("\n");
1306   if (t.Tnext) type_print(t.Tnext);
1307 }
1308 
1309 /*******************************
1310  * Pretty-print a param_t
1311  */
1312 
1313 void param_t_print(const param_t* p)
1314 {
1315     printf("Pident=%p,Ptype=%p,Pelem=%p,Psym=%p,Pnext=%p\n",p.Pident,p.Ptype,p.Pelem,p.Psym,p.Pnext);
1316     if (p.Pident)
1317         printf("\tPident = '%s'\n", p.Pident);
1318     if (p.Ptype)
1319     {   printf("\tPtype =\n");
1320         type_print(p.Ptype);
1321     }
1322     if (p.Pelem)
1323     {   printf("\tPelem =\n");
1324         elem_print(p.Pelem);
1325     }
1326     if (p.Pdeftype)
1327     {   printf("\tPdeftype =\n");
1328         type_print(p.Pdeftype);
1329     }
1330     if (p.Psym)
1331     {   printf("\tPsym = '%s'\n", p.Psym.Sident.ptr);
1332     }
1333     if (p.Pptpl)
1334     {   printf("\tPptpl = %p\n", p.Pptpl);
1335     }
1336 }
1337 
1338 void param_t_print_list(param_t* p)
1339 {
1340     for (; p; p = p.Pnext)
1341         p.print();
1342 }
1343 
1344 
1345 /**********************************
1346  * Hydrate a type.
1347  */
1348 
1349 version (SCPP_HTOD)
1350 {
1351 
1352 static if (HYDRATE)
1353 {
1354 void type_hydrate(type **pt)
1355 {
1356     type *t;
1357 
1358     assert(pt);
1359     while (isdehydrated(*pt))
1360     {
1361         t = cast(type *) ph_hydrate(cast(void**)pt);
1362         type_debug(t);
1363         switch (tybasic(t.Tty))
1364         {
1365             case TYstruct:
1366             case TYenum:
1367             case TYmemptr:
1368             case TYvtshape:
1369                 // Cannot assume symbol is hydrated, because entire HX file
1370                 // may not have been hydrated.
1371                 Classsym_hydrate(&t.Ttag);
1372                 symbol_debug(t.Ttag);
1373                 break;
1374             case TYident:
1375                 ph_hydrate(cast(void**)&t.Tident);
1376                 break;
1377             case TYtemplate:
1378                 symbol_hydrate(&(cast(typetemp_t *)t).Tsym);
1379                 param_hydrate(&t.Tparamtypes);
1380                 break;
1381             case TYarray:
1382                 if (t.Tflags & TFvla)
1383                     el_hydrate(&t.Tel);
1384                 break;
1385             default:
1386                 if (tyfunc(t.Tty))
1387                 {   param_hydrate(&t.Tparamtypes);
1388                     list_hydrate(&t.Texcspec, cast(list_free_fp)&type_hydrate);
1389                 }
1390                 else if (t.Talternate && typtr(t.Tty))
1391                     type_hydrate(&t.Talternate);
1392                 else if (t.Tkey && typtr(t.Tty))
1393                     type_hydrate(&t.Tkey);
1394                 break;
1395         }
1396         pt = &t.Tnext;
1397     }
1398 }
1399 }
1400 
1401 /**********************************
1402  * Dehydrate a type.
1403  */
1404 
1405 static if (DEHYDRATE)
1406 {
1407 void type_dehydrate(type **pt)
1408 {
1409     type *t;
1410 
1411     while ((t = *pt) != null && !isdehydrated(t))
1412     {
1413         ph_dehydrate(pt);
1414 version (DEBUG_XSYMGEN)
1415 {
1416         /* don't dehydrate types in HEAD when creating XSYM */
1417         if (xsym_gen && (t.Tflags & TFhydrated))
1418             return;
1419 }
1420         type_debug(t);
1421         switch (tybasic(t.Tty))
1422         {
1423             case TYstruct:
1424             case TYenum:
1425             case TYmemptr:
1426             case TYvtshape:
1427                 Classsym_dehydrate(&t.Ttag);
1428                 break;
1429             case TYident:
1430                 ph_dehydrate(&t.Tident);
1431                 break;
1432             case TYtemplate:
1433                 symbol_dehydrate(&(cast(typetemp_t *)t).Tsym);
1434                 param_dehydrate(&t.Tparamtypes);
1435                 break;
1436             case TYarray:
1437                 if (t.Tflags & TFvla)
1438                     el_dehydrate(&t.Tel);
1439                 break;
1440             default:
1441                 if (tyfunc(t.Tty))
1442                 {   param_dehydrate(&t.Tparamtypes);
1443                     list_dehydrate(&t.Texcspec, cast(list_free_fp)&type_dehydrate);
1444                 }
1445                 else if (t.Talternate && typtr(t.Tty))
1446                     type_dehydrate(&t.Talternate);
1447                 else if (t.Tkey && typtr(t.Tty))
1448                     type_dehydrate(&t.Tkey);
1449                 break;
1450         }
1451         pt = &t.Tnext;
1452     }
1453 }
1454 }
1455 
1456 }
1457 
1458 /****************************
1459  * Allocate a param_t.
1460  */
1461 
1462 param_t *param_calloc()
1463 {
1464     static param_t pzero;
1465     param_t *p;
1466 
1467     if (param_list)
1468     {
1469         p = param_list;
1470         param_list = p.Pnext;
1471     }
1472     else
1473     {
1474         p = cast(param_t *) mem_fmalloc(param_t.sizeof);
1475     }
1476     *p = pzero;
1477 
1478     debug p.id = param_t.IDparam;
1479 
1480     return p;
1481 }
1482 
1483 /***************************
1484  * Allocate a param_t of type t, and append it to parameter list.
1485  */
1486 
1487 param_t *param_append_type(param_t **pp,type *t)
1488 {   param_t *p;
1489 
1490     p = param_calloc();
1491     while (*pp)
1492     {   param_debug(*pp);
1493         pp = &((*pp).Pnext);   /* find end of list     */
1494     }
1495     *pp = p;                    /* append p to list     */
1496     type_debug(t);
1497     p.Ptype = t;
1498     t.Tcount++;
1499     return p;
1500 }
1501 
1502 /************************
1503  * Version of param_free() suitable for list_free().
1504  */
1505 
1506 void param_free_l(param_t *p)
1507 {
1508     param_free(&p);
1509 }
1510 
1511 /***********************
1512  * Free parameter list.
1513  * Output:
1514  *      paramlst = null
1515  */
1516 
1517 void param_free(param_t **pparamlst)
1518 {   param_t* p,pn;
1519 
1520     //debug_assert(PARSER);
1521     for (p = *pparamlst; p; p = pn)
1522     {   param_debug(p);
1523         pn = p.Pnext;
1524         type_free(p.Ptype);
1525         mem_free(p.Pident);
1526         el_free(p.Pelem);
1527         type_free(p.Pdeftype);
1528         if (p.Pptpl)
1529             param_free(&p.Pptpl);
1530 
1531         debug p.id = 0;
1532 
1533         p.Pnext = param_list;
1534         param_list = p;
1535     }
1536     *pparamlst = null;
1537 }
1538 
1539 /***********************************
1540  * Compute number of parameters
1541  */
1542 
1543 uint param_t_length(param_t* p)
1544 {
1545     uint nparams = 0;
1546 
1547     for (; p; p = p.Pnext)
1548         nparams++;
1549     return nparams;
1550 }
1551 
1552 /*************************************
1553  * Create template-argument-list blank from
1554  * template-parameter-list
1555  * Input:
1556  *      ptali   initial template-argument-list
1557  */
1558 
1559 param_t *param_t_createTal(param_t* p, param_t *ptali)
1560 {
1561 version (SCPP_HTOD)
1562 {
1563     param_t *ptalistart = ptali;
1564     param_t *pstart = p;
1565 }
1566     param_t *ptal = null;
1567     param_t **pp = &ptal;
1568 
1569     for (; p; p = p.Pnext)
1570     {
1571         *pp = param_calloc();
1572         if (p.Pident)
1573         {
1574             // Should find a way to just point rather than dup
1575             (*pp).Pident = cast(char *)MEM_PH_STRDUP(p.Pident);
1576         }
1577         if (ptali)
1578         {
1579             if (ptali.Ptype)
1580             {   (*pp).Ptype = ptali.Ptype;
1581                 (*pp).Ptype.Tcount++;
1582             }
1583             if (ptali.Pelem)
1584             {
1585                 elem *e = el_copytree(ptali.Pelem);
1586 version (SCPP_HTOD)
1587 {
1588                 if (p.Ptype)
1589                 {   type *t = p.Ptype;
1590                     t = template_tyident(t, ptalistart, pstart, 1);
1591                     e = poptelem3(typechk(e, t));
1592                     type_free(t);
1593                 }
1594 }
1595                 (*pp).Pelem = e;
1596             }
1597             (*pp).Psym = ptali.Psym;
1598             (*pp).Pflags = ptali.Pflags;
1599             assert(!ptali.Pptpl);
1600             ptali = ptali.Pnext;
1601         }
1602         pp = &(*pp).Pnext;
1603     }
1604     return ptal;
1605 }
1606 
1607 /**********************************
1608  * Look for Pident matching id
1609  */
1610 
1611 param_t *param_t_search(param_t* p, char *id)
1612 {
1613     for (; p; p = p.Pnext)
1614     {
1615         if (p.Pident && strcmp(p.Pident, id) == 0)
1616             break;
1617     }
1618     return p;
1619 }
1620 
1621 /**********************************
1622  * Look for Pident matching id
1623  */
1624 
1625 int param_t_searchn(param_t* p, char *id)
1626 {
1627     int n = 0;
1628 
1629     for (; p; p = p.Pnext)
1630     {
1631         if (p.Pident && strcmp(p.Pident, id) == 0)
1632             return n;
1633         n++;
1634     }
1635     return -1;
1636 }
1637 
1638 /*************************************
1639  * Search for member, create symbol as needed.
1640  * Used for symbol tables for VLA's such as:
1641  *      void func(int n, int a[n]);
1642  */
1643 
1644 Symbol *param_search(const(char)* name, param_t **pp)
1645 {   Symbol *s = null;
1646     param_t *p;
1647 
1648     p = (*pp).search(cast(char *)name);
1649     if (p)
1650     {
1651         s = p.Psym;
1652         if (!s)
1653         {
1654             s = symbol_calloc(p.Pident);
1655             s.Sclass = SCparameter;
1656             s.Stype = p.Ptype;
1657             s.Stype.Tcount++;
1658             p.Psym = s;
1659         }
1660     }
1661     return s;
1662 }
1663 
1664 /**********************************
1665  * Hydrate/dehydrate a type.
1666  */
1667 
1668 version (SCPP_HTOD)
1669 {
1670 static if (HYDRATE)
1671 {
1672 void param_hydrate(param_t **pp)
1673 {
1674     param_t *p;
1675 
1676     assert(pp);
1677     if (isdehydrated(*pp))
1678     {   while (*pp)
1679         {   assert(isdehydrated(*pp));
1680             p = cast(param_t *) ph_hydrate(cast(void**)pp);
1681             param_debug(p);
1682 
1683             type_hydrate(&p.Ptype);
1684             if (p.Ptype)
1685                 type_debug(p.Ptype);
1686             ph_hydrate(cast(void**)&p.Pident);
1687             if (CPP)
1688             {
1689                 el_hydrate(&p.Pelem);
1690                 if (p.Pelem)
1691                     elem_debug(p.Pelem);
1692                 type_hydrate(&p.Pdeftype);
1693                 if (p.Pptpl)
1694                     param_hydrate(&p.Pptpl);
1695                 if (p.Psym)
1696                     symbol_hydrate(&p.Psym);
1697                 if (p.PelemToken)
1698                     token_hydrate(&p.PelemToken);
1699             }
1700 
1701             pp = &p.Pnext;
1702         }
1703     }
1704 }
1705 }
1706 
1707 static if (DEHYDRATE)
1708 {
1709 void param_dehydrate(param_t **pp)
1710 {
1711     param_t *p;
1712 
1713     assert(pp);
1714     while ((p = *pp) != null && !isdehydrated(p))
1715     {   param_debug(p);
1716 
1717         ph_dehydrate(pp);
1718         if (p.Ptype && !isdehydrated(p.Ptype))
1719             type_debug(p.Ptype);
1720         type_dehydrate(&p.Ptype);
1721         ph_dehydrate(&p.Pident);
1722         if (CPP)
1723         {
1724             el_dehydrate(&p.Pelem);
1725             type_dehydrate(&p.Pdeftype);
1726             if (p.Pptpl)
1727                 param_dehydrate(&p.Pptpl);
1728             if (p.Psym)
1729                 symbol_dehydrate(&p.Psym);
1730             if (p.PelemToken)
1731                 token_dehydrate(&p.PelemToken);
1732         }
1733         pp = &p.Pnext;
1734     }
1735 }
1736 }
1737 }
1738 
1739 version (MARS)
1740 {
1741 
1742 int typematch(type *t1, type *t2, int relax);
1743 
1744 // Return TRUE if type lists match.
1745 private int paramlstmatch(param_t *p1,param_t *p2)
1746 {
1747         return p1 == p2 ||
1748             p1 && p2 && typematch(p1.Ptype,p2.Ptype,0) &&
1749             paramlstmatch(p1.Pnext,p2.Pnext)
1750             ;
1751 }
1752 
1753 /*************************************************
1754  * A cheap version of exp2.typematch() and exp2.paramlstmatch(),
1755  * so that we can get cpp_mangle() to work for MARS.
1756  * It's less complex because it doesn't do templates and
1757  * can rely on strict typechecking.
1758  * Returns:
1759  *      !=0 if types match.
1760  */
1761 
1762 int typematch(type *t1,type *t2,int relax)
1763 { tym_t t1ty, t2ty;
1764   tym_t tym;
1765 
1766   tym = ~(mTYimport | mTYnaked);
1767 
1768   return t1 == t2 ||
1769             t1 && t2 &&
1770 
1771             (
1772                 /* ignore name mangling */
1773                 (t1ty = (t1.Tty & tym)) == (t2ty = (t2.Tty & tym))
1774             )
1775                  &&
1776 
1777             (tybasic(t1ty) != TYarray || t1.Tdim == t2.Tdim ||
1778              t1.Tflags & TFsizeunknown || t2.Tflags & TFsizeunknown)
1779                  &&
1780 
1781             (tybasic(t1ty) != TYstruct
1782                 && tybasic(t1ty) != TYenum
1783                 && tybasic(t1ty) != TYmemptr
1784              || t1.Ttag == t2.Ttag)
1785                  &&
1786 
1787             typematch(t1.Tnext,t2.Tnext, 0)
1788                  &&
1789 
1790             (!tyfunc(t1ty) ||
1791              ((t1.Tflags & TFfixed) == (t2.Tflags & TFfixed) &&
1792                  paramlstmatch(t1.Tparamtypes,t2.Tparamtypes) ))
1793          ;
1794 }
1795 
1796 }
1797 
1798 }