2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 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 /*@function static bool ctuid_isAnyUserType (sef ctuid p_cid) @*/
38 /*@-macrofcndecl@*/ /*@-macroparams@*/
39 # define ctuid_isAnyUserType(cid) \
40 ((cid) == CT_ABST || (cid) == CT_USER || (cid) == CT_NUMABST)
41 /*@=macrofcndecl@*/ /*@=macroparams@*/
43 /*:private:*/ typedef struct {
46 ctype base; /* type I point to (or element of array) */
47 ctype ptr; /* type of pointer to me */
48 ctype array; /* type of array of me */
49 cstring unparse; /* unparse me, if memoized */
52 typedef /*@only@*/ ctentry o_ctentry;
57 /*@relnull@*/ /*@only@*/ o_ctentry *entries;
58 /* memoize matches...maybe in context? */
61 extern bool ctentry_isBogus (/*@sef@*/ ctentry p_c) /*@*/;
62 # define ctentry_isBogus(c) \
63 ((c)->kind == CTK_INVALID || (c)->kind == CTK_DNE)
65 static cttable cttab = { 0, 0, NULL };
67 static /*@notnull@*/ /*@only@*/ ctbase ctbase_createAbstract (typeId p_u);
68 static /*@notnull@*/ /*@only@*/ ctbase ctbase_createNumAbstract (typeId p_u);
69 static /*@observer@*/ cstring ctentry_doUnparse (ctentry p_c) /*@modifies p_c@*/;
70 static /*@only@*/ ctentry
71 ctentry_make (ctkind p_ctk, /*@keep@*/ ctbase p_c, ctype p_base,
72 ctype p_ptr, ctype p_array, /*@keep@*/ cstring p_unparse);
73 static /*@only@*/ ctentry ctentry_makeNew (ctkind p_ctk, /*@only@*/ ctbase p_c);
74 static /*@only@*/ cstring ctentry_unparse (ctentry p_c) /*@*/ ;
76 static void cttable_grow (void);
77 static ctype cttable_addDerived (ctkind p_ctk, /*@keep@*/ ctbase p_cnew, ctype p_base);
78 static ctype cttable_addFull (/*@keep@*/ ctentry p_cnew);
79 static bool ctentry_isInteresting (ctentry p_c) /*@*/;
80 static /*@notnull@*/ /*@only@*/ ctbase ctbase_makeFixedArray (ctype p_b, size_t p_size) /*@*/ ;
81 static bool ctbase_isAnytype (/*@notnull@*/ ctbase p_b) /*@*/ ;
84 ** These are file-static macros (used in ctype.c). No way to
85 ** declare them as static in C.
88 /*@-allmacros@*/ /*@-macrospec@*/ /*@-namechecks@*/
89 # define ctentry_getBase(c) ((c)->base)
90 # define ctentry_getKind(c) ((c)->kind)
91 # define ctentry_getArray(c) ((c)->array)
92 # define ctentry_getPtr(c) ((c)->ptr)
93 # define ctentry_isArray(c) ((c)->kind == CTK_ARRAY)
94 # define ctentry_isComplex(c) ((c)->kind == CTK_COMPLEX)
95 # define ctentry_isPlain(c) ((c)->kind == CTK_PLAIN)
96 # define ctentry_isPointer(c) ((c)->kind == CTK_PTR)
97 # define ctentry_setArray(c,b) ((c)->array = (b))
98 # define ctentry_setPtr(c,b) ((c)->ptr = (b))
100 # define ctbase_fixUser(c) (c = ctbase_realType(c))
101 /*@=allmacros@*/ /*@=macrospec@*/ /*@=namechecks@*/
103 static ctype cttable_addComplex (/*@notnull@*/ /*@only@*/ ctbase p_cnew);
104 static /*@observer@*/ ctbase ctype_getCtbase (ctype p_c) /*@*/ ;
105 static ctype ctype_makeConjAux (ctype p_c1, ctype p_c2, bool p_isExplicit) /*@*/ ;
106 static /*@notnull@*/ /*@observer@*/ ctbase ctype_getCtbaseSafe (ctype p_c) /*@*/ ;
107 static /*@observer@*/ ctentry ctype_getCtentry (ctype p_c) /*@*/ ;
108 static /*@observer@*/ /*@notnull@*/ ctbase
109 ctbase_realType (/*@notnull@*/ ctbase p_c) /*@*/ ;
110 static bool ctbase_isPointer (/*@notnull@*/ /*@dependent@*/ ctbase p_c) /*@*/ ;
111 static bool ctbase_isEitherArray (/*@notnull@*/ /*@dependent@*/ ctbase p_c) /*@*/ ;
112 static /*@observer@*/ enumNameList ctbase_elist (ctbase p_c) /*@*/ ;
113 static /*@only@*/ cstring ctbase_unparse (ctbase p_c) /*@*/ ;
114 static /*@only@*/ cstring ctbase_unparseDeep (ctbase p_c) /*@*/ ;
115 static /*@only@*/ /*@notnull@*/ ctbase ctbase_copy (/*@notnull@*/ ctbase p_c) /*@*/ ;
116 static void ctbase_free (/*@only@*/ ctbase p_c);
117 static /*@notnull@*/ /*@only@*/ ctbase ctbase_createPrim (cprim p_p) /*@*/ ;
118 static /*@notnull@*/ /*@only@*/ ctbase ctbase_createBool (void) /*@*/ ;
119 static /*@notnull@*/ /*@observer@*/ ctbase ctbase_getBool (void) /*@*/ ;
120 static /*@notnull@*/ /*@only@*/ ctbase ctbase_createUser (typeId p_u) /*@*/ ;
122 static /*@notnull@*/ /*@only@*/ ctbase
123 ctbase_createStruct (/*@only@*/ cstring p_n, /*@only@*/ uentryList p_f);
125 static /*@notnull@*/ /*@only@*/ ctbase
126 ctbase_createUnion (/*@keep@*/ cstring p_n, /*@only@*/ uentryList p_f);
127 static /*@notnull@*/ /*@only@*/ ctbase ctbase_createEnum (/*@keep@*/ cstring p_etag, /*@keep@*/ enumNameList p_emembers);
128 static /*@notnull@*/ /*@only@*/ ctbase ctbase_createUnknown (void);
129 static bool ctbase_match (ctbase p_c1, ctbase p_c2) /*@modifies nothing@*/;
130 static bool ctbase_matchDef (ctbase p_c1, ctbase p_c2) /*@modifies nothing@*/;
131 static bool ctbase_genMatch (ctbase p_c1, ctbase p_c2, bool p_force, bool p_arg, bool p_def, bool p_deep);
132 static bool ctbase_isAbstract (/*@notnull@*/ ctbase p_c) /*@*/ ;
133 static /*@notnull@*/ /*@only@*/ ctbase ctbase_makePointer (ctype p_b) /*@*/ ;
134 static /*@notnull@*/ /*@only@*/ ctbase ctbase_makeArray (ctype p_b) /*@*/ ;
135 static /*@notnull@*/ ctype
136 ctbase_makeFunction (ctype p_b, /*@only@*/ uentryList p_p) /*@*/ ;
137 static /*@notnull@*/ /*@observer@*/ ctbase
138 ctbase_realFunction (/*@notnull@*/ /*@dependent@*/ ctbase p_c) /*@*/ ;
139 static ctype ctbase_baseArrayPtr (/*@notnull@*/ ctbase p_c) /*@*/ ;
140 static ctype ctbase_baseFunction (/*@notnull@*/ ctbase p_c) /*@*/ ;
141 static /*@observer@*/ uentryList ctbase_argsFunction (/*@notnull@*/ ctbase p_c) /*@*/ ;
142 static /*@observer@*/ uentryList ctbase_getuentryList (/*@notnull@*/ ctbase p_c) /*@*/ ;
143 static ctype ctbase_newBase (ctype p_c, ctype p_p) /*@*/ ;
144 static ctype ctbase_newBaseExpFcn (ctype p_c, ctype p_p) /*@*/ ;
145 static bool ctbase_isFixedArray (/*@notnull@*/ ctbase p_c) /*@*/ ;
148 extern int cttable_lastIndex();
149 # define cttable_lastIndex() (cttab.size - 1)
155 /*@only@*/ uentryList params;
174 enumNameList members;
185 cprim prim; /* primitive */
186 typeId tid; /* abstract, user */
187 ctype base; /* ptr, array */
188 cfcn fcn; /* function */
189 tsu su; /* struct union */
190 tenum cenum; /* enum */
191 tconj conj; /* conj */
192 tfixed farray; /* fixed array */
201 static /*@falsenull@*/ bool ctbase_isUA (ctbase p_c) /*@*/ ;
202 static bool ctbase_isBaseUA(ctbase p_c) /*@*/ ;
203 static typeId ctbase_typeBaseUid(ctbase p_c) /*@*/ ;
204 static bool ctbase_isKind (/*@notnull@*/ ctbase p_c, ctuid p_kind) /*@*/ ;
205 static bool ctbase_isKind2 (/*@notnull@*/ ctbase p_c, ctuid p_kind1, ctuid p_kind2) /*@*/ ;
206 static /*@only@*/ /*@notnull@*/ ctbase
207 ctbase_getBaseType (/*@notnull@*/ ctbase p_c) /*@*/ ;
209 static /*@falsenull@*/ bool ctbase_isFunction(ctbase p_c) /*@*/ ;
211 /*@constant null ctbase ctbase_undefined; @*/
212 # define ctbase_undefined ((ctbase)0)
214 static /*@owned@*/ ctbase ctbase_bool = ctbase_undefined;
215 static /*@owned@*/ ctbase ctbase_unknown = ctbase_undefined;
217 static /*@falsenull@*/ bool ctbase_isDefined (ctbase c) /*@*/
219 return ((c) != ctbase_undefined);
222 static /*@truenull@*/ bool ctbase_isUndefined (ctbase c)
224 return ((c) == ctbase_undefined);
227 static ctkind ctype_getCtKind (ctype c)
229 ctentry ce = ctype_getCtentry (c);
231 return ctentry_getKind (ce);
234 static bool ctbase_isUser (ctbase c)
236 if (ctbase_isDefined (c))
238 return (ctbase_isKind (c, CT_USER));
246 static bool ctbase_isEnum (ctbase c)
248 if (ctbase_isDefined (c))
250 return (ctbase_isKind (c, CT_ENUM));
258 static bool ctbase_isExpFcn (ctbase c)
260 if (ctbase_isDefined (c))
262 return (c->type == CT_EXPFCN);
270 static /*@falsenull@*/ bool ctbase_isConj (ctbase c)
272 if (ctbase_isDefined (c))
274 return (c->type == CT_CONJ);
282 static bool ctuid_isAP (ctuid c) /*@*/
284 return (c == CT_ARRAY || c == CT_PTR);
287 static typeId ctbase_typeId (ctbase p_c);
288 static /*@only@*/ cstring ctbase_dump (ctbase p_c);
289 static /*@only@*/ ctbase ctbase_undump (char **p_c) /*@requires maxRead(*p_c) >= 2 @*/;
290 static int ctbase_compare (ctbase p_c1, ctbase p_c2, bool p_strict);
291 static bool ctbase_matchArg (ctbase p_c1, ctbase p_c2);
292 static /*@notnull@*/ /*@only@*/ ctbase
293 ctbase_makeConj (ctype p_c1, ctype p_c2, bool p_isExplicit) /*@*/ ;
294 static ctype ctbase_getConjA (/*@notnull@*/ ctbase p_c) /*@*/ ;
295 static ctype ctbase_getConjB (/*@notnull@*/ ctbase p_c) /*@*/ ;
296 static bool ctbase_isExplicitConj (/*@notnull@*/ ctbase p_c) /*@*/ ;
297 static bool ctbase_forceMatch (ctbase p_c1, ctbase p_c2) /*@modifies p_c1, p_c2@*/ ;
298 static /*@notnull@*/ /*@only@*/ ctbase ctbase_expectFunction (ctype p_c);
299 static bool ctbase_isVoidPointer(/*@notnull@*/ /*@dependent@*/ ctbase p_c) /*@*/ ;
300 static bool ctbase_isUnion (/*@notnull@*/ /*@temp@*/ ctbase p_c) /*@*/ ;
301 static bool ctbase_isStruct (/*@notnull@*/ /*@temp@*/ ctbase p_c) /*@*/ ;
302 static /*@observer@*/ cstring ctbase_enumTag (/*@notnull@*/ ctbase p_ct) /*@*/ ;
303 static /*@only@*/ cstring ctbase_unparseNotypes (ctbase p_c) /*@*/ ;
305 static /*@out@*/ /*@notnull@*/ /*@only@*/ ctbase ctbase_new (void) /*@*/ ;
306 static int nctbases = 0;
308 static /*@notnull@*/ /*@only@*/
309 ctbase ctbase_makeLiveFunction (ctype p_b, /*@only@*/ uentryList p_p);
311 static bool ctbase_isUnnamedSU (ctbase c)
313 return (ctbase_isDefined (c)
314 && (ctbase_isStruct (c) || ctbase_isUnion (c))
315 && isFakeTag (c->contents.su->name));
318 static /*@observer@*/ ctbase ctbase_realType (ctbase c)
322 typeId uid = ctbase_typeId (c);
324 if (usymtab_isBoolType (uid))
326 return ctbase_getBool ();
330 ctbase ret = ctype_getCtbase
331 (uentry_getRealType (usymtab_getTypeEntry (ctbase_typeId (c))));
333 llassert (ret != ctbase_undefined);
344 ctbase_isVoidPointer (/*@dependent@*/ /*@notnull@*/ ctbase c)
346 ctbase r = ctbase_realType (c);
348 return (ctbase_isKind (r, CT_PTR) &&
349 ctype_isVoid (r->contents.base));
353 ctbase_isPointer (/*@notnull@*/ /*@dependent@*/ ctbase c)
355 ctbase r = ctbase_realType (c);
357 return (ctbase_isKind (r, CT_PTR));
361 ctbase_isEitherArray (/*@notnull@*/ ctbase c)
363 ctbase r = ctbase_realType (c);
365 return (ctbase_isKind (r, CT_ARRAY)
366 || ctbase_isKind (r, CT_FIXEDARRAY));
370 ctbase_isFixedArray (/*@notnull@*/ ctbase c)
372 ctbase r = ctbase_realType (c);
374 return (ctbase_isKind (r, CT_FIXEDARRAY));
378 ctbase_isStruct (/*@notnull@*/ ctbase c)
380 ctbase r = ctbase_realType (c);
382 return (ctbase_isKind (r, CT_STRUCT));
386 ctbase_isUnion (/*@notnull@*/ ctbase c)
388 ctbase r = ctbase_realType (c);
390 return (ctbase_isKind (r, CT_UNION));
394 ** clean this up -> typeTable should store ctype
398 ctbase_typeBaseUid (ctbase c)
402 if (ctbase_isDefined (c))
408 return ctbase_typeBaseUid (ctype_getCtbase (c->contents.base));
410 else if (ct == CT_USER || ct == CT_ABST || ct == CT_NUMABST)
412 return c->contents.tid;
414 else if (ct == CT_FIXEDARRAY)
416 return ctbase_typeBaseUid (ctype_getCtbase (c->contents.farray->base));
420 llcontbuglit ("ctbase_typeBaseUid: bad call");
421 return typeId_invalid;
424 return typeId_invalid;
428 ctbase_isBaseUA (ctbase c)
432 if (ctbase_isDefined (c))
438 return ctbase_isBaseUA (ctype_getCtbase (c->contents.base));
440 else if (ct == CT_FIXEDARRAY)
442 return ctbase_isBaseUA (ctype_getCtbase (c->contents.farray->base));
445 return (ct == CT_USER || ct == CT_ABST || ct == CT_NUMABST);
451 ctbase_typeId (ctbase c)
455 return c->contents.tid;
459 if (ctbase_isConj (c))
461 return ctbase_typeId (ctype_getCtbase (ctbase_getConjA (c)));
465 llcontbug (message ("ctbase_typeId: bad call: %q", ctbase_unparse (c)));
466 return typeId_invalid;
471 static /*@only@*/ cstring
472 ctbase_unparse (ctbase c)
474 if (ctbase_isUndefined (c)) {
475 return cstring_makeLiteral ("<<undef>>");
481 return cstring_makeLiteral ("?");
483 return cstring_copy (context_printBoolName ());
485 return (cprim_unparse (c->contents.prim));
489 return (usymtab_getTypeEntryName (c->contents.tid));
491 return (message ("<expf: %t>", c->contents.base));
493 /* no spaces for multiple pointers */
495 if (ctype_isPointer (c->contents.base))
497 return (cstring_appendChar (cstring_copy (ctype_unparse (c->contents.base)), '*'));
501 return (message ("%t *", c->contents.base));
505 ** C prints out array declarations backwards, if
506 ** base is an array need to print out in reverse order.
509 if (ctype_isArray (c->contents.farray->base))
511 ctype base = c->contents.farray->base;
512 cstring res = message ("[%d]", (int) c->contents.farray->size);
514 while (ctype_isArray (base))
516 if (ctype_isFixedArray (base))
518 res = message ("%q[%d]",
519 res, (int) ctype_getArraySize (base));
523 res = message ("%q[]", res);
526 base = ctype_baseArrayPtr (base);
529 return (message ("%t %q", base, res));
533 return (message ("%t [%d]",
534 c->contents.farray->base,
535 (int) c->contents.farray->size));
538 if (ctype_isArray (c->contents.base))
540 ctype base = c->contents.base;
541 cstring res = cstring_makeLiteral ("[]");
543 while (ctype_isArray (base))
545 if (ctype_isFixedArray (base))
547 res = message ("%q[%d]",
548 res, (int) ctype_getArraySize (base));
552 res = message ("%q[]", res);
555 base = ctype_baseArrayPtr (base);
558 return (message ("%t %q", base, res));
563 return (message ("%t []", c->contents.base));
566 return (message ("[function (%q) returns %t]",
567 uentryList_unparseParams (c->contents.fcn->params),
568 c->contents.fcn->rval));
570 if (cstring_isDefined (c->contents.su->name) &&
571 !cstring_isEmpty (c->contents.su->name) &&
572 !isFakeTag (c->contents.su->name))
574 return (message ("struct %s", c->contents.su->name));
578 return (message ("struct { %q }",
579 uentryList_unparseAbbrev (c->contents.su->fields)));
582 if (cstring_isDefined (c->contents.su->name) &&
583 !cstring_isEmpty (c->contents.su->name) &&
584 !isFakeTag (c->contents.su->name))
586 return (message ("union %s", c->contents.su->name));
590 return (message ("union { %q }",
591 uentryList_unparseAbbrev (c->contents.su->fields)));
594 if (isFakeTag (c->contents.cenum->tag))
596 return (message ("enum { %q }",
597 enumNameList_unparseBrief (c->contents.cenum->members)));
601 return (message ("enum %s { %q }",
602 c->contents.cenum->tag,
603 enumNameList_unparseBrief (c->contents.cenum->members)));
606 if (ctbase_isAnytype (c))
608 return (cstring_makeLiteral ("<any>"));
610 else if (c->contents.conj->isExplicit || context_getFlag (FLG_SHOWALLCONJS))
612 if (!ctype_isSimple (c->contents.conj->a) ||
613 !ctype_isSimple (c->contents.conj->b))
615 return (message ("<%t> | <%t>", c->contents.conj->a, c->contents.conj->b));
619 return (message ("%t | %t", c->contents.conj->a, c->contents.conj->b));
624 return (cstring_copy (ctype_unparse (c->contents.conj->a)));
631 static /*@only@*/ cstring
632 ctbase_unparseDeep (ctbase c)
634 if (ctbase_isUndefined (c))
636 return cstring_makeLiteral ("<<undef>>");
642 return cstring_makeLiteral ("?");
644 return cstring_copy (context_printBoolName ());
646 return (cprim_unparse (c->contents.prim));
648 if (cstring_isNonEmpty (c->contents.cenum->tag))
650 return (message ("enum %s { %q }",
651 c->contents.cenum->tag,
652 enumNameList_unparse (c->contents.cenum->members)));
656 return (message ("enum { %q }",
657 enumNameList_unparse (c->contents.cenum->members)));
662 return (usymtab_getTypeEntryName (c->contents.tid));
664 return (message ("<expf: %t>", c->contents.base));
666 return (message ("%t *", c->contents.base));
668 return (message ("%t [%d]", c->contents.farray->base,
669 (int) c->contents.farray->size));
671 return (message ("%t []", c->contents.base));
673 return (message ("[function (%q) returns %t]",
674 uentryList_unparse (c->contents.fcn->params),
675 c->contents.fcn->rval));
677 return (message ("struct %s { ... } ", c->contents.su->name));
679 return (message ("union %s { ... }", c->contents.su->name));
681 if (ctbase_isAnytype (c))
683 return (cstring_makeLiteral ("<any>"));
687 return (message ("%t", c->contents.conj->a));
694 static /*@only@*/ cstring
695 ctbase_unparseNotypes (ctbase c)
697 llassert (ctbase_isDefined (c));
702 return cstring_makeLiteral ("?");
704 return cstring_copy (context_printBoolName ());
706 return (cprim_unparse (c->contents.prim));
708 if (typeId_isInvalid (c->contents.tid))
710 return cstring_makeLiteral ("enum");
714 return (message ("T#%d", c->contents.tid));
717 return (message ("uT#%d", c->contents.tid));
719 return (message ("aT#%d", c->contents.tid));
721 return (message ("nT#%d", c->contents.tid));
723 return (message ("<expf: %q >", ctbase_unparseNotypes (ctype_getCtbase (c->contents.base))));
725 return (message ("%q *", ctbase_unparseNotypes (ctype_getCtbase (c->contents.base))));
727 return (message ("%q []", ctbase_unparseNotypes (ctype_getCtbase (c->contents.base))));
729 return (message ("[function (%d) returns %q]", uentryList_size (c->contents.fcn->params),
730 ctbase_unparseNotypes (ctype_getCtbase (c->contents.fcn->rval))));
732 return (message ("struct %s", c->contents.su->name));
734 return (message ("union %s", c->contents.su->name));
736 return (message ("[enumlist]"));
738 if (ctbase_isAnytype (c))
740 return (cstring_makeLiteral ("<any>"));
744 return (message ("%q/%q",
745 ctbase_unparseNotypes (ctype_getCtbase (c->contents.conj->a)),
746 ctbase_unparseNotypes (ctype_getCtbase (c->contents.conj->b))));
753 static /*@only@*/ cstring
754 ctbase_unparseDeclaration (ctbase c, /*@only@*/ cstring name) /*@*/
756 if (ctbase_isUndefined (c))
764 return (message ("? %q", name));
766 return (message ("%s %q", context_printBoolName (), name));
768 return (message ("%q %q", cprim_unparse (c->contents.prim), name));
772 return (message ("%q %q", usymtab_getTypeEntryName (c->contents.tid), name));
774 llcontbuglit ("ctbase_unparseDeclaration: expfcn");
777 if (ctype_isFunction (c->contents.base))
779 return ctbase_unparseDeclaration (ctype_getCtbase (c->contents.base), name);
783 cstring s = cstring_prependChar ('*', name);
784 cstring ret = ctbase_unparseDeclaration (ctype_getCtbase (c->contents.base), s);
789 return (message ("%q[%d]",
790 ctbase_unparseDeclaration (ctype_getCtbase (c->contents.farray->base), name),
791 (int) c->contents.farray->size));
793 return (message ("%q[]",
794 ctbase_unparseDeclaration (ctype_getCtbase (c->contents.base), name)));
797 cstring s = message ("%q(%q)", name,
798 uentryList_unparseParams (c->contents.fcn->params));
800 return (ctbase_unparseDeclaration
801 (ctype_getCtbase (c->contents.fcn->rval), s));
804 if (cstring_isDefined (c->contents.su->name) &&
805 !cstring_isEmpty (c->contents.su->name) &&
806 !isFakeTag (c->contents.su->name))
808 return (message ("struct %s %q", c->contents.su->name, name));
812 return (message ("struct { %q } %q",
813 uentryList_unparseAbbrev (c->contents.su->fields),
817 if (cstring_isDefined (c->contents.su->name) &&
818 !cstring_isEmpty (c->contents.su->name) &&
819 !isFakeTag (c->contents.su->name))
821 return (message ("union %s %q", c->contents.su->name, name));
825 return (message ("union { %q } %q",
826 uentryList_unparseAbbrev (c->contents.su->fields),
830 if (isFakeTag (c->contents.cenum->tag))
832 return (message ("enum { %q } %q",
833 enumNameList_unparseBrief (c->contents.cenum->members),
838 return (message ("enum %s { %q } %q",
839 c->contents.cenum->tag,
840 enumNameList_unparseBrief (c->contents.cenum->members),
844 if (ctbase_isAnytype (c))
846 return (message ("<any> %q", name));
848 else if (c->contents.conj->isExplicit || context_getFlag (FLG_SHOWALLCONJS))
850 if (!ctype_isSimple (c->contents.conj->a) ||
851 !ctype_isSimple (c->contents.conj->b))
853 cstring name1 = cstring_copy (name);
858 ctbase_unparseDeclaration
859 (ctype_getCtbase (c->contents.conj->a), name1),
860 ctbase_unparseDeclaration
861 (ctype_getCtbase (c->contents.conj->b), name)));
865 cstring s1 = ctbase_unparseDeclaration (ctype_getCtbase (c->contents.conj->a),
866 cstring_copy (name));
868 (message ("%q | %q", s1,
869 ctbase_unparseDeclaration (ctype_getCtbase (c->contents.conj->b),
876 return (cstring_copy (ctype_unparse (c->contents.conj->a)));
883 static ctbase ctbase_undump (d_char *c) /*@requires maxRead(*c) >= 2 @*/
893 return (ctbase_undefined);
895 return (ctbase_createUnknown ());
897 return (ctbase_createBool ());
899 res = ctbase_createPrim (cprim_fromInt (reader_getInt (c)));
900 reader_checkChar (c, '|');
903 res = ctbase_createUser (typeId_fromInt (reader_getInt (c)));
904 reader_checkChar (c, '|');
907 res = ctbase_createAbstract (typeId_fromInt (reader_getInt (c)));
908 reader_checkChar (c, '|');
911 res = ctbase_createNumAbstract (typeId_fromInt (reader_getInt (c)));
912 reader_checkChar (c, '|');
915 res = ctbase_makePointer (ctype_undump (c));
916 reader_checkChar (c, '|');
919 res = ctbase_makeArray (ctype_undump (c));
920 reader_checkChar (c, '|');
924 ctype ct = ctype_undump (c);
927 reader_checkChar (c, '/');
928 size = size_fromInt (reader_getInt (c));
929 reader_checkChar (c, '|');
930 return (ctbase_makeFixedArray (ct, size));
935 char *lp = strchr (*c, '(');
937 llassertfatal (lp != NULL);
940 ct = ctype_undump (c);
943 return (ctbase_makeLiveFunction (ct, uentryList_undump (c)));
950 char *lc = strchr (*c, '{');
952 llassert (lc != NULL);
955 sname = mstring_copy (*c);
963 i = (unsigned) atoi (sname + 1);
968 fields = uentryList_undumpFields (c, g_currentloc);
970 ctb = ctbase_createStruct (cstring_fromCharsO (sname), fields);
976 char *lc = strchr (*c, '{');
978 llassert (lc != NULL);
981 sname = mstring_copy (*c);
982 llassert (sname != NULL);
990 i = (unsigned) atoi (sname + 1);
994 return (ctbase_createUnion (cstring_fromCharsO (sname),
995 uentryList_undumpFields (c, g_currentloc)));
1001 char *lc = strchr (*c, '{');
1003 llassert (lc != NULL);
1006 sname = mstring_copy (*c);
1013 i = (unsigned) atoi (sname + 1);
1017 ret = ctbase_createEnum (cstring_fromCharsO (sname),
1018 enumNameList_undump (c));
1026 isExplicit = bool_fromInt (reader_getInt (c));
1027 reader_checkChar (c, '.');
1028 c1 = ctype_undump (c);
1029 reader_checkChar (c, '/');
1030 c2 = ctype_undump (c);
1031 reader_checkChar (c, '|');
1033 return (ctbase_makeConj (c1, c2, isExplicit));
1038 llerror (FLG_SYNTAX,
1039 message ("Bad Library line (type): %s", cstring_fromChars (*c)));
1041 /*drl bee: pbr*/ while (**c != '\0')
1046 return ctbase_createUnknown ();
1050 /* first letter of c encodes type: */
1066 static /*@only@*/ cstring
1067 ctbase_dump (ctbase c)
1069 if (!ctbase_isDefined (c))
1071 return cstring_makeLiteral ("?");
1077 return cstring_makeLiteral ("u");
1079 return cstring_makeLiteral ("b");
1081 return (message ("p%d|", c->contents.prim));
1083 return (message ("s%d|", usymtab_convertTypeId (c->contents.tid)));
1085 return (message ("a%d|", usymtab_convertTypeId (c->contents.tid)));
1087 return (message ("n%d|", usymtab_convertTypeId (c->contents.tid)));
1089 return (message ("t%q|", ctype_dump (c->contents.base)));
1091 return (message ("y%q|", ctype_dump (c->contents.base)));
1093 return (message ("F%q/%d|",
1094 ctype_dump (c->contents.farray->base),
1095 (int) c->contents.farray->size));
1097 DPRINTF (("Dump function: %s", ctbase_unparse (c)));
1098 return (message ("f%q (%q)", ctype_dump (c->contents.fcn->rval),
1099 uentryList_dumpParams (c->contents.fcn->params)));
1101 return (message ("S%s{%q}", c->contents.su->name,
1102 uentryList_dumpFields (c->contents.su->fields)));
1104 return (message ("U%s{%q}", c->contents.su->name,
1105 uentryList_dumpFields (c->contents.su->fields)));
1110 if (cstring_isNonEmpty (c->contents.cenum->tag))
1112 s = message ("e%s{%q}",
1113 c->contents.cenum->tag,
1114 enumNameList_dump (c->contents.cenum->members));
1118 s = message ("e{%q}",
1119 enumNameList_dump (c->contents.cenum->members));
1124 return (message ("C%d.%q/%q|",
1125 bool_toInt (c->contents.conj->isExplicit),
1126 ctype_dump (c->contents.conj->a),
1127 ctype_dump (c->contents.conj->b)));
1129 /* should clean them up! */
1130 return (cstring_makeLiteral ("?"));
1132 llcontbug (message ("Cannot dump: %q", ctbase_unparse (c)));
1133 return (message ("u"));
1140 static /*@only@*/ ctbase
1141 ctbase_copy (/*@notnull@*/ ctbase c)
1146 return (ctbase_createUnknown ());
1148 return (ctbase_createBool ());
1150 return (ctbase_createEnum (cstring_copy (c->contents.cenum->tag),
1151 enumNameList_copy (c->contents.cenum->members)));
1153 return (ctbase_createPrim (c->contents.prim));
1155 return (ctbase_createUser (c->contents.tid));
1157 return (ctbase_createAbstract (c->contents.tid));
1159 return (ctbase_createNumAbstract (c->contents.tid));
1161 return (ctbase_expectFunction (c->contents.base));
1163 return (ctbase_makePointer (c->contents.base));
1165 return (ctbase_makeArray (c->contents.base));
1167 return (ctbase_makeLiveFunction (c->contents.fcn->rval,
1168 uentryList_copy (c->contents.fcn->params)));
1170 return (ctbase_createStruct (cstring_copy (c->contents.su->name),
1171 uentryList_copy (c->contents.su->fields)));
1173 return (ctbase_createUnion (cstring_copy (c->contents.su->name),
1174 uentryList_copy (c->contents.su->fields)));
1176 /*@i@*/ return (c); /* not a real copy for conj's */
1178 llbug (message ("ctbase_copy: %q", ctbase_unparse (c)));
1185 ctbase_elist (ctbase c)
1187 llassert (ctbase_isDefined (c));
1188 llassert (c->type == CT_ENUM);
1190 return (c->contents.cenum->members);
1194 ctbase_free (/*@only@*/ ctbase c)
1196 if (c == ctbase_bool || c == ctbase_unknown)
1198 /*@-mustfree@*/ return; /*@=mustfree@*/
1204 if (ctbase_isDefined (c))
1231 /* Cannot free params: uentryList_free (c->contents.fcn->params); */
1232 uentryList_freeShallow (c->contents.fcn->params);
1237 cstring_free (c->contents.su->name);
1238 uentryList_free (c->contents.su->fields);
1242 /* Don't bree conj's, */
1252 ** c should be * <unknown>
1255 static /*@only@*/ ctbase
1256 ctbase_expectFunction (ctype c)
1258 ctbase f = ctbase_new ();
1260 f->type = CT_EXPFCN;
1261 f->contents.base = c;
1267 ctbase_isExpectFunction (/*@notnull@*/ ctbase ct) /*@*/
1269 return (ct->type == CT_EXPFCN);
1273 ctbase_getExpectFunction (/*@notnull@*/ ctbase ct)
1275 llassert (ctbase_isExpectFunction (ct));
1276 return ct->contents.base;
1280 ctbase_genMatch (ctbase c1, ctbase c2, bool force, bool arg, bool def, bool deep)
1284 /* undefined types never match */
1286 if (ctbase_isUndefined (c1) || ctbase_isUndefined (c2))
1289 /* abstract types match user types of same name */
1291 c1 = ctbase_realType (c1);
1292 c2 = ctbase_realType (c2);
1294 DPRINTF (("Matching: %s / %s", ctbase_unparse (c1),
1295 ctbase_unparse (c2)));
1300 if (c1tid == CT_CONJ)
1302 return (ctbase_genMatch (ctype_getCtbase (c1->contents.conj->a), c2,
1303 force, arg, def, deep)
1304 || ctbase_genMatch (ctype_getCtbase (c1->contents.conj->b), c2,
1305 force, arg, def, deep));
1308 if (c2tid == CT_CONJ)
1310 return (ctbase_genMatch (c1, ctype_getCtbase (c2->contents.conj->a),
1311 force, arg, def, deep)
1312 || ctbase_genMatch (c1, ctype_getCtbase (c2->contents.conj->b),
1313 force, arg, def, deep));
1317 ** if the types don't match, there are some special cases...
1322 /* unknowns match anything */
1324 if (c1tid == CT_UNKNOWN || c2tid == CT_UNKNOWN)
1329 if (c1tid == CT_FIXEDARRAY
1330 && (c2tid == CT_ARRAY || (!def && c2tid == CT_PTR)))
1332 if (ctype_isVoid (c2->contents.base))
1334 return (context_getFlag (FLG_ABSTVOIDP) ||
1335 (!(ctype_isRealAbstract (c1->contents.farray->base)) &&
1336 !(ctype_isRealAbstract (c2->contents.base))));
1339 return (ctbase_genMatch (ctype_getCtbase (c1->contents.farray->base),
1340 ctype_getCtbase (c2->contents.base),
1341 force, arg, def, deep));
1345 if (c2tid == CT_FIXEDARRAY
1346 && (c1tid == CT_ARRAY || (!def && c1tid == CT_PTR)))
1348 if (ctype_isVoid (c1->contents.base))
1350 return (context_getFlag (FLG_ABSTVOIDP) ||
1351 (!(ctype_isRealAbstract (c2->contents.farray->base)) &&
1352 !(ctype_isRealAbstract (c1->contents.base))));
1355 return (ctbase_genMatch (ctype_getCtbase (c1->contents.base),
1356 ctype_getCtbase (c2->contents.farray->base),
1357 force, arg, def, deep));
1360 /* evs 2000-07-25: Bool's may match user/abstract types */
1362 if ((c1tid == CT_BOOL
1363 && (c2tid == CT_PRIM && cprim_isInt (c2->contents.prim))) ||
1365 && (c1tid == CT_PRIM && cprim_isInt (c1->contents.prim))))
1367 return (context_msgBoolInt ());
1370 if ((c1tid == CT_BOOL && (ctuid_isAnyUserType (c2tid)))) {
1371 ctype t2c = c2->contents.base;
1372 return (ctype_isBool (t2c));
1375 if ((c2tid == CT_BOOL && (ctuid_isAnyUserType (c1tid)))) {
1376 ctype t1c = c1->contents.base;
1378 return (ctype_isBool (t1c));
1381 if ((c1tid == CT_ENUM
1382 && (c2tid == CT_PRIM && cprim_isInt (c2->contents.prim))) ||
1384 && (c1tid == CT_PRIM && cprim_isInt (c1->contents.prim))))
1386 return (context_msgEnumInt ());
1390 ** arrays and pointers...yuk!
1392 ** Considered equivalent except in definitions.
1393 ** (e.g., function parameters are equivalent)
1399 if (ctuid_isAP (c1tid) && ctuid_isAP (c2tid))
1406 ** Function pointers can be removed.
1408 ** [function ..] is equivalent to [function ..] *
1411 if (c1tid == CT_PTR && c2tid == CT_FCN)
1413 if (ctype_isFunction (ctype_realType (c1->contents.base)))
1415 c1 = ctbase_realType (ctype_getCtbaseSafe (c1->contents.base));
1420 if (c2tid == CT_PTR && c1tid == CT_FCN)
1422 if (ctype_isFunction (ctype_realType (c2->contents.base)))
1424 c2 = ctbase_realType (ctype_getCtbaseSafe (c2->contents.base));
1430 ** we allow forward declarations to structures like,
1432 ** typedef struct _t *t;
1435 ** struct _t * to match t
1438 if (context_getFlag (FLG_FORWARDDECL))
1440 if (ctuid_isAnyUserType (c1tid))
1442 if (ctuid_isAP (c2tid))
1444 ctype ts = c2->contents.base;
1446 if (ctype_isUA (ts))
1448 typeId ttid = ctype_typeId (ts);
1449 typeId ctid = c1->contents.tid ;
1451 if (usymtab_matchForwardStruct (ctid, ttid))
1459 if (ctuid_isAnyUserType (c2tid))
1461 if (ctuid_isAP (c1tid))
1463 ctype ts = c1->contents.base;
1465 if (ctype_isUA (ts))
1467 typeId ttid = ctype_typeId (ts);
1468 typeId ctid = c2->contents.tid ;
1470 if (usymtab_matchForwardStruct (ctid, ttid))
1489 return (cprim_closeEnoughDeep (c1->contents.prim, c2->contents.prim));
1491 return (cprim_closeEnough (c1->contents.prim, c2->contents.prim));
1498 return (typeId_equal (c1->contents.tid, c2->contents.tid));
1500 return (cstring_equal (c1->contents.cenum->tag, c2->contents.cenum->tag));
1502 if (ctype_isVoid (c1->contents.base)
1503 || (ctype_isVoid (c2->contents.base)))
1505 if (ctype_isFunction (ctype_realType (c1->contents.base))
1506 || ctype_isFunction (ctype_realType (c2->contents.base)))
1508 return (!context_getFlag (FLG_CASTFCNPTR));
1512 return (context_getFlag (FLG_ABSTVOIDP) ||
1513 (!(ctype_isRealAbstract (c1->contents.base)) &&
1514 !(ctype_isRealAbstract (c2->contents.base))));
1519 /* Only allow one implicit function pointer. */
1521 if (!bool_equal (ctype_isRealPointer (c1->contents.base),
1522 ctype_isRealPointer (c2->contents.base))
1523 && (ctype_isRealFunction (c1->contents.base)
1524 || ctype_isRealFunction (c2->contents.base)))
1529 return (ctype_genMatch (c1->contents.base,
1530 c2->contents.base, force, arg, def, TRUE));
1533 if (ctype_isVoid (c1->contents.farray->base)
1534 || ctype_isVoid (c2->contents.farray->base))
1536 return (ctype_genMatch (c1->contents.farray->base,
1537 c2->contents.farray->base,
1538 force, arg, def, deep));
1540 if (ctype_isVoid (c1->contents.base) || ctype_isVoid (c2->contents.base))
1542 return (ctype_genMatch (c1->contents.base, c2->contents.base, force, arg, def, TRUE));
1544 return (ctype_genMatch (c1->contents.fcn->rval,
1545 c2->contents.fcn->rval,
1546 force, arg, def, TRUE)
1547 && uentryList_matchParams (c1->contents.fcn->params,
1548 c2->contents.fcn->params,
1552 DPRINTF (("Struct: %s / %s",
1553 c1->contents.su->name,
1554 c2->contents.su->name));
1556 if (isFakeTag (c1->contents.su->name)
1557 && isFakeTag (c2->contents.su->name))
1559 /* Both fake tags, check structure */
1560 if (cstring_equal (c1->contents.su->name, c2->contents.su->name))
1566 return uentryList_matchFields (c1->contents.su->fields,
1567 c2->contents.su->fields);
1572 if (!cstring_isEmpty (c1->contents.su->name))
1574 return (cstring_equal (c1->contents.su->name, c2->contents.su->name));
1578 if (!cstring_isEmpty (c2->contents.su->name))
1583 llcontbuglit ("ctbase_genMatch: match fields");
1588 llcontbug (message ("ctbase_genMatch: unknown type: %d\n", (int)c1tid));
1594 ** like ctbase_match, except for conjuncts:
1595 ** modifies conjuncts to match only
1599 ctbase_forceMatch (ctbase c1, ctbase c2) /*@modifies c1, c2@*/
1601 return (ctbase_genMatch (c1, c2, TRUE, FALSE, FALSE, FALSE));
1605 ctbase_match (ctbase c1, ctbase c2) /*@modifies nothing@*/
1607 return (ctbase_genMatch (c1, c2, FALSE, FALSE, FALSE, FALSE));
1611 ctbase_matchDef (ctbase c1, ctbase c2) /*@modifies nothing@*/
1613 return (ctbase_genMatch (c1, c2, FALSE, FALSE, TRUE, FALSE));
1617 ctbase_matchArg (ctbase c1, ctbase c2)
1619 return (ctbase_genMatch (c1, c2, FALSE, TRUE, FALSE, FALSE));
1622 static /*@out@*/ /*@only@*/ /*@notnull@*/ ctbase
1625 ctbase c = (ctbase) dmalloc (sizeof (*c));
1629 if (nctbases % 100 == 0 && nctbases > lastnc)
1631 llmsg (message ("ctbases: %d", nctbases));
1638 static /*@only@*/ ctbase
1639 ctbase_createPrim (cprim p)
1641 ctbase c = ctbase_new ();
1644 c->contents.prim = p;
1649 static /*@observer@*/ ctbase
1650 ctbase_getBool (void)
1652 /*@i@*/ return ctbase_createBool ();
1656 ctbase_createBool ()
1658 if (!ctbase_isDefined (ctbase_bool))
1660 ctbase_bool = ctbase_new ();
1661 ctbase_bool->type = CT_BOOL;
1662 ctbase_bool->contents.prim = CTX_BOOL;
1665 /*@-retalias@*/ /*@-globstate@*/
1667 /*@=retalias@*/ /*@=globstate@*/
1670 static /*@only@*/ ctbase
1671 ctbase_createUser (typeId u)
1673 ctbase c = ctbase_new ();
1676 c->contents.tid = u;
1678 llassert (typeId_isValid (u));
1683 static /*@only@*/ ctbase
1684 ctbase_createEnum (/*@keep@*/ cstring etag, /*@keep@*/ enumNameList emembers)
1686 ctbase c = ctbase_new ();
1690 if (cstring_isUndefined (etag))
1692 llcontbuglit ("Undefined enum tag!");
1696 c->contents.cenum = (tenum) dmalloc (sizeof (*c->contents.cenum));
1697 c->contents.cenum->tag = etag;
1698 c->contents.cenum->members = emembers;
1703 static /*@observer@*/ cstring
1704 ctbase_enumTag (/*@notnull@*/ ctbase ct)
1706 return (ct->contents.cenum->tag);
1709 static /*@only@*/ ctbase
1710 ctbase_createAbstract (typeId u)
1712 ctbase c = ctbase_new ();
1715 c->contents.tid = u;
1717 /* also check its abstract? */
1719 llassert (typeId_isValid (c->contents.tid));
1724 static /*@only@*/ ctbase
1725 ctbase_createNumAbstract (typeId u)
1727 ctbase c = ctbase_new ();
1729 c->type = CT_NUMABST;
1730 c->contents.tid = u;
1732 /* also check its abstract? */
1734 llassert (typeId_isValid (c->contents.tid));
1738 static /*@only@*/ ctbase
1739 ctbase_createUnknown (void)
1741 if (!ctbase_isDefined (ctbase_unknown))
1743 ctbase_unknown = ctbase_new ();
1744 ctbase_unknown->type = CT_UNKNOWN;
1745 ctbase_unknown->contents.prim = CTX_UNKNOWN;
1748 /*@-retalias@*/ /*@-globstate@*/
1749 return ctbase_unknown;
1750 /*@=retalias@*/ /*@=globstate@*/
1754 ** requires: result is not assigned to b
1755 ** (should copy, but no way to reclaim storage)
1758 static /*@only@*/ ctbase
1759 ctbase_makePointer (ctype b)
1761 ctbase c = ctbase_new ();
1764 c->contents.base = b;
1769 static /*@only@*/ ctbase
1770 ctbase_makeArray (ctype b)
1772 ctbase c = ctbase_new ();
1775 c->contents.base = b;
1780 static /*@notnull@*/ /*@only@*/ ctbase
1781 ctbase_makeFixedArray (ctype b, size_t size)
1783 ctbase c = ctbase_new ();
1785 c->type = CT_FIXEDARRAY;
1787 c->contents.farray = (tfixed) dmalloc (sizeof (*c->contents.farray));
1788 c->contents.farray->base = b;
1789 c->contents.farray->size = size;
1795 ctbase_makeFunction (ctype b, /*@only@*/ uentryList p)
1797 ctbase c = ctbase_new ();
1801 c->contents.fcn = (cfcn) dmalloc (sizeof (*c->contents.fcn));
1803 if (ctype_isFunction (b)) /* was: && ctype_isPointer (b)) */
1808 if (ctype_isPointer (b))
1810 ctb = ctype_getCtbase (ctype_baseArrayPtr (b));
1814 ctb = ctype_getCtbase (b);
1817 llassert (ctbase_isDefined (ctb));
1818 llassert (ctb->type == CT_FCN);
1820 rval = ctype_makeFunction (ctb->contents.fcn->rval, p);
1822 c->contents.fcn->rval = rval;
1823 c->contents.fcn->params = uentryList_copy (ctb->contents.fcn->params); /* no copy before */
1827 c->contents.fcn->rval = b;
1828 c->contents.fcn->params = uentryList_copy (p); /* no copy before */
1829 /*@-branchstate@*/ /* p is really released on this branch */
1833 ct = cttable_addComplex (c);
1834 return (ct); /* was: ctype_makePointer (ct)); */
1838 ctbase_makeNFFunction (ctype b, /*@only@*/ uentryList p)
1840 ctbase c = ctbase_new ();
1844 c->contents.fcn = (cfcn) dmalloc (sizeof (*c->contents.fcn));
1846 if (ctype_isFunction (b)) /* was && ctype_isPointer (b)) */
1851 if (ctype_isPointer (b))
1853 ctb = ctype_getCtbase (ctype_baseArrayPtr (b));
1857 ctb = ctype_getCtbase (b);
1860 llassert (ctbase_isDefined (ctb));
1861 llassert (ctb->type == CT_FCN);
1863 rval = ctype_makeNFParamsFunction (ctb->contents.fcn->rval, p);
1865 c->contents.fcn->rval = rval;
1866 c->contents.fcn->params = uentryList_copy (ctb->contents.fcn->params);
1870 c->contents.fcn->rval = b;
1871 c->contents.fcn->params = uentryList_copy (p);
1876 ct = cttable_addComplex (c);
1877 return (ct); /* was: ctype_makePointer (ct)); */
1880 static /*@only@*/ ctbase
1881 ctbase_makeLiveFunction (ctype b, /*@only@*/ uentryList p)
1883 ctbase c = ctbase_new ();
1887 c->contents.fcn = (cfcn) dmalloc (sizeof (*c->contents.fcn));
1888 c->contents.fcn->rval = b;
1889 c->contents.fcn->params = p;
1891 /*@-mustfree@*/ return (c); /*@=mustfree@*/
1894 static /*@observer@*/ /*@notnull@*/ ctbase
1895 ctbase_realFunction (/*@dependent@*/ /*@notnull@*/ ctbase c)
1899 if (c->type == CT_FCN)
1904 llassert (ctbase_isFunction (c));
1906 res = ctype_getCtbase (c->contents.base);
1908 llassert (ctbase_isDefined (res));
1914 ctbase_isFunction (ctbase c)
1916 llassert (c != ctbase_undefined);
1918 if (c->type == CT_FCN)
1924 if (c->type == CT_PTR)
1926 ctbase fcn = ctype_getCtbase (ctbase_baseArrayPtr (c));
1928 return (ctbase_isDefined (fcn) && fcn->type == CT_FCN);
1935 /* doesn't copy c1 and c2 */
1937 static /*@only@*/ ctbase
1938 ctbase_makeConj (ctype c1, ctype c2, bool isExplicit)
1940 ctbase c = ctbase_new ();
1944 c->contents.conj = (tconj) dmalloc (sizeof (*c->contents.conj));
1945 c->contents.conj->a = c1;
1946 c->contents.conj->b = c2;
1947 c->contents.conj->isExplicit = isExplicit;
1952 static bool ctbase_isAnytype (/*@notnull@*/ ctbase b)
1955 ** A unknown|dne conj is a special representation for an anytype.
1958 if (b->type == CT_CONJ)
1961 return (b->contents.conj->a == ctype_unknown
1962 && b->contents.conj->b == ctype_dne);
1963 /*@noaccess ctype@*/
1970 ctbase_getConjA (/*@notnull@*/ ctbase c)
1972 llassert (c->type == CT_CONJ);
1973 return (c->contents.conj->a);
1977 ctbase_getConjB (/*@notnull@*/ ctbase c)
1979 llassert (c->type == CT_CONJ);
1980 return (c->contents.conj->b);
1984 ctbase_isExplicitConj (/*@notnull@*/ ctbase c)
1986 llassert (c->type == CT_CONJ);
1987 return (c->contents.conj->isExplicit);
1990 static /*@only@*/ ctbase
1991 ctbase_createStruct (/*@only@*/ cstring n, /*@only@*/ uentryList f)
1993 ctbase c = ctbase_new ();
1995 c->type = CT_STRUCT;
1997 c->contents.su = (tsu) dmalloc (sizeof (*c->contents.su));
1998 c->contents.su->name = n;
1999 c->contents.su->fields = f;
2004 static /*@observer@*/ uentryList
2005 ctbase_getuentryList (/*@notnull@*/ ctbase c)
2007 c = ctbase_realType (c);
2009 if (!(c->type == CT_STRUCT || c->type == CT_UNION))
2010 llfatalbug (message ("ctbase_getuentryList: bad invocation: %q", ctbase_unparse (c)));
2012 return (c->contents.su->fields);
2016 ctbase_createUnion (/*@keep@*/ cstring n, /*@only@*/ uentryList f)
2018 ctbase c = ctbase_new ();
2022 c->contents.su = (tsu) dmalloc (sizeof (*c->contents.su));
2023 c->contents.su->name = n;
2024 c->contents.su->fields = f;
2030 ctbase_baseArrayPtr (/*@notnull@*/ ctbase c)
2033 c = ctbase_realType (c);
2036 if (ct == CT_FIXEDARRAY)
2038 return c->contents.farray->base;
2042 llassert (ctuid_isAP (ct));
2044 return c->contents.base;
2049 ctbase_baseFunction (/*@notnull@*/ ctbase c)
2052 c = ctbase_realFunction (c);
2054 if (c->type != CT_FCN)
2056 llfatalbug (message ("ctbase_baseFunction: bad call: %q", ctbase_unparse (c)));
2059 return (c->contents.fcn->rval);
2063 ctbase_argsFunction (/*@notnull@*/ ctbase c)
2066 c = ctbase_realFunction (c);
2068 if (c->type != CT_FCN)
2070 llfatalbug (message ("ctbase_argsFunction: bad call: %q",
2071 ctbase_unparse (c)));
2073 return (c->contents.fcn->params);
2077 ctbase_baseisExpFcn (ctype c)
2080 c = ctype_removePointers (c);
2082 cb = ctype_getCtbase (c);
2083 llassert (ctbase_isDefined (cb));
2085 if (cb->type == CT_FCN)
2087 c = ctype_removePointers (ctype_getReturnType (c));
2089 cb = ctype_getCtbase (c);
2090 llassert (ctbase_isDefined (cb));
2092 return (cb->type == CT_EXPFCN);
2098 ** ctbase_newBase behaves specially when p is a CONJ:
2100 ** c -> conj (newBase (c, p.a), p.b)
2104 ctbase_newBase (ctype c, ctype p)
2108 DPRINTF (("New base: %s / %s", ctype_unparse (c), ctype_unparse (p)));
2110 if (ctype_isUndefined (c) || ctype_isUnknown (c))
2115 cb = ctype_getCtbase (c);
2117 if (ctype_isConj (p))
2119 ctbase pb = ctype_getCtbase (p);
2121 llassert (ctbase_isDefined (pb));
2123 if (pb->contents.conj->isExplicit)
2125 return (ctype_makeExplicitConj (ctype_newBase (c, pb->contents.conj->a),
2126 pb->contents.conj->b));
2131 return (ctype_makeConj (ctype_newBase (c, pb->contents.conj->a),
2132 pb->contents.conj->b));
2137 if (ctbase_baseisExpFcn (c))
2139 return (ctbase_newBaseExpFcn (c, p));
2142 llassert (ctbase_isDefined (cb));
2162 cbn = ctbase_newBase (cb->contents.base, p);
2163 ret = ctype_makePointer (cbn);
2168 return (ctype_makeFixedArray (ctbase_newBase (cb->contents.farray->base, p),
2169 cb->contents.farray->size));
2171 return (ctype_makeArray (ctbase_newBase (cb->contents.base, p)));
2173 return (ctype_makeRawFunction (ctbase_newBase (cb->contents.fcn->rval, p),
2174 cb->contents.fcn->params));
2176 return (ctype_makeConjAux (ctbase_newBase (cb->contents.conj->a, p),
2177 ctbase_newBase (cb->contents.conj->b, p),
2178 cb->contents.conj->isExplicit));
2180 llcontbug (message ("ctbase_newBase: bad ctbase: %q", ctbase_unparse (cb)));
2187 ctbase_newBaseExpFcn (ctype c, ctype p)
2189 ctbase cb = ctype_getCtbase (c);
2192 ctype fp = ctype_unknown;
2193 uentryList ctargs = ctype_argsFunction (c);
2196 ** okay, this is really ugly...
2198 ** pointers inside <expf> mean pointers to the function;
2199 ** pointers outside <expf> are pointers to the return value;
2200 ** because its a function there is one superfluous pointer.
2204 ** bf is a ctype, used to derived structure of cb
2207 if (!ctbase_isFunction (cb))
2208 llbuglit ("ctbase_newBaseExpFcn: expFcn -> not a function");
2210 tmpct = ctype_getBaseType (ctype_getReturnType (c));
2213 ** pointers before expfcn -> p are pointers to function, not result
2217 tcb = ctype_getCtbase (tmpct);
2219 llassert (ctbase_isDefined (tcb));
2220 tmpct = tcb->contents.base;
2223 ** record pointers to base in fp
2226 while (!ctype_isUnknown (tmpct))
2228 if (ctype_isExpFcn (tmpct)) {
2229 ctbase ttcb = ctype_getCtbase (tmpct);
2232 ** evs 2000-05-16: This is necessary to deal with function pointers in parens.
2233 ** The whole function pointer parsing is a major kludge, but it seems to work,
2234 ** and I'm only embarrassed by it when I haven't look at the C spec recently...
2237 llassert (ctbase_isDefined (ttcb));
2238 tmpct = ttcb->contents.base;
2239 llassert (!ctype_isUnknown (tmpct));
2242 switch (ctype_getCtKind (tmpct))
2245 fp = ctype_makePointer (fp);
2246 /*@switchbreak@*/ break;
2248 fp = ctype_makeArray (fp);
2249 /*@switchbreak@*/ break;
2252 ctbase fbase = ctype_getCtbase (tmpct);
2254 if (ctbase_isFunction (fbase))
2256 fp = ctype_makeFunction (fp, uentryList_copy (ctargs));
2257 ctargs = ctbase_argsFunction (fbase);
2263 ("ctbase_newBaseExpFcn: fixing expfunction: bad complex type: %s [base: %q]",
2264 ctype_unparse (tmpct), ctbase_unparse (fbase)));
2271 (message ("ctbase_newBaseExpFcn: fixing expfunction: bad type: %s",
2272 ctype_unparse (tmpct)));
2276 tmpct = ctype_baseArrayPtr (tmpct);
2280 tmpct = ctype_getReturnType (c);
2283 ** pointers to expf are pointers to return value
2286 while (!ctype_isExpFcn (tmpct))
2288 switch (ctype_getCtKind (tmpct))
2291 p = ctype_makePointer (p);
2292 /*@switchbreak@*/ break;
2294 p = ctype_makeArray (p);
2295 /*@switchbreak@*/ break;
2298 ctbase fbase = ctype_getCtbase (tmpct);
2300 if (ctbase_isFunction (fbase))
2302 p = ctype_makeFunction (p, uentryList_copy (ctbase_argsFunction (fbase)));
2308 ("ctbase_newBaseExpFcn: fixing expfunction: bad complex type: %s",
2309 ctype_unparse (tmpct)));
2317 (message ("ctbase_newBaseExpFcn: fixing expfunction2: bad type: %t",
2322 tmpct = ctype_baseArrayPtr (tmpct);
2328 ** pointers to fp are pointers to function type
2331 ret = ctype_makeRawFunction (p, uentryList_copy (ctargs));
2333 while (ctype_getCtKind (fp) > CTK_PLAIN)
2335 switch (ctype_getCtKind (fp))
2338 ret = ctype_makePointer (ret);
2339 /*@switchbreak@*/ break;
2341 ret = ctype_makeArray (ret);
2342 /*@switchbreak@*/ break;
2345 ctbase fbase = ctype_getCtbase (fp);
2347 if (ctbase_isFunction (fbase))
2350 ctype_makeFunction (ret,
2351 uentryList_copy (ctbase_argsFunction (fbase)));
2362 llcontbug (message ("post-fixing expfunction: bad type: %t", fp));
2366 fp = ctype_baseArrayPtr (fp);
2374 ** returns lowest level base of c: plain type
2377 static /*@notnull@*/ /*@only@*/ ctbase
2378 ctbase_getBaseType (/*@notnull@*/ ctbase c)
2393 return (ctbase_copy (c));
2397 return (ctbase_getBaseType (ctype_getCtbaseSafe (c->contents.base)));
2400 return (ctbase_getBaseType (ctype_getCtbaseSafe (c->contents.farray->base)));
2401 case CT_CONJ: /* base type of A conj branch? */
2402 return (ctbase_getBaseType (ctype_getCtbaseSafe (c->contents.conj->a)));
2404 return (ctbase_copy (c));
2407 llfatalbug (message ("ctbase_getBaseType: bad ctbase: %q", ctbase_unparse (c)));
2414 ctbase_compare (ctbase c1, ctbase c2, bool strict)
2418 if (ctbase_isUndefined (c1) || ctbase_isUndefined (c2))
2420 llcontbuglit ("ctbase_compare: undefined ctbase");
2437 return (int_compare (c1->contents.prim, c2->contents.prim));
2441 return (typeId_compare (c1->contents.tid, c2->contents.tid));
2444 case CT_ENUM: /* for now, keep like abstract */
2447 return (typeId_compare (c1->contents.tid, c2->contents.tid));
2449 return (ctype_compare (c1->contents.base, c2->contents.base));
2451 INTCOMPARERETURN (c1->contents.farray->size, c2->contents.farray->size);
2453 return (ctype_compare (c1->contents.farray->base,
2454 c2->contents.farray->base));
2456 return (ctype_compare (c1->contents.base, c2->contents.base));
2459 COMPARERETURN (ctype_compare (c1->contents.fcn->rval, c2->contents.fcn->rval));
2463 return (uentryList_compareStrict (c1->contents.fcn->params,
2464 c2->contents.fcn->params));
2468 return (uentryList_compareParams (c1->contents.fcn->params,
2469 c2->contents.fcn->params));
2473 return (ctype_compare (c1->contents.base, c2->contents.base));
2476 /* evs 2000-07-28: this block was missing! */
2478 int ncmp = cstring_compare (c1->contents.su->name,
2479 c2->contents.su->name);
2482 if (isFakeTag (c1->contents.su->name)
2483 && isFakeTag (c2->contents.su->name)) {
2484 ; /* If they are both fake struct tags, don't require match. */
2491 DPRINTF (("Comparing fields: %s / %s",
2492 ctbase_unparse (c1),
2493 ctbase_unparse (c2)));
2495 return (uentryList_compareFields (c1->contents.su->fields,
2496 c2->contents.su->fields));
2499 COMPARERETURN (ctype_compare (c1->contents.conj->a,
2500 c2->contents.conj->a));
2501 COMPARERETURN (ctype_compare (c1->contents.conj->b,
2502 c2->contents.conj->b));
2503 return (bool_compare (c1->contents.conj->isExplicit,
2504 c2->contents.conj->isExplicit));
2511 ctbase_compareStrict (/*@notnull@*/ ctbase c1, /*@notnull@*/ ctbase c2)
2513 return (ctbase_compare (c1, c2, TRUE));
2516 static bool ctbase_equivStrict (/*@notnull@*/ ctbase c1, /*@notnull@*/ ctbase c2)
2518 return (ctbase_compareStrict (c1,c2) == 0);
2521 static bool ctbase_equiv (/*@notnull@*/ ctbase c1, /*@notnull@*/ ctbase c2)
2523 return (ctbase_compare (c1, c2, FALSE) == 0);
2527 ctbase_isKind (/*@notnull@*/ ctbase c, ctuid kind)
2535 return (ctbase_isKind (ctype_getCtbaseSafe (c->contents.conj->a), kind) ||
2536 ctbase_isKind (ctype_getCtbaseSafe (c->contents.conj->b), kind));
2542 ctbase_isKind2 (/*@notnull@*/ ctbase c, ctuid kind1, ctuid kind2)
2546 if (ck == kind1 || ck == kind2)
2550 return (ctbase_isKind2 (ctype_getCtbaseSafe (c->contents.conj->a), kind1, kind2) ||
2551 ctbase_isKind2 (ctype_getCtbaseSafe (c->contents.conj->b), kind1, kind2));
2557 ctbase_isAbstract (/*@notnull@*/ ctbase c)
2559 return (c->type == CT_ABST || c->type == CT_NUMABST);
2563 ctbase_isNumAbstract (/*@notnull@*/ ctbase c)
2565 return (c->type == CT_NUMABST);
2568 static bool ctbase_isUA (ctbase c)
2570 return (ctbase_isDefined (c) && (ctuid_isAnyUserType (c->type)));
2574 ctbase_almostEqual (ctbase c1, ctbase c2)
2578 /* undefined types never match */
2580 if (ctbase_isUndefined (c1) || ctbase_isUndefined (c2))
2586 if (c1tid == CT_FIXEDARRAY && c2tid == CT_ARRAY)
2588 return (ctbase_almostEqual (ctype_getCtbase (c1->contents.farray->base),
2589 ctype_getCtbase (c2->contents.base)));
2592 if (c2tid == CT_FIXEDARRAY && c1tid == CT_ARRAY)
2594 return (ctbase_almostEqual (ctype_getCtbase (c1->contents.base),
2595 ctype_getCtbase (c2->contents.farray->base)));
2606 return (cprim_equal (c1->contents.prim, c2->contents.prim));
2612 return (typeId_equal (c1->contents.tid, c2->contents.tid));
2614 return (cstring_equal (c1->contents.cenum->tag, c2->contents.cenum->tag));
2616 return (ctype_almostEqual (c1->contents.base, c2->contents.base));
2618 return (ctype_almostEqual (c1->contents.farray->base,
2619 c2->contents.farray->base));
2621 return (ctype_almostEqual (c1->contents.base, c2->contents.base));
2623 return (ctype_almostEqual (c1->contents.fcn->rval, c2->contents.fcn->rval)
2624 && uentryList_matchParams (c1->contents.fcn->params,
2625 c2->contents.fcn->params, FALSE, TRUE));
2628 if (!cstring_isEmpty (c1->contents.su->name))
2630 return (cstring_equal (c1->contents.su->name, c2->contents.su->name));
2634 if (!cstring_isEmpty (c2->contents.su->name))
2639 llcontbuglit ("ctbase_almostEqual: match fields");
2643 llcontbug (message ("ctbase_almostEqual: unknown type: %d\n", (int)c1tid));
2648 /*drl added July 02, 001
2649 called by ctype_getArraySize
2652 size_t ctbase_getArraySize (ctbase ctb)
2654 /*drl 1/25/2002 fixed discovered by Jim Francis */
2657 llassert (ctbase_isDefined (ctb) );
2658 r = ctbase_realType (ctb);
2659 llassert (ctbase_isFixedArray(r) );
2661 return (r->contents.farray->size);
2664 bool ctbase_isBigger (ctbase ct1, ctbase ct2)
2666 if (ct1 != NULL && ct2 != NULL
2667 && (ct1->type == CT_PRIM && ct2->type == CT_PRIM))
2669 /* Only compare sizes for primitives */
2670 cprim cp1 = ct1->contents.prim;
2671 cprim cp2 = ct2->contents.prim;
2672 int nbits1 = cprim_getExpectedBits (cp1);
2673 int nbits2 = cprim_getExpectedBits (cp2);
2675 if (nbits1 > nbits2) {
2687 int ctbase_getSize (ctbase ct)
2700 cprim cp = ct->contents.prim;
2701 int nbits = cprim_getExpectedBits (cp);
2713 /* Malloc returns void *, but they are bytes. Normal void * is pointer size. */
2714 if (ctype_isVoid (ct->contents.base))
2720 return ctype_getSize (ct->contents.base);