2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2002 University of Virginia,
4 ** Massachusetts Institute of Technology
6 ** This program is free software; you can redistribute it and/or modify it
7 ** under the terms of the GNU General Public License as published by the
8 ** Free Software Foundation; either version 2 of the License, or (at your
9 ** option) any later version.
11 ** This program is distributed in the hope that it will be useful, but
12 ** WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 ** General Public License for more details.
16 ** The GNU General Public License is available from http://www.gnu.org/ or
17 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 ** MA 02111-1307, USA.
20 ** For information on splint: splint@cs.virginia.edu
21 ** To report a bug: splint-bug@cs.virginia.edu
22 ** For more information: http://www.splint.org
27 ** NOTE: This is not a stand-alone source file, but is included in ctype.c.
28 ** (This is necessary because there is no other way in C to have a
29 ** hidden scope, besides at the file level.)
34 abst_typedef /*@null@*/ struct s_ctbase *ctbase;
36 /*@private@*/ typedef struct {
39 ctype base; /* type I point to (or element of array) */
40 ctype ptr; /* type of pointer to me */
41 ctype array; /* type of array of me */
42 cstring unparse; /* unparse me, if memoized */
45 typedef /*@only@*/ ctentry o_ctentry;
50 /*@relnull@*/ /*@only@*/ o_ctentry *entries;
51 /* memoize matches...maybe in context? */
54 extern bool ctentry_isBogus (/*@sef@*/ ctentry p_c) /*@*/;
55 # define ctentry_isBogus(c) \
56 ((c)->kind == CTK_INVALID || (c)->kind == CTK_DNE)
58 static cttable cttab = { 0, 0, NULL };
60 static /*@notnull@*/ /*@only@*/ ctbase ctbase_createAbstract (typeId p_u);
61 static /*@observer@*/ cstring ctentry_doUnparse (ctentry p_c) /*@modifies p_c@*/;
62 static /*@only@*/ ctentry
63 ctentry_make (ctkind p_ctk, /*@keep@*/ ctbase p_c, ctype p_base,
64 ctype p_ptr, ctype p_array, /*@keep@*/ cstring p_unparse);
65 static /*@only@*/ ctentry ctentry_makeNew (ctkind p_ctk, /*@only@*/ ctbase p_c);
66 static /*@only@*/ cstring ctentry_unparse (ctentry p_c) /*@*/ ;
68 static void cttable_grow (void);
69 static ctype cttable_addDerived (ctkind p_ctk, /*@keep@*/ ctbase p_cnew, ctype p_base);
70 static ctype cttable_addFull (/*@keep@*/ ctentry p_cnew);
71 static bool ctentry_isInteresting (ctentry p_c) /*@*/;
72 static /*@notnull@*/ /*@only@*/ ctbase ctbase_makeFixedArray (ctype p_b, size_t p_size) /*@*/ ;
73 static bool ctbase_isAnytype (/*@notnull@*/ ctbase p_b) /*@*/ ;
76 ** These are file-static macros (used in ctype.c). No way to
77 ** declare them as static in C.
80 /*@-allmacros@*/ /*@-macrospec@*/ /*@-namechecks@*/
81 # define ctentry_getBase(c) ((c)->base)
82 # define ctentry_getKind(c) ((c)->kind)
83 # define ctentry_getArray(c) ((c)->array)
84 # define ctentry_getPtr(c) ((c)->ptr)
85 # define ctentry_isArray(c) ((c)->kind == CTK_ARRAY)
86 # define ctentry_isComplex(c) ((c)->kind == CTK_COMPLEX)
87 # define ctentry_isPlain(c) ((c)->kind == CTK_PLAIN)
88 # define ctentry_isPointer(c) ((c)->kind == CTK_PTR)
89 # define ctentry_setArray(c,b) ((c)->array = (b))
90 # define ctentry_setPtr(c,b) ((c)->ptr = (b))
92 # define ctbase_fixUser(c) (c = ctbase_realType(c))
93 /*@=allmacros@*/ /*@=macrospec@*/ /*@=namechecks@*/
95 static ctype cttable_addComplex (/*@notnull@*/ /*@only@*/ ctbase p_cnew);
96 static /*@observer@*/ ctbase ctype_getCtbase (ctype p_c) /*@*/ ;
97 static ctype ctype_makeConjAux (ctype p_c1, ctype p_c2, bool p_isExplicit) /*@*/ ;
98 static /*@notnull@*/ /*@observer@*/ ctbase ctype_getCtbaseSafe (ctype p_c) /*@*/ ;
99 static /*@observer@*/ ctentry ctype_getCtentry (ctype p_c) /*@*/ ;
100 static /*@observer@*/ /*@notnull@*/ ctbase
101 ctbase_realType (/*@notnull@*/ ctbase p_c) /*@*/ ;
102 static bool ctbase_isPointer (/*@notnull@*/ /*@dependent@*/ ctbase p_c) /*@*/ ;
103 static bool ctbase_isEitherArray (/*@notnull@*/ /*@dependent@*/ ctbase p_c) /*@*/ ;
104 static /*@observer@*/ enumNameList ctbase_elist (ctbase p_c) /*@*/ ;
105 static /*@only@*/ cstring ctbase_unparse (ctbase p_c) /*@*/ ;
106 static /*@only@*/ cstring ctbase_unparseDeep (ctbase p_c) /*@*/ ;
107 static /*@only@*/ /*@notnull@*/ ctbase ctbase_copy (/*@notnull@*/ ctbase p_c) /*@*/ ;
108 static void ctbase_free (/*@only@*/ ctbase p_c);
109 static /*@notnull@*/ /*@only@*/ ctbase ctbase_createPrim (cprim p_p) /*@*/ ;
110 static /*@notnull@*/ /*@only@*/ ctbase ctbase_createBool (void) /*@*/ ;
111 static /*@notnull@*/ /*@observer@*/ ctbase ctbase_getBool (void) /*@*/ ;
112 static /*@notnull@*/ /*@only@*/ ctbase ctbase_createUser (typeId p_u) /*@*/ ;
114 static /*@notnull@*/ /*@only@*/ ctbase
115 ctbase_createStruct (/*@only@*/ cstring p_n, /*@only@*/ uentryList p_f);
117 static /*@notnull@*/ /*@only@*/ ctbase
118 ctbase_createUnion (/*@keep@*/ cstring p_n, /*@only@*/ uentryList p_f);
119 static /*@notnull@*/ /*@only@*/ ctbase ctbase_createEnum (/*@keep@*/ cstring p_etag, /*@keep@*/ enumNameList p_emembers);
120 static /*@notnull@*/ /*@only@*/ ctbase ctbase_createUnknown (void);
121 static bool ctbase_match (ctbase p_c1, ctbase p_c2) /*@modifies nothing@*/;
122 static bool ctbase_matchDef (ctbase p_c1, ctbase p_c2) /*@modifies nothing@*/;
123 static bool ctbase_genMatch (ctbase p_c1, ctbase p_c2, bool p_force, bool p_arg, bool p_def, bool p_deep);
124 static bool ctbase_isAbstract (/*@notnull@*/ ctbase p_c) /*@*/ ;
125 static /*@notnull@*/ /*@only@*/ ctbase ctbase_makePointer (ctype p_b) /*@*/ ;
126 static /*@notnull@*/ /*@only@*/ ctbase ctbase_makeArray (ctype p_b) /*@*/ ;
127 static /*@notnull@*/ ctype
128 ctbase_makeFunction (ctype p_b, /*@only@*/ uentryList p_p) /*@*/ ;
129 static /*@notnull@*/ /*@observer@*/ ctbase
130 ctbase_realFunction (/*@notnull@*/ /*@dependent@*/ ctbase p_c) /*@*/ ;
131 static ctype ctbase_baseArrayPtr (/*@notnull@*/ ctbase p_c) /*@*/ ;
132 static ctype ctbase_baseFunction (/*@notnull@*/ ctbase p_c) /*@*/ ;
133 static /*@observer@*/ uentryList ctbase_argsFunction (/*@notnull@*/ ctbase p_c) /*@*/ ;
134 static /*@observer@*/ uentryList ctbase_getuentryList (/*@notnull@*/ ctbase p_c) /*@*/ ;
135 static ctype ctbase_newBase (ctype p_c, ctype p_p) /*@*/ ;
136 static ctype ctbase_newBaseExpFcn (ctype p_c, ctype p_p) /*@*/ ;
137 static bool ctbase_isFixedArray (/*@notnull@*/ ctbase p_c) /*@*/ ;
140 extern int cttable_lastIndex();
141 # define cttable_lastIndex() (cttab.size - 1)
147 /*@only@*/ uentryList params;
166 enumNameList members;
177 cprim prim; /* primitive */
178 typeId tid; /* abstract, user */
179 ctype base; /* ptr, array */
180 cfcn fcn; /* function */
181 tsu su; /* struct union */
182 tenum cenum; /* enum */
183 tconj conj; /* conj */
184 tfixed farray; /* fixed array */
193 static /*@falsenull@*/ bool ctbase_isUA (ctbase p_c) /*@*/ ;
194 static bool ctbase_isBaseUA(ctbase p_c) /*@*/ ;
195 static typeId ctbase_typeBaseUid(ctbase p_c) /*@*/ ;
196 static bool ctbase_isKind (/*@notnull@*/ ctbase p_c, ctuid p_kind) /*@*/ ;
197 static bool ctbase_isKind2 (/*@notnull@*/ ctbase p_c, ctuid p_kind1, ctuid p_kind2) /*@*/ ;
198 static /*@only@*/ /*@notnull@*/ ctbase
199 ctbase_getBaseType (/*@notnull@*/ ctbase p_c) /*@*/ ;
201 static /*@falsenull@*/ bool ctbase_isFunction(ctbase p_c) /*@*/ ;
203 /*@constant null ctbase ctbase_undefined; @*/
204 # define ctbase_undefined ((ctbase)0)
206 static /*@owned@*/ ctbase ctbase_bool = ctbase_undefined;
207 static /*@owned@*/ ctbase ctbase_unknown = ctbase_undefined;
209 static /*@falsenull@*/ bool ctbase_isDefined (ctbase c) /*@*/
211 return ((c) != ctbase_undefined);
214 static /*@truenull@*/ bool ctbase_isUndefined (ctbase c)
216 return ((c) == ctbase_undefined);
219 static ctkind ctype_getCtKind (ctype c)
221 ctentry ce = ctype_getCtentry (c);
223 return ctentry_getKind (ce);
226 static bool ctbase_isUser (ctbase c)
228 if (ctbase_isDefined (c))
230 return (ctbase_isKind (c, CT_USER));
238 static bool ctbase_isEnum (ctbase c)
240 if (ctbase_isDefined (c))
242 return (ctbase_isKind (c, CT_ENUM));
250 static bool ctbase_isExpFcn (ctbase c)
252 if (ctbase_isDefined (c))
254 return (c->type == CT_EXPFCN);
262 static /*@falsenull@*/ bool ctbase_isConj (ctbase c)
264 if (ctbase_isDefined (c))
266 return (c->type == CT_CONJ);
274 static bool ctuid_isAP (ctuid c) /*@*/
276 return (c == CT_ARRAY || c == CT_PTR);
279 static typeId ctbase_typeId (ctbase p_c);
280 static /*@only@*/ cstring ctbase_dump (ctbase p_c);
281 static /*@only@*/ ctbase ctbase_undump (char **p_c) /*@requires maxRead(*p_c) >= 2 @*/;
282 static int ctbase_compare (ctbase p_c1, ctbase p_c2, bool p_strict);
283 static bool ctbase_matchArg (ctbase p_c1, ctbase p_c2);
284 static /*@notnull@*/ /*@only@*/ ctbase
285 ctbase_makeConj (ctype p_c1, ctype p_c2, bool p_isExplicit) /*@*/ ;
286 static ctype ctbase_getConjA (/*@notnull@*/ ctbase p_c) /*@*/ ;
287 static ctype ctbase_getConjB (/*@notnull@*/ ctbase p_c) /*@*/ ;
288 static bool ctbase_isExplicitConj (/*@notnull@*/ ctbase p_c) /*@*/ ;
289 static bool ctbase_forceMatch (ctbase p_c1, ctbase p_c2) /*@modifies p_c1, p_c2@*/ ;
290 static /*@notnull@*/ /*@only@*/ ctbase ctbase_expectFunction (ctype p_c);
291 static bool ctbase_isVoidPointer(/*@notnull@*/ /*@dependent@*/ ctbase p_c) /*@*/ ;
292 static bool ctbase_isUnion (/*@notnull@*/ /*@temp@*/ ctbase p_c) /*@*/ ;
293 static bool ctbase_isStruct (/*@notnull@*/ /*@temp@*/ ctbase p_c) /*@*/ ;
294 static /*@observer@*/ cstring ctbase_enumTag (/*@notnull@*/ ctbase p_ct) /*@*/ ;
295 static /*@only@*/ cstring ctbase_unparseNotypes (ctbase p_c) /*@*/ ;
297 static /*@out@*/ /*@notnull@*/ /*@only@*/ ctbase ctbase_new (void) /*@*/ ;
298 static int nctbases = 0;
300 static /*@notnull@*/ /*@only@*/
301 ctbase ctbase_makeLiveFunction (ctype p_b, /*@only@*/ uentryList p_p);
303 static bool ctbase_isUnnamedSU (ctbase c)
305 return (ctbase_isDefined (c)
306 && (ctbase_isStruct (c) || ctbase_isUnion (c))
307 && isFakeTag (c->contents.su->name));
310 static /*@observer@*/ ctbase ctbase_realType (ctbase c)
314 typeId uid = ctbase_typeId (c);
316 if (usymtab_isBoolType (uid))
318 return ctbase_getBool ();
322 ctbase ret = ctype_getCtbase
323 (uentry_getRealType (usymtab_getTypeEntry (ctbase_typeId (c))));
325 llassert (ret != ctbase_undefined);
336 ctbase_isVoidPointer (/*@dependent@*/ /*@notnull@*/ ctbase c)
338 ctbase r = ctbase_realType (c);
340 return (ctbase_isKind (r, CT_PTR) &&
341 ctype_isVoid (r->contents.base));
345 ctbase_isPointer (/*@notnull@*/ /*@dependent@*/ ctbase c)
347 ctbase r = ctbase_realType (c);
349 return (ctbase_isKind (r, CT_PTR));
353 ctbase_isEitherArray (/*@notnull@*/ ctbase c)
355 ctbase r = ctbase_realType (c);
357 return (ctbase_isKind (r, CT_ARRAY)
358 || ctbase_isKind (r, CT_FIXEDARRAY));
362 ctbase_isFixedArray (/*@notnull@*/ ctbase c)
364 ctbase r = ctbase_realType (c);
366 return (ctbase_isKind (r, CT_FIXEDARRAY));
370 ctbase_isStruct (/*@notnull@*/ ctbase c)
372 ctbase r = ctbase_realType (c);
374 return (ctbase_isKind (r, CT_STRUCT));
378 ctbase_isUnion (/*@notnull@*/ ctbase c)
380 ctbase r = ctbase_realType (c);
382 return (ctbase_isKind (r, CT_UNION));
386 ** clean this up -> typeTable should store ctype
390 ctbase_typeBaseUid (ctbase c)
394 if (ctbase_isDefined (c))
400 return ctbase_typeBaseUid (ctype_getCtbase (c->contents.base));
402 else if (ct == CT_USER || ct == CT_ABST)
404 return c->contents.tid;
406 else if (ct == CT_FIXEDARRAY)
408 return ctbase_typeBaseUid (ctype_getCtbase (c->contents.farray->base));
412 llcontbuglit ("ctbase_typeBaseUid: bad call");
413 return typeId_invalid;
416 return typeId_invalid;
420 ctbase_isBaseUA (ctbase c)
424 if (ctbase_isDefined (c))
430 return ctbase_isBaseUA (ctype_getCtbase (c->contents.base));
432 else if (ct == CT_FIXEDARRAY)
434 return ctbase_isBaseUA (ctype_getCtbase (c->contents.farray->base));
437 return (ct == CT_USER || ct == CT_ABST);
443 ctbase_typeId (ctbase c)
447 return c->contents.tid;
451 if (ctbase_isConj (c))
453 return ctbase_typeId (ctype_getCtbase (ctbase_getConjA (c)));
457 llcontbug (message ("ctbase_typeId: bad call: %q", ctbase_unparse (c)));
458 return typeId_invalid;
463 static /*@only@*/ cstring
464 ctbase_unparse (ctbase c)
466 if (ctbase_isUndefined (c)) {
467 return cstring_makeLiteral ("<<undef>>");
473 return cstring_makeLiteral ("?");
475 return cstring_copy (context_printBoolName ());
477 return (cprim_unparse (c->contents.prim));
479 return (usymtab_getTypeEntryName (c->contents.tid));
481 return (usymtab_getTypeEntryName (c->contents.tid));
483 return (message ("<expf: %t>", c->contents.base));
485 /* no spaces for multiple pointers */
487 if (ctype_isPointer (c->contents.base))
489 return (cstring_appendChar (cstring_copy (ctype_unparse (c->contents.base)), '*'));
493 return (message ("%t *", c->contents.base));
496 return (message ("%t [%d]",
497 c->contents.farray->base,
498 (int) c->contents.farray->size));
500 return (message ("%t []", c->contents.base));
502 return (message ("[function (%q) returns %t]",
503 uentryList_unparseParams (c->contents.fcn->params),
504 c->contents.fcn->rval));
506 if (cstring_isDefined (c->contents.su->name) &&
507 !cstring_isEmpty (c->contents.su->name) &&
508 !isFakeTag (c->contents.su->name))
510 return (message ("struct %s", c->contents.su->name));
514 return (message ("struct { %q }",
515 uentryList_unparseAbbrev (c->contents.su->fields)));
518 if (cstring_isDefined (c->contents.su->name) &&
519 !cstring_isEmpty (c->contents.su->name) &&
520 !isFakeTag (c->contents.su->name))
522 return (message ("union %s", c->contents.su->name));
526 return (message ("union { %q }",
527 uentryList_unparseAbbrev (c->contents.su->fields)));
530 if (isFakeTag (c->contents.cenum->tag))
532 return (message ("enum { %q }",
533 enumNameList_unparseBrief (c->contents.cenum->members)));
537 return (message ("enum %s { %q }",
538 c->contents.cenum->tag,
539 enumNameList_unparseBrief (c->contents.cenum->members)));
542 if (ctbase_isAnytype (c))
544 return (cstring_makeLiteral ("<any>"));
546 else if (c->contents.conj->isExplicit || context_getFlag (FLG_SHOWALLCONJS))
548 if (!ctype_isSimple (c->contents.conj->a) ||
549 !ctype_isSimple (c->contents.conj->b))
551 return (message ("<%t> | <%t>", c->contents.conj->a, c->contents.conj->b));
555 return (message ("%t | %t", c->contents.conj->a, c->contents.conj->b));
560 return (cstring_copy (ctype_unparse (c->contents.conj->a)));
567 static /*@only@*/ cstring
568 ctbase_unparseDeep (ctbase c)
570 if (ctbase_isUndefined (c))
572 return cstring_makeLiteral ("<<undef>>");
578 return cstring_makeLiteral ("?");
580 return cstring_copy (context_printBoolName ());
582 return (cprim_unparse (c->contents.prim));
584 if (cstring_isNonEmpty (c->contents.cenum->tag))
586 return (message ("enum %s { %q }",
587 c->contents.cenum->tag,
588 enumNameList_unparse (c->contents.cenum->members)));
592 return (message ("enum { %q }",
593 enumNameList_unparse (c->contents.cenum->members)));
596 return (usymtab_getTypeEntryName (c->contents.tid));
598 return (usymtab_getTypeEntryName (c->contents.tid));
600 return (message ("<expf: %t>", c->contents.base));
602 return (message ("%t *", c->contents.base));
604 return (message ("%t [%d]", c->contents.farray->base,
605 (int) c->contents.farray->size));
607 return (message ("%t []", c->contents.base));
609 return (message ("[function (%q) returns %t]",
610 uentryList_unparse (c->contents.fcn->params),
611 c->contents.fcn->rval));
613 return (message ("struct %s { ... } ", c->contents.su->name));
615 return (message ("union %s { ... }", c->contents.su->name));
617 if (ctbase_isAnytype (c))
619 return (cstring_makeLiteral ("<any>"));
623 return (message ("%t", c->contents.conj->a));
630 static /*@only@*/ cstring
631 ctbase_unparseNotypes (ctbase c)
633 llassert (ctbase_isDefined (c));
638 return cstring_makeLiteral ("?");
640 return cstring_copy (context_printBoolName ());
642 return (cprim_unparse (c->contents.prim));
644 if (typeId_isInvalid (c->contents.tid))
646 return cstring_makeLiteral ("enum");
650 return (message ("T#%d", c->contents.tid));
653 return (message ("uT#%d", c->contents.tid));
655 return (message ("aT#%d", c->contents.tid));
657 return (message ("<expf: %q >", ctbase_unparseNotypes (ctype_getCtbase (c->contents.base))));
659 return (message ("%q *", ctbase_unparseNotypes (ctype_getCtbase (c->contents.base))));
661 return (message ("%q []", ctbase_unparseNotypes (ctype_getCtbase (c->contents.base))));
663 return (message ("[function (%d) returns %q]", uentryList_size (c->contents.fcn->params),
664 ctbase_unparseNotypes (ctype_getCtbase (c->contents.fcn->rval))));
666 return (message ("struct %s", c->contents.su->name));
668 return (message ("union %s", c->contents.su->name));
670 return (message ("[enumlist]"));
672 if (ctbase_isAnytype (c))
674 return (cstring_makeLiteral ("<any>"));
678 return (message ("%q/%q",
679 ctbase_unparseNotypes (ctype_getCtbase (c->contents.conj->a)),
680 ctbase_unparseNotypes (ctype_getCtbase (c->contents.conj->b))));
687 static /*@only@*/ cstring
688 ctbase_unparseDeclaration (ctbase c, /*@only@*/ cstring name) /*@*/
690 if (ctbase_isUndefined (c))
698 return (message ("? %q", name));
700 return (message ("%s %q", context_printBoolName (), name));
702 return (message ("%q %q", cprim_unparse (c->contents.prim), name));
705 return (message ("%q %q", usymtab_getTypeEntryName (c->contents.tid), name));
707 llcontbuglit ("ctbase_unparseDeclaration: expfcn");
710 if (ctype_isFunction (c->contents.base))
712 return ctbase_unparseDeclaration (ctype_getCtbase (c->contents.base), name);
716 cstring s = cstring_prependChar ('*', name);
717 cstring ret = ctbase_unparseDeclaration (ctype_getCtbase (c->contents.base), s);
722 return (message ("%q[%d]",
723 ctbase_unparseDeclaration (ctype_getCtbase (c->contents.farray->base), name),
724 (int) c->contents.farray->size));
726 return (message ("%q[]",
727 ctbase_unparseDeclaration (ctype_getCtbase (c->contents.base), name)));
730 cstring s = message ("%q(%q)", name,
731 uentryList_unparseParams (c->contents.fcn->params));
733 return (ctbase_unparseDeclaration
734 (ctype_getCtbase (c->contents.fcn->rval), s));
737 if (cstring_isDefined (c->contents.su->name) &&
738 !cstring_isEmpty (c->contents.su->name) &&
739 !isFakeTag (c->contents.su->name))
741 return (message ("struct %s %q", c->contents.su->name, name));
745 return (message ("struct { %q } %q",
746 uentryList_unparseAbbrev (c->contents.su->fields),
750 if (cstring_isDefined (c->contents.su->name) &&
751 !cstring_isEmpty (c->contents.su->name) &&
752 !isFakeTag (c->contents.su->name))
754 return (message ("union %s %q", c->contents.su->name, name));
758 return (message ("union { %q } %q",
759 uentryList_unparseAbbrev (c->contents.su->fields),
763 if (isFakeTag (c->contents.cenum->tag))
765 return (message ("enum { %q } %q",
766 enumNameList_unparseBrief (c->contents.cenum->members),
771 return (message ("enum %s { %q } %q",
772 c->contents.cenum->tag,
773 enumNameList_unparseBrief (c->contents.cenum->members),
777 if (ctbase_isAnytype (c))
779 return (message ("<any> %q", name));
781 else if (c->contents.conj->isExplicit || context_getFlag (FLG_SHOWALLCONJS))
783 if (!ctype_isSimple (c->contents.conj->a) ||
784 !ctype_isSimple (c->contents.conj->b))
786 cstring name1 = cstring_copy (name);
791 ctbase_unparseDeclaration
792 (ctype_getCtbase (c->contents.conj->a), name1),
793 ctbase_unparseDeclaration
794 (ctype_getCtbase (c->contents.conj->b), name)));
798 cstring s1 = ctbase_unparseDeclaration (ctype_getCtbase (c->contents.conj->a),
799 cstring_copy (name));
801 (message ("%q | %q", s1,
802 ctbase_unparseDeclaration (ctype_getCtbase (c->contents.conj->b),
809 return (cstring_copy (ctype_unparse (c->contents.conj->a)));
816 static ctbase ctbase_undump (d_char *c) /*@requires maxRead(*c) >= 2 @*/
826 return (ctbase_undefined);
828 return (ctbase_createUnknown ());
830 return (ctbase_createBool ());
832 res = ctbase_createPrim (cprim_fromInt (reader_getInt (c)));
833 reader_checkChar (c, '|');
836 res = ctbase_createUser (typeId_fromInt (reader_getInt (c)));
837 reader_checkChar (c, '|');
840 res = ctbase_createAbstract (typeId_fromInt (reader_getInt (c)));
841 reader_checkChar (c, '|');
844 res = ctbase_makePointer (ctype_undump (c));
845 reader_checkChar (c, '|');
848 res = ctbase_makeArray (ctype_undump (c));
849 reader_checkChar (c, '|');
853 ctype ct = ctype_undump (c);
856 reader_checkChar (c, '/');
857 size = size_fromInt (reader_getInt (c));
858 reader_checkChar (c, '|');
859 return (ctbase_makeFixedArray (ct, size));
864 char *lp = strchr (*c, '(');
866 llassertfatal (lp != NULL);
869 ct = ctype_undump (c);
872 return (ctbase_makeLiveFunction (ct, uentryList_undump (c)));
879 char *lc = strchr (*c, '{');
881 llassert (lc != NULL);
884 sname = mstring_copy (*c);
892 i = (unsigned) atoi (sname + 1);
897 fields = uentryList_undumpFields (c, g_currentloc);
899 ctb = ctbase_createStruct (cstring_fromCharsO (sname), fields);
905 char *lc = strchr (*c, '{');
907 llassert (lc != NULL);
910 sname = mstring_copy (*c);
911 llassert (sname != NULL);
919 i = (unsigned) atoi (sname + 1);
923 return (ctbase_createUnion (cstring_fromCharsO (sname),
924 uentryList_undumpFields (c, g_currentloc)));
930 char *lc = strchr (*c, '{');
932 llassert (lc != NULL);
935 sname = mstring_copy (*c);
942 i = (unsigned) atoi (sname + 1);
946 ret = ctbase_createEnum (cstring_fromCharsO (sname),
947 enumNameList_undump (c));
955 isExplicit = bool_fromInt (reader_getInt (c));
956 reader_checkChar (c, '.');
957 c1 = ctype_undump (c);
958 reader_checkChar (c, '/');
959 c2 = ctype_undump (c);
960 reader_checkChar (c, '|');
962 return (ctbase_makeConj (c1, c2, isExplicit));
968 message ("Bad Library line (type): %s", cstring_fromChars (*c)));
970 /*drl bee: pbr*/ while (**c != '\0')
975 return ctbase_createUnknown ();
979 /* first letter of c encodes type: */
995 static /*@only@*/ cstring
996 ctbase_dump (ctbase c)
998 if (!ctbase_isDefined (c))
1000 return cstring_makeLiteral ("?");
1006 return cstring_makeLiteral ("u");
1008 return cstring_makeLiteral ("b");
1010 return (message ("p%d|", c->contents.prim));
1012 return (message ("s%d|",
1013 usymtab_convertId (c->contents.tid)));
1015 return (message ("a%d|", usymtab_convertId (c->contents.tid)));
1017 return (message ("t%q|", ctype_dump (c->contents.base)));
1019 return (message ("y%q|", ctype_dump (c->contents.base)));
1021 return (message ("F%q/%d|",
1022 ctype_dump (c->contents.farray->base),
1023 (int) c->contents.farray->size));
1025 DPRINTF (("Dump function: %s", ctbase_unparse (c)));
1026 return (message ("f%q (%q)", ctype_dump (c->contents.fcn->rval),
1027 uentryList_dumpParams (c->contents.fcn->params)));
1029 return (message ("S%s{%q}", c->contents.su->name,
1030 uentryList_dumpFields (c->contents.su->fields)));
1032 return (message ("U%s{%q}", c->contents.su->name,
1033 uentryList_dumpFields (c->contents.su->fields)));
1038 if (cstring_isNonEmpty (c->contents.cenum->tag))
1040 s = message ("e%s{%q}",
1041 c->contents.cenum->tag,
1042 enumNameList_dump (c->contents.cenum->members));
1046 s = message ("e{%q}",
1047 enumNameList_dump (c->contents.cenum->members));
1052 return (message ("C%d.%q/%q|",
1053 bool_toInt (c->contents.conj->isExplicit),
1054 ctype_dump (c->contents.conj->a),
1055 ctype_dump (c->contents.conj->b)));
1057 /* should clean them up! */
1058 return (cstring_makeLiteral ("?"));
1060 llcontbug (message ("Cannot dump: %q", ctbase_unparse (c)));
1061 return (message ("u"));
1068 static /*@only@*/ ctbase
1069 ctbase_copy (/*@notnull@*/ ctbase c)
1074 return (ctbase_createUnknown ());
1076 return (ctbase_createBool ());
1078 return (ctbase_createEnum (cstring_copy (c->contents.cenum->tag),
1079 enumNameList_copy (c->contents.cenum->members)));
1081 return (ctbase_createPrim (c->contents.prim));
1083 return (ctbase_createUser (c->contents.tid));
1085 return (ctbase_createAbstract (c->contents.tid));
1087 return (ctbase_expectFunction (c->contents.base));
1089 return (ctbase_makePointer (c->contents.base));
1091 return (ctbase_makeArray (c->contents.base));
1093 return (ctbase_makeLiveFunction (c->contents.fcn->rval,
1094 uentryList_copy (c->contents.fcn->params)));
1096 return (ctbase_createStruct (cstring_copy (c->contents.su->name),
1097 uentryList_copy (c->contents.su->fields)));
1099 return (ctbase_createUnion (cstring_copy (c->contents.su->name),
1100 uentryList_copy (c->contents.su->fields)));
1102 /*@i@*/ return (c); /* not a real copy for conj's */
1104 llbug (message ("ctbase_copy: %q", ctbase_unparse (c)));
1111 ctbase_elist (ctbase c)
1113 llassert (ctbase_isDefined (c));
1114 llassert (c->type == CT_ENUM);
1116 return (c->contents.cenum->members);
1120 ctbase_free (/*@only@*/ ctbase c)
1122 if (c == ctbase_bool || c == ctbase_unknown)
1124 /*@-mustfree@*/ return; /*@=mustfree@*/
1130 if (ctbase_isDefined (c))
1158 /*@i32@*/ /* uentryList_free (c->contents.fcn->params); */
1163 cstring_free (c->contents.su->name);
1164 uentryList_free (c->contents.su->fields);
1168 /* Don't bree conj's, */
1178 ** c should be * <unknown>
1181 static /*@only@*/ ctbase
1182 ctbase_expectFunction (ctype c)
1184 ctbase f = ctbase_new ();
1186 f->type = CT_EXPFCN;
1187 f->contents.base = c;
1193 ctbase_isExpectFunction (/*@notnull@*/ ctbase ct) /*@*/
1195 return (ct->type == CT_EXPFCN);
1199 ctbase_getExpectFunction (/*@notnull@*/ ctbase ct)
1201 llassert (ctbase_isExpectFunction (ct));
1202 return ct->contents.base;
1206 ctbase_genMatch (ctbase c1, ctbase c2, bool force, bool arg, bool def, bool deep)
1210 /* undefined types never match */
1212 if (ctbase_isUndefined (c1) || ctbase_isUndefined (c2))
1215 /* abstract types match user types of same name */
1217 c1 = ctbase_realType (c1);
1218 c2 = ctbase_realType (c2);
1220 DPRINTF (("Matching: %s / %s", ctbase_unparse (c1),
1221 ctbase_unparse (c2)));
1226 if (c1tid == CT_CONJ)
1228 return (ctbase_genMatch (ctype_getCtbase (c1->contents.conj->a), c2,
1229 force, arg, def, deep)
1230 || ctbase_genMatch (ctype_getCtbase (c1->contents.conj->b), c2,
1231 force, arg, def, deep));
1234 if (c2tid == CT_CONJ)
1236 return (ctbase_genMatch (c1, ctype_getCtbase (c2->contents.conj->a),
1237 force, arg, def, deep)
1238 || ctbase_genMatch (c1, ctype_getCtbase (c2->contents.conj->b),
1239 force, arg, def, deep));
1243 ** if the types don't match, there are some special cases...
1248 /* unknowns match anything */
1250 if (c1tid == CT_UNKNOWN || c2tid == CT_UNKNOWN)
1255 if (c1tid == CT_FIXEDARRAY
1256 && (c2tid == CT_ARRAY || (!def && c2tid == CT_PTR)))
1258 if (ctype_isVoid (c2->contents.base))
1260 return (context_getFlag (FLG_ABSTVOIDP) ||
1261 (!(ctype_isRealAbstract (c1->contents.farray->base)) &&
1262 !(ctype_isRealAbstract (c2->contents.base))));
1265 return (ctbase_genMatch (ctype_getCtbase (c1->contents.farray->base),
1266 ctype_getCtbase (c2->contents.base),
1267 force, arg, def, deep));
1271 if (c2tid == CT_FIXEDARRAY
1272 && (c1tid == CT_ARRAY || (!def && c1tid == CT_PTR)))
1274 if (ctype_isVoid (c1->contents.base))
1276 return (context_getFlag (FLG_ABSTVOIDP) ||
1277 (!(ctype_isRealAbstract (c2->contents.farray->base)) &&
1278 !(ctype_isRealAbstract (c1->contents.base))));
1281 return (ctbase_genMatch (ctype_getCtbase (c1->contents.base),
1282 ctype_getCtbase (c2->contents.farray->base),
1283 force, arg, def, deep));
1286 /* evs 2000-07-25: Bool's may match user/abstract types */
1288 if ((c1tid == CT_BOOL
1289 && (c2tid == CT_PRIM && cprim_isInt (c2->contents.prim))) ||
1291 && (c1tid == CT_PRIM && cprim_isInt (c1->contents.prim))))
1293 return (context_msgBoolInt ());
1296 if ((c1tid == CT_BOOL && (c2tid == CT_ABST || c2tid == CT_USER))) {
1297 ctype t2c = c2->contents.base;
1299 return (ctype_isBool (t2c));
1302 if ((c2tid == CT_BOOL && (c1tid == CT_ABST || c1tid == CT_USER))) {
1303 ctype t1c = c1->contents.base;
1305 return (ctype_isBool (t1c));
1308 if ((c1tid == CT_ENUM
1309 && (c2tid == CT_PRIM && cprim_isInt (c2->contents.prim))) ||
1311 && (c1tid == CT_PRIM && cprim_isInt (c1->contents.prim))))
1313 return (context_msgEnumInt ());
1317 ** arrays and pointers...yuk!
1319 ** Considered equivalent except in definitions.
1320 ** (e.g., function parameters are equivalent)
1326 if (ctuid_isAP (c1tid) && ctuid_isAP (c2tid))
1333 ** Function pointers can be removed.
1335 ** [function ..] is equivalent to [function ..] *
1338 if (c1tid == CT_PTR && c2tid == CT_FCN)
1340 if (ctype_isFunction (ctype_realType (c1->contents.base)))
1342 c1 = ctbase_realType (ctype_getCtbaseSafe (c1->contents.base));
1347 if (c2tid == CT_PTR && c1tid == CT_FCN)
1349 if (ctype_isFunction (ctype_realType (c2->contents.base)))
1351 c2 = ctbase_realType (ctype_getCtbaseSafe (c2->contents.base));
1357 ** we allow forward declarations to structures like,
1359 ** typedef struct _t *t;
1362 ** struct _t * to match t
1365 if (context_getFlag (FLG_FORWARDDECL))
1367 if (c1tid == CT_ABST || c1tid == CT_USER)
1369 if (ctuid_isAP (c2tid))
1371 ctype ts = c2->contents.base;
1373 if (ctype_isUA (ts))
1375 typeId ttid = ctype_typeId (ts);
1376 typeId ctid = c1->contents.tid ;
1378 if (usymtab_matchForwardStruct (ctid, ttid))
1386 if (c2tid == CT_ABST || c2tid == CT_USER)
1388 if (ctuid_isAP (c1tid))
1390 ctype ts = c1->contents.base;
1392 if (ctype_isUA (ts))
1394 typeId ttid = ctype_typeId (ts);
1395 typeId ctid = c2->contents.tid ;
1397 if (usymtab_matchForwardStruct (ctid, ttid))
1416 return (cprim_closeEnoughDeep (c1->contents.prim, c2->contents.prim));
1418 return (cprim_closeEnough (c1->contents.prim, c2->contents.prim));
1423 return (typeId_equal (c1->contents.tid, c2->contents.tid));
1425 return (typeId_equal (c1->contents.tid, c2->contents.tid));
1427 return (cstring_equal (c1->contents.cenum->tag, c2->contents.cenum->tag));
1429 if (ctype_isVoid (c1->contents.base)
1430 || (ctype_isVoid (c2->contents.base)))
1432 if (ctype_isFunction (ctype_realType (c1->contents.base))
1433 || ctype_isFunction (ctype_realType (c2->contents.base)))
1435 return (!context_getFlag (FLG_CASTFCNPTR));
1439 return (context_getFlag (FLG_ABSTVOIDP) ||
1440 (!(ctype_isRealAbstract (c1->contents.base)) &&
1441 !(ctype_isRealAbstract (c2->contents.base))));
1446 /* Only allow one implicit function pointer. */
1448 if (!bool_equal (ctype_isRealPointer (c1->contents.base),
1449 ctype_isRealPointer (c2->contents.base))
1450 && (ctype_isRealFunction (c1->contents.base)
1451 || ctype_isRealFunction (c2->contents.base)))
1456 return (ctype_genMatch (c1->contents.base,
1457 c2->contents.base, force, arg, def, TRUE));
1460 if (ctype_isVoid (c1->contents.farray->base)
1461 || ctype_isVoid (c2->contents.farray->base))
1463 return (ctype_genMatch (c1->contents.farray->base,
1464 c2->contents.farray->base,
1465 force, arg, def, deep));
1467 if (ctype_isVoid (c1->contents.base) || ctype_isVoid (c2->contents.base))
1469 return (ctype_genMatch (c1->contents.base, c2->contents.base, force, arg, def, TRUE));
1471 return (ctype_genMatch (c1->contents.fcn->rval,
1472 c2->contents.fcn->rval,
1473 force, arg, def, TRUE)
1474 && uentryList_matchParams (c1->contents.fcn->params,
1475 c2->contents.fcn->params,
1479 DPRINTF (("Struct: %s / %s",
1480 c1->contents.su->name,
1481 c2->contents.su->name));
1483 if (isFakeTag (c1->contents.su->name)
1484 && isFakeTag (c2->contents.su->name))
1486 /* Both fake tags, check structure */
1487 if (cstring_equal (c1->contents.su->name, c2->contents.su->name))
1493 return uentryList_matchFields (c1->contents.su->fields,
1494 c2->contents.su->fields);
1499 if (!cstring_isEmpty (c1->contents.su->name))
1501 return (cstring_equal (c1->contents.su->name, c2->contents.su->name));
1505 if (!cstring_isEmpty (c2->contents.su->name))
1510 llcontbuglit ("ctbase_genMatch: match fields");
1515 llcontbug (message ("ctbase_genMatch: unknown type: %d\n", (int)c1tid));
1521 ** like ctbase_match, except for conjuncts:
1522 ** modifies conjuncts to match only
1526 ctbase_forceMatch (ctbase c1, ctbase c2) /*@modifies c1, c2@*/
1528 return (ctbase_genMatch (c1, c2, TRUE, FALSE, FALSE, FALSE));
1532 ctbase_match (ctbase c1, ctbase c2) /*@modifies nothing@*/
1534 return (ctbase_genMatch (c1, c2, FALSE, FALSE, FALSE, FALSE));
1538 ctbase_matchDef (ctbase c1, ctbase c2) /*@modifies nothing@*/
1540 return (ctbase_genMatch (c1, c2, FALSE, FALSE, TRUE, FALSE));
1544 ctbase_matchArg (ctbase c1, ctbase c2)
1546 return (ctbase_genMatch (c1, c2, FALSE, TRUE, FALSE, FALSE));
1549 static /*@out@*/ /*@only@*/ /*@notnull@*/ ctbase
1552 ctbase c = (ctbase) dmalloc (sizeof (*c));
1556 if (nctbases % 100 == 0 && nctbases > lastnc)
1558 llmsg (message ("ctbases: %d", nctbases));
1565 static /*@only@*/ ctbase
1566 ctbase_createPrim (cprim p)
1568 ctbase c = ctbase_new ();
1571 c->contents.prim = p;
1576 static /*@observer@*/ ctbase
1577 ctbase_getBool (void)
1579 /*@i@*/ return ctbase_createBool ();
1583 ctbase_createBool ()
1585 if (!ctbase_isDefined (ctbase_bool))
1587 ctbase_bool = ctbase_new ();
1588 ctbase_bool->type = CT_BOOL;
1589 ctbase_bool->contents.prim = CTX_BOOL;
1592 /*@-retalias@*/ /*@-globstate@*/
1594 /*@=retalias@*/ /*@=globstate@*/
1597 static /*@only@*/ ctbase
1598 ctbase_createUser (typeId u)
1600 ctbase c = ctbase_new ();
1603 c->contents.tid = u;
1605 llassert (typeId_isValid (u));
1610 static /*@only@*/ ctbase
1611 ctbase_createEnum (/*@keep@*/ cstring etag, /*@keep@*/ enumNameList emembers)
1613 ctbase c = ctbase_new ();
1617 if (cstring_isUndefined (etag))
1619 llcontbuglit ("Undefined enum tag!");
1623 c->contents.cenum = (tenum) dmalloc (sizeof (*c->contents.cenum));
1624 c->contents.cenum->tag = etag;
1625 c->contents.cenum->members = emembers;
1630 static /*@observer@*/ cstring
1631 ctbase_enumTag (/*@notnull@*/ ctbase ct)
1633 return (ct->contents.cenum->tag);
1636 static /*@only@*/ ctbase
1637 ctbase_createAbstract (typeId u)
1639 ctbase c = ctbase_new ();
1642 c->contents.tid = u;
1644 /* also check its abstract? */
1646 llassert (typeId_isValid (c->contents.tid));
1651 static /*@only@*/ ctbase
1652 ctbase_createUnknown (void)
1654 if (!ctbase_isDefined (ctbase_unknown))
1656 ctbase_unknown = ctbase_new ();
1657 ctbase_unknown->type = CT_UNKNOWN;
1658 ctbase_unknown->contents.prim = CTX_UNKNOWN;
1661 /*@-retalias@*/ /*@-globstate@*/
1662 return ctbase_unknown;
1663 /*@=retalias@*/ /*@=globstate@*/
1667 ** requires: result is not assigned to b
1668 ** (should copy, but no way to reclaim storage)
1671 static /*@only@*/ ctbase
1672 ctbase_makePointer (ctype b)
1674 ctbase c = ctbase_new ();
1677 c->contents.base = b;
1682 static /*@only@*/ ctbase
1683 ctbase_makeArray (ctype b)
1685 ctbase c = ctbase_new ();
1688 c->contents.base = b;
1693 static /*@notnull@*/ /*@only@*/ ctbase
1694 ctbase_makeFixedArray (ctype b, size_t size)
1696 ctbase c = ctbase_new ();
1698 c->type = CT_FIXEDARRAY;
1700 c->contents.farray = (tfixed) dmalloc (sizeof (*c->contents.farray));
1701 c->contents.farray->base = b;
1702 c->contents.farray->size = size;
1708 ctbase_makeFunction (ctype b, /*@only@*/ uentryList p)
1710 ctbase c = ctbase_new ();
1714 c->contents.fcn = (cfcn) dmalloc (sizeof (*c->contents.fcn));
1716 if (ctype_isFunction (b)) /* was: && ctype_isPointer (b)) */
1721 if (ctype_isPointer (b))
1723 ctb = ctype_getCtbase (ctype_baseArrayPtr (b));
1727 ctb = ctype_getCtbase (b);
1730 llassert (ctbase_isDefined (ctb));
1731 llassert (ctb->type == CT_FCN);
1733 rval = ctype_makeFunction (ctb->contents.fcn->rval, p);
1735 c->contents.fcn->rval = rval;
1736 c->contents.fcn->params = uentryList_copy (ctb->contents.fcn->params); /* no copy before */
1740 c->contents.fcn->rval = b;
1741 c->contents.fcn->params = uentryList_copy (p); /* no copy before */
1742 /*@-branchstate@*/ /* p is really released on this branch */
1746 ct = cttable_addComplex (c);
1747 return (ct); /* was: ctype_makePointer (ct)); */
1751 ctbase_makeNFFunction (ctype b, /*@only@*/ uentryList p)
1753 ctbase c = ctbase_new ();
1757 c->contents.fcn = (cfcn) dmalloc (sizeof (*c->contents.fcn));
1759 if (ctype_isFunction (b)) /* was && ctype_isPointer (b)) */
1764 if (ctype_isPointer (b))
1766 ctb = ctype_getCtbase (ctype_baseArrayPtr (b));
1770 ctb = ctype_getCtbase (b);
1773 llassert (ctbase_isDefined (ctb));
1774 llassert (ctb->type == CT_FCN);
1776 rval = ctype_makeNFParamsFunction (ctb->contents.fcn->rval, p);
1778 c->contents.fcn->rval = rval;
1779 c->contents.fcn->params = uentryList_copy (ctb->contents.fcn->params);
1783 c->contents.fcn->rval = b;
1784 c->contents.fcn->params = uentryList_copy (p);
1789 ct = cttable_addComplex (c);
1790 return (ct); /* was: ctype_makePointer (ct)); */
1793 static /*@only@*/ ctbase
1794 ctbase_makeLiveFunction (ctype b, /*@only@*/ uentryList p)
1796 ctbase c = ctbase_new ();
1800 c->contents.fcn = (cfcn) dmalloc (sizeof (*c->contents.fcn));
1801 c->contents.fcn->rval = b;
1802 c->contents.fcn->params = p;
1804 /*@-mustfree@*/ return (c); /*@=mustfree@*/
1807 static /*@observer@*/ /*@notnull@*/ ctbase
1808 ctbase_realFunction (/*@dependent@*/ /*@notnull@*/ ctbase c)
1812 if (c->type == CT_FCN)
1817 llassert (ctbase_isFunction (c));
1819 res = ctype_getCtbase (c->contents.base);
1821 llassert (ctbase_isDefined (res));
1827 ctbase_isFunction (ctbase c)
1829 llassert (c != ctbase_undefined);
1831 if (c->type == CT_FCN)
1837 if (c->type == CT_PTR)
1839 ctbase fcn = ctype_getCtbase (ctbase_baseArrayPtr (c));
1841 return (ctbase_isDefined (fcn) && fcn->type == CT_FCN);
1848 /* doesn't copy c1 and c2 */
1850 static /*@only@*/ ctbase
1851 ctbase_makeConj (ctype c1, ctype c2, bool isExplicit)
1853 ctbase c = ctbase_new ();
1857 c->contents.conj = (tconj) dmalloc (sizeof (*c->contents.conj));
1858 c->contents.conj->a = c1;
1859 c->contents.conj->b = c2;
1860 c->contents.conj->isExplicit = isExplicit;
1865 static bool ctbase_isAnytype (/*@notnull@*/ ctbase b)
1868 ** A unknown|dne conj is a special representation for an anytype.
1871 if (b->type == CT_CONJ)
1874 return (b->contents.conj->a == ctype_unknown
1875 && b->contents.conj->b == ctype_dne);
1876 /*@noaccess ctype@*/
1883 ctbase_getConjA (/*@notnull@*/ ctbase c)
1885 llassert (c->type == CT_CONJ);
1886 return (c->contents.conj->a);
1890 ctbase_getConjB (/*@notnull@*/ ctbase c)
1892 llassert (c->type == CT_CONJ);
1893 return (c->contents.conj->b);
1897 ctbase_isExplicitConj (/*@notnull@*/ ctbase c)
1899 llassert (c->type == CT_CONJ);
1900 return (c->contents.conj->isExplicit);
1903 static /*@only@*/ ctbase
1904 ctbase_createStruct (/*@only@*/ cstring n, /*@only@*/ uentryList f)
1906 ctbase c = ctbase_new ();
1908 c->type = CT_STRUCT;
1910 c->contents.su = (tsu) dmalloc (sizeof (*c->contents.su));
1911 c->contents.su->name = n;
1912 c->contents.su->fields = f;
1917 static /*@observer@*/ uentryList
1918 ctbase_getuentryList (/*@notnull@*/ ctbase c)
1920 c = ctbase_realType (c);
1922 if (!(c->type == CT_STRUCT || c->type == CT_UNION))
1923 llfatalbug (message ("ctbase_getuentryList: bad invocation: %q", ctbase_unparse (c)));
1925 return (c->contents.su->fields);
1929 ctbase_createUnion (/*@keep@*/ cstring n, /*@only@*/ uentryList f)
1931 ctbase c = ctbase_new ();
1935 c->contents.su = (tsu) dmalloc (sizeof (*c->contents.su));
1936 c->contents.su->name = n;
1937 c->contents.su->fields = f;
1943 ctbase_baseArrayPtr (/*@notnull@*/ ctbase c)
1946 c = ctbase_realType (c);
1949 if (ct == CT_FIXEDARRAY)
1951 return c->contents.farray->base;
1955 llassert (ctuid_isAP (ct));
1957 return c->contents.base;
1962 ctbase_baseFunction (/*@notnull@*/ ctbase c)
1965 c = ctbase_realFunction (c);
1967 if (c->type != CT_FCN)
1969 llfatalbug (message ("ctbase_baseFunction: bad call: %q", ctbase_unparse (c)));
1972 return (c->contents.fcn->rval);
1976 ctbase_argsFunction (/*@notnull@*/ ctbase c)
1979 c = ctbase_realFunction (c);
1981 if (c->type != CT_FCN)
1983 llfatalbug (message ("ctbase_argsFunction: bad call: %q",
1984 ctbase_unparse (c)));
1986 return (c->contents.fcn->params);
1990 ctbase_baseisExpFcn (ctype c)
1993 c = ctype_removePointers (c);
1995 cb = ctype_getCtbase (c);
1996 llassert (ctbase_isDefined (cb));
1998 if (cb->type == CT_FCN)
2000 c = ctype_removePointers (ctype_getReturnType (c));
2002 cb = ctype_getCtbase (c);
2003 llassert (ctbase_isDefined (cb));
2005 return (cb->type == CT_EXPFCN);
2011 ** ctbase_newBase behaves specially when p is a CONJ:
2013 ** c -> conj (newBase (c, p.a), p.b)
2017 ctbase_newBase (ctype c, ctype p)
2021 DPRINTF (("New base: %s / %s", ctype_unparse (c), ctype_unparse (p)));
2023 if (ctype_isUndefined (c) || ctype_isUnknown (c))
2028 cb = ctype_getCtbase (c);
2030 if (ctype_isConj (p))
2032 ctbase pb = ctype_getCtbase (p);
2034 llassert (ctbase_isDefined (pb));
2036 if (pb->contents.conj->isExplicit)
2038 return (ctype_makeExplicitConj (ctype_newBase (c, pb->contents.conj->a),
2039 pb->contents.conj->b));
2044 return (ctype_makeConj (ctype_newBase (c, pb->contents.conj->a),
2045 pb->contents.conj->b));
2050 if (ctbase_baseisExpFcn (c))
2052 return (ctbase_newBaseExpFcn (c, p));
2055 llassert (ctbase_isDefined (cb));
2074 cbn = ctbase_newBase (cb->contents.base, p);
2075 ret = ctype_makePointer (cbn);
2080 return (ctype_makeFixedArray (ctbase_newBase (cb->contents.farray->base, p),
2081 cb->contents.farray->size));
2083 return (ctype_makeArray (ctbase_newBase (cb->contents.base, p)));
2085 return (ctype_makeRawFunction (ctbase_newBase (cb->contents.fcn->rval, p),
2086 cb->contents.fcn->params));
2088 return (ctype_makeConjAux (ctbase_newBase (cb->contents.conj->a, p),
2089 ctbase_newBase (cb->contents.conj->b, p),
2090 cb->contents.conj->isExplicit));
2092 llcontbug (message ("ctbase_newBase: bad ctbase: %q", ctbase_unparse (cb)));
2099 ctbase_newBaseExpFcn (ctype c, ctype p)
2101 ctbase cb = ctype_getCtbase (c);
2104 ctype fp = ctype_unknown;
2105 uentryList ctargs = ctype_argsFunction (c);
2108 ** okay, this is really ugly...
2110 ** pointers inside <expf> mean pointers to the function;
2111 ** pointers outside <expf> are pointers to the return value;
2112 ** because its a function there is one superfluous pointer.
2116 ** bf is a ctype, used to derived structure of cb
2119 if (!ctbase_isFunction (cb))
2120 llbuglit ("ctbase_newBaseExpFcn: expFcn -> not a function");
2122 tmpct = ctype_getBaseType (ctype_getReturnType (c));
2125 ** pointers before expfcn -> p are pointers to function, not result
2129 tcb = ctype_getCtbase (tmpct);
2131 llassert (ctbase_isDefined (tcb));
2132 tmpct = tcb->contents.base;
2135 ** record pointers to base in fp
2138 while (!ctype_isUnknown (tmpct))
2140 if (ctype_isExpFcn (tmpct)) {
2141 ctbase ttcb = ctype_getCtbase (tmpct);
2144 ** evs 2000-05-16: This is necessary to deal with function pointers in parens.
2145 ** The whole function pointer parsing is a major kludge, but it seems to work,
2146 ** and I'm only embarrassed by it when I haven't look at the C spec recently...
2149 llassert (ctbase_isDefined (ttcb));
2150 tmpct = ttcb->contents.base;
2151 llassert (!ctype_isUnknown (tmpct));
2154 switch (ctype_getCtKind (tmpct))
2157 fp = ctype_makePointer (fp);
2158 /*@switchbreak@*/ break;
2160 fp = ctype_makeArray (fp);
2161 /*@switchbreak@*/ break;
2164 ctbase fbase = ctype_getCtbase (tmpct);
2166 if (ctbase_isFunction (fbase))
2168 fp = ctype_makeFunction (fp, uentryList_copy (ctargs));
2169 ctargs = ctbase_argsFunction (fbase);
2175 ("ctbase_newBaseExpFcn: fixing expfunction: bad complex type: %s [base: %q]",
2176 ctype_unparse (tmpct), ctbase_unparse (fbase)));
2183 (message ("ctbase_newBaseExpFcn: fixing expfunction: bad type: %s",
2184 ctype_unparse (tmpct)));
2188 tmpct = ctype_baseArrayPtr (tmpct);
2192 tmpct = ctype_getReturnType (c);
2195 ** pointers to expf are pointers to return value
2198 while (!ctype_isExpFcn (tmpct))
2200 switch (ctype_getCtKind (tmpct))
2203 p = ctype_makePointer (p);
2204 /*@switchbreak@*/ break;
2206 p = ctype_makeArray (p);
2207 /*@switchbreak@*/ break;
2210 ctbase fbase = ctype_getCtbase (tmpct);
2212 if (ctbase_isFunction (fbase))
2214 p = ctype_makeFunction (p, uentryList_copy (ctbase_argsFunction (fbase)));
2220 ("ctbase_newBaseExpFcn: fixing expfunction: bad complex type: %s",
2221 ctype_unparse (tmpct)));
2229 (message ("ctbase_newBaseExpFcn: fixing expfunction2: bad type: %t",
2234 tmpct = ctype_baseArrayPtr (tmpct);
2240 ** pointers to fp are pointers to function type
2243 ret = ctype_makeRawFunction (p, uentryList_copy (ctargs));
2245 while (ctype_getCtKind (fp) > CTK_PLAIN)
2247 switch (ctype_getCtKind (fp))
2250 ret = ctype_makePointer (ret);
2251 /*@switchbreak@*/ break;
2253 ret = ctype_makeArray (ret);
2254 /*@switchbreak@*/ break;
2257 ctbase fbase = ctype_getCtbase (fp);
2259 if (ctbase_isFunction (fbase))
2262 ctype_makeFunction (ret,
2263 uentryList_copy (ctbase_argsFunction (fbase)));
2274 llcontbug (message ("post-fixing expfunction: bad type: %t", fp));
2278 fp = ctype_baseArrayPtr (fp);
2286 ** returns lowest level base of c: plain type
2289 static /*@notnull@*/ /*@only@*/ ctbase
2290 ctbase_getBaseType (/*@notnull@*/ ctbase c)
2304 return (ctbase_copy (c));
2308 return (ctbase_getBaseType (ctype_getCtbaseSafe (c->contents.base)));
2311 return (ctbase_getBaseType (ctype_getCtbaseSafe (c->contents.farray->base)));
2312 case CT_CONJ: /* base type of A conj branch? */
2313 return (ctbase_getBaseType (ctype_getCtbaseSafe (c->contents.conj->a)));
2315 return (ctbase_copy (c));
2318 llfatalbug (message ("ctbase_getBaseType: bad ctbase: %q", ctbase_unparse (c)));
2325 ctbase_compare (ctbase c1, ctbase c2, bool strict)
2329 if (ctbase_isUndefined (c1) || ctbase_isUndefined (c2))
2331 llcontbuglit ("ctbase_compare: undefined ctbase");
2348 return (int_compare (c1->contents.prim, c2->contents.prim));
2352 return (int_compare (c1->contents.tid, c2->contents.tid));
2355 case CT_ENUM: /* for now, keep like abstract */
2357 return (int_compare (c1->contents.tid, c2->contents.tid));
2359 return (ctype_compare (c1->contents.base, c2->contents.base));
2361 INTCOMPARERETURN (c1->contents.farray->size, c2->contents.farray->size);
2363 return (ctype_compare (c1->contents.farray->base,
2364 c2->contents.farray->base));
2366 return (ctype_compare (c1->contents.base, c2->contents.base));
2369 COMPARERETURN (ctype_compare (c1->contents.fcn->rval, c2->contents.fcn->rval));
2373 return (uentryList_compareStrict (c1->contents.fcn->params,
2374 c2->contents.fcn->params));
2378 return (uentryList_compareParams (c1->contents.fcn->params,
2379 c2->contents.fcn->params));
2383 return (ctype_compare (c1->contents.base, c2->contents.base));
2386 /* evs 2000-07-28: this block was missing! */
2388 int ncmp = cstring_compare (c1->contents.su->name,
2389 c2->contents.su->name);
2392 if (isFakeTag (c1->contents.su->name)
2393 && isFakeTag (c2->contents.su->name)) {
2394 ; /* If they are both fake struct tags, don't require match. */
2401 DPRINTF (("Comparing fields: %s / %s",
2402 ctbase_unparse (c1),
2403 ctbase_unparse (c2)));
2405 return (uentryList_compareFields (c1->contents.su->fields,
2406 c2->contents.su->fields));
2409 COMPARERETURN (ctype_compare (c1->contents.conj->a,
2410 c2->contents.conj->a));
2411 COMPARERETURN (ctype_compare (c1->contents.conj->b,
2412 c2->contents.conj->b));
2413 return (bool_compare (c1->contents.conj->isExplicit,
2414 c2->contents.conj->isExplicit));
2421 ctbase_compareStrict (/*@notnull@*/ ctbase c1, /*@notnull@*/ ctbase c2)
2423 return (ctbase_compare (c1, c2, TRUE));
2426 static bool ctbase_equivStrict (/*@notnull@*/ ctbase c1, /*@notnull@*/ ctbase c2)
2428 return (ctbase_compareStrict (c1,c2) == 0);
2431 static bool ctbase_equiv (/*@notnull@*/ ctbase c1, /*@notnull@*/ ctbase c2)
2433 return (ctbase_compare (c1, c2, FALSE) == 0);
2437 ctbase_isKind (/*@notnull@*/ ctbase c, ctuid kind)
2445 return (ctbase_isKind (ctype_getCtbaseSafe (c->contents.conj->a), kind) ||
2446 ctbase_isKind (ctype_getCtbaseSafe (c->contents.conj->b), kind));
2452 ctbase_isKind2 (/*@notnull@*/ ctbase c, ctuid kind1, ctuid kind2)
2456 if (ck == kind1 || ck == kind2)
2460 return (ctbase_isKind2 (ctype_getCtbaseSafe (c->contents.conj->a), kind1, kind2) ||
2461 ctbase_isKind2 (ctype_getCtbaseSafe (c->contents.conj->b), kind1, kind2));
2467 ctbase_isAbstract (/*@notnull@*/ ctbase c)
2469 return (c->type == CT_ABST);
2472 static bool ctbase_isUA (ctbase c)
2474 return (ctbase_isDefined (c) && ((c)->type == CT_USER || (c)->type == CT_ABST));
2478 ctbase_almostEqual (ctbase c1, ctbase c2)
2482 /* undefined types never match */
2484 if (ctbase_isUndefined (c1) || ctbase_isUndefined (c2))
2490 if (c1tid == CT_FIXEDARRAY && c2tid == CT_ARRAY)
2492 return (ctbase_almostEqual (ctype_getCtbase (c1->contents.farray->base),
2493 ctype_getCtbase (c2->contents.base)));
2496 if (c2tid == CT_FIXEDARRAY && c1tid == CT_ARRAY)
2498 return (ctbase_almostEqual (ctype_getCtbase (c1->contents.base),
2499 ctype_getCtbase (c2->contents.farray->base)));
2510 return (cprim_equal (c1->contents.prim, c2->contents.prim));
2514 return (typeId_equal (c1->contents.tid, c2->contents.tid));
2516 return (typeId_equal (c1->contents.tid, c2->contents.tid));
2518 return (cstring_equal (c1->contents.cenum->tag, c2->contents.cenum->tag));
2520 return (ctype_almostEqual (c1->contents.base, c2->contents.base));
2522 return (ctype_almostEqual (c1->contents.farray->base,
2523 c2->contents.farray->base));
2525 return (ctype_almostEqual (c1->contents.base, c2->contents.base));
2527 return (ctype_almostEqual (c1->contents.fcn->rval, c2->contents.fcn->rval)
2528 && uentryList_matchParams (c1->contents.fcn->params,
2529 c2->contents.fcn->params, FALSE, TRUE));
2532 if (!cstring_isEmpty (c1->contents.su->name))
2534 return (cstring_equal (c1->contents.su->name, c2->contents.su->name));
2538 if (!cstring_isEmpty (c2->contents.su->name))
2543 llcontbuglit ("ctbase_almostEqual: match fields");
2547 llcontbug (message ("ctbase_almostEqual: unknown type: %d\n", (int)c1tid));
2552 /*drl added July 02, 001
2553 called by ctype_getArraySize
2556 size_t ctbase_getArraySize (ctbase ctb)
2558 /*drl 1/25/2002 fixed discovered by Jim Francis */
2561 llassert (ctbase_isDefined (ctb) );
2562 r = ctbase_realType (ctb);
2563 llassert (ctbase_isFixedArray(r) );
2565 return (r->contents.farray->size);