Moved OS dependent constants from constants.h to osd.h
[splint-patched.git] / src / clabstract.c
blob9a3d36842f29a4cd3fed946cb1940e52f013fe59
1 /*
2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 University of Virginia,
4 ** Massachusetts Institute of Technology
5 **
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.
10 **
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.
15 **
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: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
25 ** clabstract.c
27 ** ASTs for C grammar
31 # include "splintMacros.nf"
32 # include "basic.h"
33 # include "usymtab_interface.h"
35 # include "structNames.h"
36 # include "nameChecks.h"
38 # include "cgrammar.h"
41 ** Lots of variables are needed because of interactions with the
42 ** parser. This is easier than restructuring the grammar so the
43 ** right values are available in the right place.
46 /*drl*/
47 static /*@only@*/ constraintList implicitFcnConstraints = NULL;
49 static void clabstract_prepareFunction (uentry p_e) /*@modifies p_e@*/ ;
50 static bool fcnNoGlobals = FALSE;
51 static void processVariable (/*@temp@*/ idDecl p_t) /*@modifies internalState@*/ ;
53 static bool s_processingVars = FALSE;
54 static bool s_processingParams = FALSE;
55 static bool s_processingGlobals = FALSE;
56 static bool s_processingTypedef = FALSE;
57 static bool s_processingIterVars = FALSE;
58 static /*@only@*/ qtype processingType = qtype_undefined;
59 static uentry currentIter = uentry_undefined;
60 static /*@dependent@*/ uentryList saveParamList; /* for old style functions */
61 static /*@owned@*/ uentry saveFunction = uentry_undefined;
62 static int saveIterParamNo;
63 static idDecl fixStructDecl (/*@returned@*/ idDecl p_d);
64 static void checkTypeDecl (uentry p_e, ctype p_rep);
65 static /*@dependent@*/ fileloc saveStoreLoc = fileloc_undefined;
66 static storageClassCode storageClass = SCNONE;
67 static void declareEnumList (/*@temp@*/ enumNameList p_el, ctype p_c, fileloc p_loc);
68 static void resetGlobals (void);
69 static /*@null@*/ qual specialFunctionCode;
70 static bool argsUsed = FALSE;
72 extern void clabstract_initMod ()
74 specialFunctionCode = qual_createUnknown ();
75 DPRINTF (("Initialized: %s", qual_unparse (specialFunctionCode)));
78 static bool hasSpecialCode (void)
80 return (!qual_isUnknown (specialFunctionCode));
83 extern void setArgsUsed (void)
85 if (argsUsed)
87 voptgenerror
88 (FLG_SYNTAX,
89 cstring_makeLiteral ("Multiple ARGSUSED comments for one function"),
90 g_currentloc);
93 argsUsed = TRUE;
96 static void reflectArgsUsed (uentry ue)
98 if (argsUsed)
100 if (uentry_isFunction (ue))
102 uentryList params = uentry_getParams (ue);
104 uentryList_elements (params, el)
106 uentry_setUsed (el, fileloc_undefined);
107 } end_uentryList_elements ;
110 argsUsed = FALSE;
114 extern void setSpecialFunction (qual qu)
116 if (!qual_isUnknown (specialFunctionCode))
118 voptgenerror (FLG_SYNTAX,
119 message ("Multiple special function codes: %s, %s "
120 "(first code is ignored)",
121 qual_unparse (specialFunctionCode),
122 qual_unparse (qu)),
123 g_currentloc);
126 specialFunctionCode = qu;
129 static void reflectSpecialCode (uentry ue)
131 if (qual_isUnknown (specialFunctionCode)) {
133 } else if (qual_isPrintfLike (specialFunctionCode)) {
134 uentry_setPrintfLike (ue);
135 } else if (qual_isScanfLike (specialFunctionCode)) {
136 uentry_setScanfLike (ue);
137 } else if (qual_isMessageLike (specialFunctionCode)) {
138 uentry_setMessageLike (ue);
139 } else {
140 BADBRANCH;
143 specialFunctionCode = qual_createUnknown ();
146 static void resetStorageClass (void)
148 qtype_free (processingType);
149 processingType = qtype_undefined;
150 storageClass = SCNONE;
153 static void reflectStorageClass (uentry u)
155 if (storageClass == SCSTATIC)
157 uentry_setStatic (u);
159 else if (storageClass == SCEXTERN)
161 uentry_setExtern (u);
163 else
165 ; /* no storage class */
170 void storeLoc ()
172 saveStoreLoc = g_currentloc;
175 void setFunctionNoGlobals (void)
177 fcnNoGlobals = TRUE;
180 static void reflectGlobalQualifiers (sRef sr, qualList quals)
182 DPRINTF (("Reflect global qualifiers: %s / %s",
183 sRef_unparseFull (sr), qualList_unparse (quals)));
185 qualList_elements (quals, qel)
187 if (qual_isGlobalQual (qel)) /* undef, killed */
189 sstate oldstate = sRef_getDefState (sr);
190 sstate defstate = sstate_fromQual (qel);
192 if ((oldstate == SS_UNDEFGLOB && defstate == SS_KILLED)
193 || (oldstate == SS_KILLED && defstate == SS_UNDEFGLOB))
195 defstate = SS_UNDEFKILLED;
197 else
199 ; /* any errors? */
202 sRef_setDefState (sr, defstate, fileloc_undefined);
203 DPRINTF (("State: %s", sRef_unparseFull (sr)));
205 else if (qual_isAllocQual (qel)) /* out, partial, reldef, etc. */
207 ctype realType = sRef_getType (sr);
208 sstate defstate = sstate_fromQual (qel);
210 if (qual_isRelDef (qel))
212 ; /* okay anywhere */
214 else
216 if (!ctype_isAP (realType)
217 && !ctype_isSU (realType)
218 && !ctype_isUnknown (realType)
219 && !ctype_isAbstract (sRef_getType (sr)))
221 llerror
222 (FLG_SYNTAX,
223 message ("Qualifier %s used on non-pointer or struct: %q",
224 qual_unparse (qel), sRef_unparse (sr)));
229 sRef_setDefState (sr, defstate, fileloc_undefined);
231 else if (qual_isNull (qel))
233 sRef_setNullState (sr, NS_POSNULL, fileloc_undefined);
235 else if (qual_isRelNull (qel))
237 sRef_setNullState (sr, NS_RELNULL, fileloc_undefined);
239 else if (qual_isNotNull (qel))
241 sRef_setNullState (sr, NS_MNOTNULL, fileloc_undefined);
243 else
245 if (qual_isCQual (qel))
247 ; /* okay */
249 else
251 llerror (FLG_SYNTAX,
252 message ("Qualifier %s cannot be used in a globals list",
253 qual_unparse (qel)));
256 } end_qualList_elements;
259 sRef clabstract_createGlobal (sRef sr, qualList quals)
261 sRef res;
263 if (sRef_isValid (sr))
265 res = sRef_copy (sr);
266 DPRINTF (("Reflecting quals: %s / %s", sRef_unparse (sr), qualList_unparse (quals)));
267 reflectGlobalQualifiers (res, quals);
268 DPRINTF (("==> %s", sRef_unparseFull (res)));
270 else
272 res = sRef_undefined;
275 qualList_free (quals);
276 return res;
279 extern void declareCIter (cstring name, /*@owned@*/ uentryList params)
281 uentry ue;
283 ue = uentry_makeIter (name,
284 ctype_makeFunction (ctype_void, params),
285 fileloc_copy (g_currentloc));
287 usymtab_supEntry (uentry_makeEndIter (name, fileloc_copy (g_currentloc)));
288 ue = usymtab_supGlobalEntryReturn (ue);
291 extern void nextIterParam (void)
293 llassert (s_processingIterVars);
294 saveIterParamNo++;
297 extern int iterParamNo (void)
299 llassert (s_processingIterVars);
300 return saveIterParamNo;
304 ** yucky hacks to put it in the right place
307 /*@only@*/ uentry
308 makeCurrentParam (idDecl t)
310 uentry ue;
312 saveStoreLoc = fileloc_undefined;
314 /* param number unknown */
316 ue = uentry_makeParam (t, 0);
317 return ue;
320 ctype
321 declareUnnamedEnum (enumNameList el)
323 ctype ret = usymtab_enumEnumNameListType (el);
324 ctype rt;
325 uentry e;
327 if (ctype_isDefined (ret))
329 rt = ret;
330 e = uentry_makeEnumTagLoc (ctype_enumTag (rt), ret);
332 reflectStorageClass (e);
333 usymtab_supGlobalEntry (e);
335 declareEnumList (el, ret, g_currentloc);
336 enumNameList_free (el);
338 else
340 ctype ct = ctype_createEnum (fakeTag (), el);
342 e = uentry_makeEnumTagLoc (ctype_enumTag (ctype_realType (ct)), ct);
343 reflectStorageClass (e);
345 e = usymtab_supGlobalEntryReturn (e);
346 rt = uentry_getAbstractType (e);
347 declareEnumList (el, ct, g_currentloc);
350 return (rt);
353 ctype
354 declareEnum (cstring ename, enumNameList el)
356 ctype cet;
357 uentry e;
359 llassert (cstring_isDefined (ename));
361 cet = ctype_createEnum (ename, el);
362 e = uentry_makeEnumTagLoc (ename, cet);
363 reflectStorageClass (e);
364 e = usymtab_supGlobalEntryReturn (e);
365 cet = uentry_getType (e);
366 declareEnumList (el, cet, uentry_whereLast (e));
367 return (uentry_getAbstractType (e));
370 static void
371 declareEnumList (enumNameList el, ctype c, fileloc loc)
373 bool boolnames = FALSE;
374 bool othernames = FALSE;
376 (void) context_getSaveLocation (); /* undefine it */
378 if (context_maybeSet (FLG_NUMENUMMEMBERS))
380 int maxnum = context_getValue (FLG_NUMENUMMEMBERS);
381 int num = enumNameList_size (el);
383 if (num > maxnum)
385 voptgenerror
386 (FLG_NUMENUMMEMBERS,
387 message ("Enumerator %s declared with %d members (limit is set to %d)",
388 ctype_unparse (c), num, maxnum),
389 loc);
393 enumNameList_elements (el, e)
395 uentry ue = usymtab_lookupExposeGlob (e);
396 ctype ct = uentry_getType (ue);
398 llassert (uentry_isEnumConstant (ue));
400 if (ctype_isUnknown (ct))
402 uentry_setType (ue, c);
404 else
406 if (cstring_equal (e, context_getFalseName ())
407 || cstring_equal (e, context_getTrueName ()))
409 if (othernames)
411 if (optgenerror
412 (FLG_INCONDEFS,
413 message ("Enumerator mixes boolean name (%s) with "
414 "non-boolean names",
416 uentry_whereLast (ue)))
422 boolnames = TRUE;
423 uentry_setType (ue, ctype_bool);
424 DPRINTF (("Set type: %s / %s",
425 uentry_unparse (ue), ctype_unparse (ctype_bool)));
427 else
429 if (boolnames)
431 if (optgenerror
432 (FLG_INCONDEFS,
433 message ("Enumerator mixes boolean names (%s, %s) with "
434 "non-boolean name: %s",
435 context_getTrueName (),
436 context_getFalseName (),
438 uentry_whereLast (ue)))
444 othernames = TRUE;
447 if (!ctype_match (c, ct))
449 if (ctype_isDirectBool (ct))
451 if (cstring_equal (e, context_getFalseName ())
452 || cstring_equal (e, context_getTrueName ()))
454 DPRINTF (("Here we are!"));
456 else
458 if (optgenerror
459 (FLG_INCONDEFS,
460 message ("Enumerator member %s declared with "
461 "inconsistent type: %s",
462 e, ctype_unparse (c)),
463 uentry_whereLast (ue)))
465 uentry_showWhereSpecifiedExtra
466 (ue, cstring_copy (ctype_unparse (ct)));
470 else
472 if (optgenerror
473 (FLG_INCONDEFS,
474 message ("Enumerator member %s declared with "
475 "inconsistent type: %s",
476 e, ctype_unparse (c)),
477 uentry_whereLast (ue)))
479 uentry_showWhereSpecifiedExtra
480 (ue, cstring_copy (ctype_unparse (ct)));
485 } end_enumNameList_elements;
488 static /*@dependent@*/ uentryList currentParamList;
490 /*drl added 3-28-2002*/
491 /* this function takes a list of paramentar and generates a list
492 of constraints.
495 /* drl modified 10/23/2002
497 The current semantics are generated constraints of the form MaxSet(p) >= 0 and MaxRead(p) >= 0 for all pointers
498 unless the @out@ annotation has been applied to a parameter, then we only want to generate maxSet(p) > = 0
501 void setImplicitfcnConstraints (void)
503 uentryList params;
504 sRef s;
505 constraint c;
506 params = currentParamList;
508 if (constraintList_isDefined (implicitFcnConstraints))
510 constraintList_free (implicitFcnConstraints);
513 implicitFcnConstraints = constraintList_makeNew();
515 uentryList_elements (params, el)
517 DPRINTF (("setImplicitfcnConstraints doing: %s", uentry_unparse(el)));
519 if (uentry_isVariable (el))
521 s = uentry_getSref(el);
523 if (sRef_isReference (s))
525 DPRINTF((message ("%s is a pointer", sRef_unparse(s) ) ));
526 /*drl 4/26/01
527 chagned this from MaxSet(s) == 0 to MaxSet(s) >= 0 */
528 c = constraint_makeSRefWriteSafeInt (s, 0);
530 implicitFcnConstraints = constraintList_add (implicitFcnConstraints , c);
532 /*drl 10/23/2002 added support for out*/
534 if (!uentry_isOut(el))
536 c = constraint_makeSRefReadSafeInt (s, 0);
537 implicitFcnConstraints = constraintList_add (implicitFcnConstraints , c);
540 else
542 DPRINTF((message ("%s is NOT a pointer", sRef_unparse(s) ) ));
544 } /*end uentry_isVariable*/
545 else if (uentry_isElipsisMarker (el) )
547 /* just ignore these*/
551 else
553 /* just ignore this
554 I'm not sure if this is possible though
558 } end_uentryList_elements;
562 /*@observer@*/ constraintList getImplicitFcnConstraints (void)
564 return implicitFcnConstraints;
567 void setCurrentParams (/*@dependent@*/ uentryList ue)
569 currentParamList = ue;
572 void clearCurrentParams (void)
574 currentParamList = uentryList_undefined;
578 ** requires: uentry_isFunction (e)
579 ** parameter names for current function are in currentParamList
582 static void enterFunctionParams (uentryList params)
584 int paramno = 0;
586 uentryList_elements (params, current)
588 if (uentry_hasName (current))
590 uentry_setParamNo (current, paramno);
591 usymtab_supEntry (uentry_copy (current));
594 paramno++;
595 } end_uentryList_elements;
599 extern void enterParamsTemp (void)
601 usymtab_enterScope ();
602 enterFunctionParams (currentParamList);
605 extern void exitParamsTemp (void)
607 usymtab_quietPlainExitScope ();
610 static /*@exposed@*/ uentry clabstract_globalDeclareFunction (idDecl tid)
612 ctype deftype = idDecl_getCtype (tid);
613 ctype rettype;
614 uentry ue;
616 DPRINTF (("Global function: %s", idDecl_unparse (tid)));
618 if (ctype_isFunction (deftype))
620 rettype = ctype_getReturnType (deftype);
622 else
624 rettype = ctype_unknown;
628 ** check has been moved here...
631 if (ctype_isFunction (idDecl_getCtype (tid)))
633 ue = uentry_makeIdFunction (tid);
634 reflectSpecialCode (ue);
635 reflectArgsUsed (ue);
636 reflectStorageClass (ue);
637 uentry_checkParams (ue);
639 DPRINTF (("Supercede function: %s", uentry_unparseFull (ue)));
641 ue = usymtab_supGlobalEntryReturn (ue);
642 DPRINTF (("After supercede function: %s", uentry_unparseFull (ue)));
644 DPRINTF (("Enter function: %s", uentry_unparseFull (ue)));
645 context_enterFunction (ue);
646 enterFunctionParams (uentry_getParams (ue));
648 resetStorageClass ();
649 DPRINTF (("Function: %s", uentry_unparseFull (ue)));
650 return (ue);
652 else
654 llparseerror (message ("Non-function declaration: %q",
655 idDecl_unparse (tid)));
656 return (uentry_undefined);
661 ** for now, no type checking
662 ** (must check later though!)
665 static /*@only@*/ uentry globalDeclareOldStyleFunction (idDecl tid)
667 uentry ue;
670 ** check has been moved here...
673 if (cstring_equalLit (idDecl_observeId (tid), "main"))
675 context_setFlagTemp (FLG_MAINTYPE, FALSE);
678 ue = uentry_makeIdFunction (tid);
679 reflectStorageClass (ue);
680 reflectSpecialCode (ue);
681 reflectArgsUsed (ue);
682 uentry_setDefined (ue, g_currentloc);
683 uentry_checkParams (ue);
684 resetStorageClass ();
686 /* context_enterOldStyleScope (); */
688 return (ue);
691 static void oldStyleDeclareFunction (/*@only@*/ uentry e)
693 uentryList params = saveParamList;
694 ctype rt = uentry_getType (e);
696 llassert (ctype_isFunction (rt));
698 if (uentry_hasStateClauseList (e)
699 || uentry_hasConditions (e))
701 llfatalerror (message ("%q: Old-style function declaration uses a clause (rewrite with function parameters): %q",
702 fileloc_unparse (g_currentloc), uentry_unparse (e)));
705 e = usymtab_supGlobalEntryReturn (e);
707 context_enterFunction (e);
708 enterFunctionParams (params);
709 saveParamList = uentryList_undefined;
710 resetStorageClass ();
713 static void oldStyleCompleteFunction (/*@only@*/ uentry e)
715 uentryList params = saveParamList;
716 ctype rt = uentry_getType (e);
718 llassert (ctype_isFunction (rt));
720 if (uentry_hasStateClauseList (e)
721 || uentry_hasConditions (e))
723 llfatalerror (message ("%q: Old-style function declaration uses a clause (rewrite with function parameters): %q",
724 fileloc_unparse (g_currentloc), uentry_unparse (e)));
727 e = usymtab_supGlobalEntryReturn (e);
729 context_completeOldStyleFunction (e);
730 enterFunctionParams (params);
731 saveParamList = uentryList_undefined;
732 resetStorageClass ();
735 void clabstract_declareFunction (idDecl tid) /*@globals undef saveFunction; @*/
737 uentry ue;
739 DPRINTF (("Declare function: %s", idDecl_unparse (tid)));
741 if (ctype_isUnknown (idDecl_getCtype (tid)))
744 ** No type, its really a plain name (int) declaration
747 voptgenerror (FLG_IMPTYPE,
748 message ("No type before declaration name (implicit int type): %q",
749 idDecl_unparse (tid)),
750 g_currentloc);
751 tid = idDecl_replaceCtype (tid, ctype_int);
752 processVariable (tid);
753 saveFunction = uentry_undefined;
755 else
757 if (s_processingParams)
759 ue = globalDeclareOldStyleFunction (tid);
760 saveFunction = ue;
761 DPRINTF (("Set save function: %s", uentry_unparseFull (ue)));
763 else
765 saveFunction = uentry_undefined;
767 if (context_inRealFunction ())
769 ue = uentry_makeVariableLoc (idDecl_observeId (tid), ctype_unknown);
771 llparseerror (message ("Function declared inside function: %q",
772 idDecl_unparse (tid)));
774 context_quietExitFunction ();
775 ue = usymtab_supEntryReturn (ue);
777 else
779 if (context_inInnerScope ())
781 llparseerror (message ("Declaration in inner context: %q",
782 idDecl_unparse (tid)));
784 sRef_setGlobalScope ();
785 ue = uentry_makeVariableLoc (idDecl_observeId (tid),
786 ctype_unknown);
787 ue = usymtab_supGlobalEntryReturn (ue);
788 sRef_clearGlobalScope ();
790 else
792 ue = clabstract_globalDeclareFunction (tid);
796 resetGlobals ();
799 resetStorageClass ();
802 idDecl_free (tid);
805 void declareStaticFunction (idDecl tid) /*@globals undef saveFunction; @*/
807 uentry ue;
809 DPRINTF (("Declare static funciton: %s", idDecl_unparse (tid)));
811 if (s_processingParams)
813 ue = globalDeclareOldStyleFunction (tid);
814 saveFunction = ue;
816 else
818 saveFunction = uentry_undefined;
820 if (context_inRealFunction ())
822 ue = uentry_makeVariableLoc (idDecl_observeId (tid), ctype_unknown);
824 llparseerror (message ("Function declared inside function: %q",
825 idDecl_unparse (tid)));
827 context_quietExitFunction ();
828 ue = usymtab_supEntryReturn (ue);
830 else
832 if (context_inInnerScope ())
834 llparseerror (message ("Declaration in inner context: %q",
835 idDecl_unparse (tid)));
837 sRef_setGlobalScope ();
838 ue = uentry_makeVariableLoc (idDecl_observeId (tid),
839 ctype_unknown);
840 ue = usymtab_supGlobalEntryReturn (ue);
841 sRef_clearGlobalScope ();
843 else
845 ctype deftype = idDecl_getCtype (tid);
846 ctype rettype;
848 if (ctype_isFunction (deftype))
850 rettype = ctype_getReturnType (deftype);
852 else
854 rettype = ctype_unknown;
858 ** check has been moved here...
861 if (ctype_isFunction (idDecl_getCtype (tid)))
863 ue = uentry_makeIdFunction (tid);
864 reflectSpecialCode (ue);
865 reflectArgsUsed (ue);
867 else
869 DPRINTF (("Here we are!"));
870 llparseerror (message ("Inconsistent function declaration: %q",
871 idDecl_unparse (tid)));
873 tid = idDecl_replaceCtype
874 (tid, ctype_makeFunction (ctype_unknown, uentryList_undefined));
875 ue = uentry_makeIdFunction (tid);
878 reflectStorageClass (ue);
879 uentry_setStatic (ue);
881 uentry_checkParams (ue);
883 DPRINTF (("Sub global entry: %s", uentry_unparse (ue)));
884 ue = usymtab_supGlobalEntryReturn (ue);
886 context_enterFunction (ue);
887 enterFunctionParams (uentry_getParams (ue));
888 resetStorageClass ();
892 resetGlobals ();
895 resetStorageClass ();
896 idDecl_free (tid);
899 void
900 checkTypeDecl (uentry e, ctype rep)
902 cstring n = uentry_getName (e);
904 DPRINTF (("Check type decl: %s", uentry_unparseFull (e)));
906 if (cstring_equal (context_getBoolName (), n))
908 ctype rrep = ctype_realType (rep);
911 ** for abstract enum types, we need to fix the enum members:
912 ** they should have the abstract type, not the rep type.
915 if (ctype_isEnum (ctype_realType (rrep)))
917 enumNameList el = ctype_elist (rrep);
919 enumNameList_elements (el, ye)
921 if (usymtab_existsGlob (ye))
923 uentry ue = usymtab_lookupSafe (ye);
924 uentry_setType (ue, ctype_bool);
927 if (cstring_equal (context_getTrueName (), ye)
928 || cstring_equal (context_getFalseName (), ye))
932 else
934 vgenhinterror
935 (FLG_SYNTAX,
936 message ("Member of boolean enumerated type definition "
937 "does not match name set to represent true "
938 "or false: %s",
939 ye),
940 message ("Use -boolfalse and -booltrue to set the "
941 "name of false and true boolean values."),
942 uentry_whereDefined (e));
944 } end_enumNameList_elements;
948 if (usymtab_exists (n))
950 usymId llm = usymtab_getId (n);
951 uentry le = usymtab_getTypeEntry (typeId_fromUsymId (llm));
953 uentry_setDeclared (e, g_currentloc);
954 uentry_setSref (e, sRef_makeGlobal (llm, uentry_getType (le), stateInfo_currentLoc ()));
956 DPRINTF (("Here we are: %s / %s",
957 n, context_getBoolName ()));
959 if (uentry_isAbstractDatatype (le))
961 ctype rrep = ctype_realType (rep);
963 DPRINTF (("Abstract type: %s", uentry_unparseFull (le)));
966 ** for abstract enum types, we need to fix the enum members:
967 ** they should have the abstract type, not the rep type.
970 if (ctype_isEnum (ctype_realType (rrep)))
972 ctype at = uentry_getAbstractType (le);
973 enumNameList el = ctype_elist (rrep);
975 enumNameList_elements (el, ye)
977 if (usymtab_existsGlob (ye))
979 uentry ue = usymtab_lookupSafe (ye);
981 llassert (uentry_isEitherConstant (ue));
983 /* evans 2002-04-22 */
984 if (ctype_isBool (uentry_getType (ue)))
987 ** If set using -booltrue or -boolfalse, don't change the type.
990 else
992 llassertprint (ctype_match (uentry_getType (ue), rrep),
993 ("Bad enum: %s / %s",
994 uentry_unparse (ue),
995 ctype_unparse (rrep)));
997 uentry_setType (ue, at);
1000 } end_enumNameList_elements;
1003 if (uentry_isMutableDatatype (le))
1005 /* maybe more complicated if abstract and immutable ? */
1007 if (!ctype_isRealPointer (rep) && !ctype_isRealAbstract (rep))
1009 voptgenerror
1010 (FLG_MUTREP,
1011 message ("Mutable abstract type %s declared without pointer "
1012 "indirection: %s (violates assignment semantics)",
1013 n, ctype_unparse (rep)),
1014 uentry_whereDefined (e));
1016 uentry_setMutable (e);
1021 else
1023 fileloc fl = uentry_whereDeclared (e);
1025 if (context_getFlag (FLG_LIKELYBOOL)
1026 && !context_getFlag (FLG_BOOLINT))
1028 if ((cstring_equalLit (n, "BOOL")
1029 || cstring_equalLit (n, "Bool")
1030 || cstring_equalLit (n, "bool")
1031 || cstring_equalLit (n, "boolean")
1032 || cstring_equalLit (n, "Boolean")
1033 || cstring_equalLit (n, "BOOLEAN"))
1034 && !(cstring_equal (n, context_getBoolName ())))
1036 if (context_setBoolName ()) {
1037 voptgenerror
1038 (FLG_LIKELYBOOL,
1039 message ("Type %s is probably meant as a boolean type, but does "
1040 "not match the boolean type name \"%s\".",
1042 context_getBoolName ()),
1043 fl);
1044 } else
1045 voptgenerror
1046 (FLG_LIKELYBOOL,
1047 message ("Type %s is probably meant as a boolean type, "
1048 "but the boolean type name is not set. "
1049 "Use -booltype %s to set it.",
1052 fl);
1056 if (!uentry_isStatic (e)
1057 && !ctype_isFunction (uentry_getType (e))
1058 && !fileloc_isLib (fl)
1059 && !fileloc_isImport (fl)
1060 && fileloc_isHeader (fl))
1062 voptgenerror (FLG_EXPORTTYPE,
1063 message ("Type exported, but not specified: %s\n", n),
1064 fl);
1068 cstring_free (n);
1071 uentryList
1072 fixUentryList (idDeclList tl, qtype q)
1074 uentryList f = uentryList_new ();
1076 idDeclList_elements (tl, i)
1078 if (idDecl_isDefined (i))
1080 uentry ue;
1081 uentry old;
1082 ctype rt;
1084 (void) idDecl_fixBase (i, q);
1087 ** implicit annotations
1090 (void) fixStructDecl (i);
1092 ue = uentry_makeIdVariable (i);
1093 rt = ctype_realType (uentry_getType (ue));
1096 ** where is this here???
1098 if (ctype_isArray (rt) || ctype_isSU (rt))
1100 sRef_setAllocated (uentry_getSref (ue), uentry_whereDefined (ue));
1106 if (uentry_isValid (old = uentryList_lookupField (f, uentry_rawName (ue))))
1108 if (optgenerror (FLG_SYNTAX,
1109 message ("Field name reused: %s", uentry_rawName (ue)),
1110 uentry_whereDefined (ue)))
1112 llgenmsg (message ("Previous use of %s", uentry_rawName (ue)),
1113 uentry_whereDefined (old));
1117 f = uentryList_add (f, ue);
1119 } end_idDeclList_elements;
1121 idDeclList_free (tl);
1122 return (f);
1126 ** This is a hack to support unnamed struct/union fields as done by
1127 ** Microsoft VC++. It is not supported by the ANSI standard.
1129 ** The inner fields are added to the outer structure. This is meaningful
1130 ** for nesting structs inside unions, but Splint does no related
1131 ** checking.
1134 uentryList
1135 fixUnnamedDecl (qtype q)
1137 ctype ct = ctype_realType (qtype_getType (q));
1139 if (ctype_isStruct (ct) || ctype_isUnion (ct))
1141 return uentryList_single (uentry_makeUnnamedVariable (ct));
1143 else if (ctype_isEnum (ct))
1145 /* evans 2002-02-05: nothing to do for unnamed enum lists */
1146 return uentryList_undefined;
1148 else
1150 voptgenerror
1151 (FLG_SYNTAX,
1152 message ("Type name in field declarations: %s", qtype_unparse (q)),
1153 g_currentloc);
1156 return uentryList_undefined;
1159 void setStorageClass (storageClassCode sc)
1161 storageClass = sc;
1164 void
1165 setProcessingIterVars (uentry iter)
1167 s_processingIterVars = TRUE;
1168 currentIter = iter;
1169 saveIterParamNo = 0;
1172 void
1173 setProcessingGlobalsList ()
1175 s_processingGlobals = TRUE;
1176 fcnNoGlobals = FALSE;
1179 static bool ProcessingGlobMods = FALSE;
1181 void
1182 setProcessingGlobMods ()
1184 ProcessingGlobMods = TRUE;
1187 void
1188 clearProcessingGlobMods ()
1190 ProcessingGlobMods = FALSE;
1193 bool
1194 isProcessingGlobMods ()
1196 return (ProcessingGlobMods);
1199 static void resetGlobals (void)
1201 s_processingGlobals = FALSE;
1202 fcnNoGlobals = FALSE;
1205 void
1206 unsetProcessingGlobals ()
1208 s_processingGlobals = FALSE;
1211 void
1212 setProcessingVars (/*@only@*/ qtype q)
1214 s_processingVars = TRUE;
1215 qtype_free (processingType);
1216 processingType = q;
1219 static void
1220 setGenericParamList (/*@dependent@*/ uentryList pm)
1222 s_processingParams = TRUE;
1223 saveParamList = pm;
1226 void
1227 setProcessingTypedef (qtype q)
1229 s_processingTypedef = TRUE;
1231 qtype_free (processingType);
1232 processingType = q;
1235 void
1236 unsetProcessingVars ()
1238 resetStorageClass ();
1239 s_processingVars = FALSE;
1242 void
1243 oldStyleDoneParams ()
1245 if (s_processingParams)
1247 if (uentry_isInvalid (saveFunction))
1249 llbuglit ("unsetProcessingVars: no saved function\n");
1251 else
1253 ctype ct = ctype_getReturnType (uentry_getType (saveFunction));
1254 uentryList params = uentryList_copy (saveParamList);
1255 ctype ct2 = ctype_makeFunction (ct, params);
1257 uentry_setType (saveFunction, ct2);
1258 s_processingParams = FALSE;
1260 oldStyleCompleteFunction (saveFunction);
1261 saveFunction = uentry_undefined;
1262 resetGlobals ();
1265 else
1268 ** If the paramlist used a type name, we could be here.
1271 llfatalerror (message ("%q: Old-style function parameter list uses a "
1272 "type name.", fileloc_unparse (g_currentloc)));
1276 void
1277 checkDoneParams ()
1279 if (uentry_isValid (saveFunction))
1282 ** old style declaration
1285 ctype ct = ctype_getReturnType (uentry_getType (saveFunction));
1286 ctype ct2;
1288 DPRINTF (("save function: %s", uentry_unparseFull (saveFunction)));
1290 uentryList_elements (saveParamList, current)
1292 uentry_setType (current, ctype_int); /* all params are ints */
1293 } end_uentryList_elements;
1295 ct2 = ctype_makeParamsFunction (ct, uentryList_copy (saveParamList));
1297 uentry_setType (saveFunction, ct2);
1298 s_processingParams = FALSE;
1300 oldStyleDeclareFunction (saveFunction);
1301 saveFunction = uentry_undefined;
1305 void clabstract_declareType (/*@only@*/ exprNodeList decls, /*@only@*/ warnClause warn)
1307 llassert (s_processingTypedef);
1309 DPRINTF (("Declare type: %s", exprNodeList_unparse (decls)));
1311 if (warnClause_isDefined (warn))
1313 DPRINTF (("Has a warn clause!"));
1314 DPRINTF (("Warn: %s", warnClause_unparse (warn)));
1316 exprNodeList_elements (decls, el)
1318 uentry ue = exprNode_getUentry (el);
1319 cstring uname = uentry_getName (ue);
1321 DPRINTF (("Entry: %s", exprNode_unparse (el)));
1324 ** Need to lookup again to make sure we have the right one...
1327 ue = usymtab_lookupExposeGlob (uname);
1329 llassert (uentry_isValid (ue));
1330 llassert (uentry_isDatatype (ue));
1332 DPRINTF (("Warning for %s: %s",
1333 uentry_unparse (ue), warnClause_unparse (warn)));
1335 uentry_addWarning (ue, warnClause_copy (warn));
1336 DPRINTF (("After add warning: %s", uentry_unparseFull (ue)));
1337 cstring_free (uname);
1338 } end_exprNodeList_elements;
1341 warnClause_free (warn);
1342 exprNodeList_free (decls);
1343 unsetProcessingTypedef ();
1346 void
1347 unsetProcessingTypedef ()
1349 s_processingTypedef = FALSE;
1352 void checkConstant (qtype t, idDecl id)
1354 uentry e;
1356 id = idDecl_fixBase (id, t);
1357 e = uentry_makeIdConstant (id);
1359 reflectStorageClass (e);
1360 resetStorageClass ();
1362 DPRINTF (("Constant: %s", uentry_unparseFull (e)));
1363 usymtab_supGlobalEntry (e);
1366 void checkValueConstant (qtype t, idDecl id, exprNode e)
1368 uentry ue;
1370 id = idDecl_fixBase (id, t);
1371 ue = uentry_makeIdConstant (id);
1372 reflectStorageClass (ue);
1373 resetStorageClass ();
1375 if (exprNode_isDefined (e))
1377 if (!exprNode_matchType (uentry_getType (ue), e))
1379 (void) gentypeerror
1380 (exprNode_getType (e), e,
1381 uentry_getType (ue), exprNode_undefined,
1382 message ("Constant %q initialized to type %t, expects %t: %s",
1383 uentry_getName (ue),
1384 exprNode_getType (e),
1385 uentry_getType (ue),
1386 exprNode_unparse (e)),
1387 exprNode_loc (e));
1389 else
1391 if (exprNode_hasValue (e))
1393 uentry_mergeConstantValue (ue, multiVal_copy (exprNode_getValue (e)));
1395 else
1397 DPRINTF (("No value: %s", exprNode_unparse (e)));
1402 DPRINTF (("Constant value: %s", uentry_unparseFull (ue)));
1403 usymtab_supGlobalEntry (ue);
1406 static void processVariable (idDecl t)
1408 uentry e;
1409 ctype ct;
1411 ct = ctype_realType (idDecl_getCtype (t));
1413 if (s_processingParams)
1415 cstring id = idDecl_getName (t);
1416 int paramno = uentryList_lookupRealName (saveParamList, id);
1418 if (paramno >= 0)
1420 uentry cparam = uentryList_getN (saveParamList, paramno);
1422 DPRINTF (("Processing param: %s", uentry_unparseFull (cparam)));
1423 uentry_setType (cparam, idDecl_getCtype (t));
1424 uentry_reflectQualifiers (cparam, idDecl_getQuals (t));
1425 uentry_setDeclaredOnly (cparam, context_getSaveLocation ());
1426 DPRINTF (("Processing param: %s", uentry_unparseFull (cparam)));
1428 else
1430 llfatalerrorLoc
1431 (message ("Old style declaration uses unlisted parameter: %s",
1432 id));
1435 else
1437 fileloc loc;
1439 if (context_inIterDef ())
1441 cstring pname = makeParam (idDecl_observeId (t));
1442 uentry p = usymtab_lookupSafe (pname);
1444 cstring_free (pname);
1446 if (uentry_isYield (p))
1448 e = uentry_makeParam (t, sRef_getParam (uentry_getSref (p)));
1449 uentry_checkYieldParam (p, e);
1450 usymtab_supEntrySref (e);
1451 return;
1455 if ((hasSpecialCode () || argsUsed)
1456 && ctype_isFunction (idDecl_getCtype (t)))
1458 e = uentry_makeIdFunction (t);
1459 reflectSpecialCode (e);
1460 reflectArgsUsed (e);
1462 else
1464 e = uentry_makeIdVariable (t);
1467 loc = uentry_whereDeclared (e);
1470 if (context_inGlobalScope ())
1472 uentry_checkParams was here!
1476 if (ctype_isFunction (uentry_getType (e)))
1478 clabstract_prepareFunction (e);
1481 DPRINTF (("Superceding... %s", uentry_unparseFull (e)));
1482 e = usymtab_supEntrySrefReturn (e);
1483 DPRINTF (("After superceding... %s", uentry_unparseFull (e)));
1485 if (uentry_isExtern (e) && !context_inGlobalScope ())
1487 voptgenerror
1488 (FLG_NESTEDEXTERN,
1489 message ("Declaration using extern inside function scope: %q",
1490 uentry_unparse (e)),
1491 g_currentloc);
1493 uentry_setDefined (e, fileloc_getExternal ());
1494 sRef_setDefined (uentry_getSref (e), fileloc_getExternal ());
1497 if (uentry_isFunction (e))
1499 if (!context_inXHFile ())
1501 checkParamNames (e);
1505 if (uentry_isVar (e) && uentry_isCheckedUnknown (e))
1507 sRef sr = uentry_getSref (e);
1509 if (sRef_isLocalVar (sr))
1511 if (context_getFlag (FLG_IMPCHECKMODINTERNALS))
1513 uentry_setCheckMod (e);
1515 else
1517 uentry_setUnchecked (e);
1520 else if (sRef_isFileStatic (sr))
1522 if (context_getFlag (FLG_IMPCHECKEDSTRICTSTATICS))
1524 uentry_setCheckedStrict (e);
1526 else if (context_getFlag (FLG_IMPCHECKEDSTATICS))
1528 uentry_setChecked (e);
1530 else if (context_getFlag (FLG_IMPCHECKMODSTATICS))
1532 uentry_setCheckMod (e);
1534 else
1539 else /* real global */
1541 llassert (sRef_isRealGlobal (sr));
1543 if (context_getFlag (FLG_IMPCHECKEDSTRICTGLOBALS))
1545 uentry_setCheckedStrict (e);
1547 else if (context_getFlag (FLG_IMPCHECKEDGLOBALS))
1549 uentry_setChecked (e);
1551 else if (context_getFlag (FLG_IMPCHECKMODGLOBALS))
1553 uentry_setCheckMod (e);
1555 else
1564 void processNamedDecl (idDecl t)
1566 if (qtype_isUndefined (processingType))
1568 processingType = qtype_create (ctype_int);
1569 t = idDecl_fixBase (t, processingType);
1571 voptgenerror (FLG_IMPTYPE,
1572 message ("No type before declaration name (implicit int type): %q",
1573 idDecl_unparse (t)),
1574 g_currentloc);
1576 else
1578 t = idDecl_fixBase (t, processingType);
1581 DPRINTF (("Declare: %s", idDecl_unparse (t)));
1583 if (s_processingGlobals)
1585 cstring id = idDecl_getName (t);
1586 uentry ue = usymtab_lookupSafe (id);
1588 if (!uentry_isValid (ue))
1590 llerror (FLG_UNRECOG,
1591 message ("Variable used in globals list is undeclared: %s", id));
1593 else
1595 if (!ctype_match (uentry_getType (ue), idDecl_getCtype (t)))
1597 voptgenerror
1598 (FLG_INCONDEFS,
1599 message ("Variable %s used in globals list declared %s, "
1600 "but listed as %s",
1601 id, ctype_unparse (uentry_getType (ue)),
1602 ctype_unparse (idDecl_getCtype (t))),
1603 g_currentloc);
1605 else
1607 sRef sr = sRef_copy (uentry_getSref (ue));
1608 reflectGlobalQualifiers (sr, idDecl_getQuals (t));
1612 else if (s_processingVars)
1614 processVariable (t);
1616 else if (s_processingTypedef)
1618 ctype ct = idDecl_getCtype (t);
1619 uentry e;
1621 DPRINTF (("Processing typedef: %s", ctype_unparse (ct)));
1623 e = uentry_makeIdDatatype (t);
1625 if (cstring_equal (idDecl_getName (t), context_getBoolName ())) {
1626 ctype rt = ctype_realType (ct);
1628 if (ctype_isEnum (rt)) {
1630 } else {
1631 if (!(ctype_isInt (rt)
1632 || ctype_isUnknown (rt)
1633 || ctype_isChar (rt))) {
1634 (void) llgenerror
1635 (FLG_BOOLTYPE,
1636 message ("Boolean type %s defined using non-standard type %s (integral, char or enum type expected)",
1637 context_getBoolName (),
1638 ctype_unparse (ct)),
1639 uentry_whereLast (e));
1642 ct = ctype_bool;
1643 uentry_setType (e, ct);
1647 reflectStorageClass (e);
1648 checkTypeDecl (e, ct);
1650 e = usymtab_supReturnTypeEntry (e);
1652 else
1654 llparseerror (message ("Suspect missing struct or union keyword: %q",
1655 idDecl_unparse (t)));
1661 ** moved from grammar
1664 static idDecl fixStructDecl (/*@returned@*/ idDecl d)
1666 if (ctype_isVisiblySharable (idDecl_getCtype (d))
1667 && context_getFlag (FLG_STRUCTIMPONLY))
1669 if (!qualList_hasAliasQualifier (idDecl_getQuals (d)))
1671 if (qualList_hasExposureQualifier (idDecl_getQuals (d)))
1673 idDecl_addQual (d, qual_createDependent ());
1675 else
1677 idDecl_addQual (d, qual_createImpOnly ());
1682 return d;
1685 ctype
1686 declareUnnamedStruct (/*@only@*/ uentryList f)
1688 DPRINTF (("Unnamed struct: %s", uentryList_unparse (f)));
1690 if (context_maybeSet (FLG_NUMSTRUCTFIELDS))
1692 int num = uentryList_size (f);
1693 int max = context_getValue (FLG_NUMSTRUCTFIELDS);
1695 if (num > max)
1697 voptgenerror
1698 (FLG_NUMSTRUCTFIELDS,
1699 message ("Structure declared with %d fields "
1700 "(limit is set to %d)",
1701 num, max),
1702 g_currentloc);
1706 return (ctype_createUnnamedStruct (f));
1709 ctype
1710 declareUnnamedUnion (/*@only@*/ uentryList f)
1712 DPRINTF (("Unnamed union: %s", uentryList_unparse (f)));
1714 if (context_maybeSet (FLG_NUMSTRUCTFIELDS))
1716 int num = uentryList_size (f);
1717 int max = context_getValue (FLG_NUMSTRUCTFIELDS);
1719 if (num > max)
1721 voptgenerror
1722 (FLG_NUMSTRUCTFIELDS,
1723 message ("Union declared with %d fields "
1724 "(limit is set to %d)",
1725 num, max),
1726 g_currentloc);
1730 return (ctype_createUnnamedUnion (f));
1733 ctype declareStruct (cstring id, /*@only@*/ uentryList f)
1735 ctype ct;
1736 uentry ue;
1737 int num = uentryList_size (f);
1739 DPRINTF (("Declare struct: %s / %s [%d]", id, uentryList_unparse (f),
1740 uentryList_size (f)));
1742 ct = ctype_createStruct (cstring_copy (id), f);
1744 DPRINTF (("Ctype: %s", ctype_unparse (ct)));
1746 ue = uentry_makeStructTagLoc (id, ct);
1748 DPRINTF (("ue: %s", uentry_unparseFull (ue)));
1750 if (context_maybeSet (FLG_NUMSTRUCTFIELDS))
1752 int max = context_getValue (FLG_NUMSTRUCTFIELDS);
1754 if (num > max)
1756 voptgenerror
1757 (FLG_NUMSTRUCTFIELDS,
1758 message ("Structure %q declared with %d fields "
1759 "(limit is set to %d)",
1760 uentry_getName (ue), num, max),
1761 uentry_whereLast (ue));
1765 return (usymtab_supTypeEntry (ue));
1768 ctype declareUnion (cstring id, uentryList f)
1770 ctype ct;
1771 uentry ue;
1772 int num = uentryList_size (f);
1774 ct = ctype_createUnion (cstring_copy (id), f);
1775 ue = uentry_makeUnionTagLoc (id, ct);
1777 if (context_maybeSet (FLG_NUMSTRUCTFIELDS))
1779 int max = context_getValue (FLG_NUMSTRUCTFIELDS);
1781 if (num > max)
1783 voptgenerror
1784 (FLG_NUMSTRUCTFIELDS,
1785 message ("Union %q declared with %d fields "
1786 "(limit is set to %d)",
1787 uentry_getName (ue), num, max),
1788 uentry_whereLast (ue));
1792 return (usymtab_supTypeEntry (ue));
1795 ctype handleStruct (/*@only@*/ cstring id)
1797 if (usymtab_existsStructTag (id))
1799 ctype ct = uentry_getAbstractType (usymtab_lookupStructTag (id));
1801 cstring_free (id);
1802 return ct;
1804 else
1806 return (ctype_createForwardStruct (id));
1810 ctype handleUnion (/*@only@*/ cstring id)
1812 if (usymtab_existsUnionTag (id))
1814 ctype ret = uentry_getAbstractType (usymtab_lookupUnionTag (id));
1815 cstring_free (id);
1816 return (ret);
1818 else
1820 return (ctype_createForwardUnion (id));
1824 ctype
1825 handleEnum (cstring id)
1827 if (usymtab_existsEnumTag (id))
1829 ctype ret = uentry_getAbstractType (usymtab_lookupEnumTag (id));
1830 cstring_free (id);
1831 return ret;
1833 else
1835 return (ctype_createForwardEnum (id));
1839 bool processingIterVars (void)
1841 return s_processingIterVars;
1844 uentry getCurrentIter (void)
1846 return currentIter;
1849 static bool flipOldStyle = FALSE;
1850 static bool flipNewStyle = TRUE;
1852 void setFlipOldStyle () { flipOldStyle = TRUE; }
1853 bool isFlipOldStyle () { return flipOldStyle; }
1854 bool isNewStyle () { return flipNewStyle; }
1855 void setNewStyle () { flipNewStyle = TRUE; }
1857 /*@dependent@*/ uentryList handleParamIdList (/*@dependent@*/ uentryList params)
1859 int paramno = 0;
1862 ** this is a really YUCKY hack to handle old style
1863 ** declarations.
1866 voptgenerror (FLG_OLDSTYLE,
1867 cstring_makeLiteral ("Old style function declaration"),
1868 g_currentloc);
1870 DPRINTF (("Handle old style params: %s", uentryList_unparseFull (params)));
1872 uentryList_elements (params, current)
1874 uentry_setParam (current);
1875 uentry_setSref (current, sRef_makeParam
1876 (paramno, ctype_unknown,
1877 stateInfo_makeLoc (uentry_whereLast (current), SA_DECLARED)));
1878 paramno++;
1879 } end_uentryList_elements;
1881 setGenericParamList (params);
1882 cscannerHelp_setExpectingTypeName ();
1884 return params;
1887 /*@dependent@*/ uentryList handleParamTypeList (/*@returned@*/ uentryList params)
1889 if (flipOldStyle)
1891 uentryList_fixMissingNames (params);
1893 voptgenerror (FLG_OLDSTYLE,
1894 cstring_makeLiteral ("Old style function declaration."),
1895 g_currentloc);
1897 setGenericParamList (params);
1898 flipOldStyle = FALSE;
1899 cscannerHelp_setExpectingTypeName ();
1902 return (params);
1905 void
1906 doVaDcl ()
1908 ctype c = ctype_unknown;
1909 cstring id = cstring_makeLiteral ("va_alist");
1910 uentry e;
1912 if (s_processingParams)
1914 int i = uentryList_lookupRealName (saveParamList, id);
1916 if (i >= 0)
1918 fileloc loc = context_getSaveLocation ();
1919 e = uentry_makeVariableSrefParam
1920 (id, c, loc,
1921 sRef_makeParam (i, c, stateInfo_makeLoc (loc, SA_DECLARED)));
1923 else
1925 e = uentry_undefined; /* suppress gcc message */
1926 llfatalerrorLoc (cstring_makeLiteral ("va_dcl used without va_alist"));
1929 else
1931 llerror (FLG_SYNTAX, cstring_makeLiteral ("va_dcl used outside of function declaration"));
1932 e = uentry_makeVariableLoc (id, c);
1935 cstring_free (id);
1936 uentry_setUsed (e, g_currentloc);
1937 usymtab_supEntrySref (e);
1940 /*@exposed@*/ sRef modListPointer (/*@exposed@*/ sRef s)
1942 ctype ct = sRef_getType (s);
1943 ctype rt = ctype_realType (ct);
1945 if (ctype_isAP (rt))
1947 if (context_inHeader () && ctype_isAbstract (ct))
1949 voptgenerror
1950 (FLG_ABSTRACT,
1951 message
1952 ("Modifies clause in header file dereferences abstract "
1953 "type %s (interface modifies clause should not depend "
1954 "on or expose type representation): %q",
1955 ctype_unparse (ct),
1956 sRef_unparse (s)),
1957 g_currentloc);
1960 return (sRef_constructPointer (s));
1962 else
1964 if (ctype_isKnown (rt))
1966 voptgenerror
1967 (FLG_TYPE,
1968 message ("Implementation modifies clause dereferences non-pointer (type %s): %q",
1969 ctype_unparse (rt),
1970 sRef_unparse (s)),
1971 g_currentloc);
1974 return s;
1978 /*@exposed@*/ sRef modListFieldAccess (sRef s, cstring f)
1980 ctype ct = sRef_getType (s);
1981 ctype rt = ctype_realType (ct);
1983 if (ctype_isStructorUnion (rt))
1985 uentry tf = uentryList_lookupField (ctype_getFields (rt), f);
1987 if (uentry_isUndefined (tf))
1989 voptgenerror (FLG_TYPE,
1990 message ("Modifies list accesses non-existent "
1991 "field %s of %t: %q", f, ct,
1992 sRef_unparse (s)),
1993 g_currentloc);
1995 cstring_free (f);
1996 return sRef_undefined;
1998 else
2000 if (ctype_isAbstract (ct) && context_inHeader ())
2002 voptgenerror
2003 (FLG_ABSTRACT,
2004 message
2005 ("Modifies clause in header file accesses abstract "
2006 "type %s (interface modifies clause should not depend "
2007 "on or expose type representation): %q",
2008 ctype_unparse (ct),
2009 sRef_unparse (s)),
2010 g_currentloc);
2014 cstring_markOwned (f);
2015 return (sRef_makeField (s, f));
2017 else
2019 voptgenerror
2020 (FLG_TYPE,
2021 message ("Modifies clause dereferences non-pointer (type %s): %q",
2022 ctype_unparse (rt),
2023 sRef_unparse (s)),
2024 g_currentloc);
2026 cstring_free (f);
2027 return s;
2031 /*@dependent@*/ sRef clabstract_unrecognizedGlobal (cstring s)
2033 if (cstring_equalLit (s, "nothing"))
2035 return sRef_makeNothing ();
2037 else if (cstring_equalLit (s, "internalState"))
2039 return sRef_makeInternalState ();
2041 else if (cstring_equalLit (s, "fileSystem")
2042 || cstring_equalLit (s, "systemState"))
2044 return sRef_makeSystemState ();
2046 else
2048 voptgenerror
2049 (FLG_UNRECOG,
2050 message ("Unrecognized identifier in globals list: %s", s),
2051 g_currentloc);
2053 return sRef_undefined;
2057 /*@exposed@*/ sRef modListArrowAccess (sRef s, cstring f)
2059 ctype ct = sRef_getType (s);
2060 ctype rt = ctype_realType (ct);
2062 if (ctype_isRealPointer (rt))
2064 ctype b = ctype_baseArrayPtr (rt);
2065 ctype rb = ctype_realType (b);
2067 if (ctype_isStructorUnion (rb))
2069 uentry tf = uentryList_lookupField (ctype_getFields (rb), f);
2071 if (uentry_isUndefined (tf))
2073 voptgenerror (FLG_TYPE,
2074 message ("Modifies list arrow accesses non-existent "
2075 "field %s of %t: %q", f, b,
2076 sRef_unparse (s)),
2077 g_currentloc);
2079 cstring_free (f);
2080 return sRef_undefined;
2082 else
2084 if (context_inHeader ())
2086 if (ctype_isAbstract (b))
2088 voptgenerror
2089 (FLG_ABSTRACT,
2090 message
2091 ("Modifies clause in header file arrow accesses abstract "
2092 "type %s (interface modifies clause should not depend "
2093 "on or expose type representation): %q",
2094 ctype_unparse (b),
2095 sRef_unparse (s)),
2096 g_currentloc);
2099 else
2101 if (ctype_isAbstract (rt))
2103 voptgenerror
2104 (FLG_ABSTRACT,
2105 message
2106 ("Modifies clause arrow accesses inaccessible abstract "
2107 "type %s (interface modifies clause should not depend "
2108 "on or expose type representation): %q",
2109 ctype_unparse (rt),
2110 sRef_unparse (s)),
2111 g_currentloc);
2116 cstring_markOwned (f);
2117 return (sRef_makeArrow (s, f));
2119 else
2121 voptgenerror
2122 (FLG_TYPE,
2123 message ("Modifies clause arrow accesses pointer to "
2124 "non-structure (type %s): %q",
2125 ctype_unparse (rt),
2126 sRef_unparse (s)),
2127 g_currentloc);
2130 else
2132 voptgenerror
2133 (FLG_TYPE,
2134 message ("Modifies clause arrow accesses non-pointer (type %s): %q",
2135 ctype_unparse (rt),
2136 sRef_unparse (s)),
2137 g_currentloc);
2140 cstring_free (f);
2141 return s;
2144 sRef checkStateClausesId (uentry ue)
2146 cstring s = uentry_rawName (ue);
2148 if (sRef_isFileOrGlobalScope (uentry_getSref (ue)))
2150 voptgenerror
2151 (FLG_COMMENTERROR,
2152 message ("Global variable %s used state clause. (Global variables "
2153 "are not recognized in state clauses. If they are present "
2154 "they are ignored. "
2155 " If there is "
2156 "sufficient interest in support for this, it may be "
2157 "added to a future release. Send mail to "
2158 "info@splint.org.)",
2160 g_currentloc);
2162 return sRef_undefined;
2164 else
2166 if (cstring_equalLit (s, "result"))
2168 if (optgenerror
2169 (FLG_SYNTAX,
2170 message ("Special clause list uses %s which is a variable and has special "
2171 "meaning in a modifies list. (Special meaning assumed.)", s),
2172 g_currentloc))
2174 uentry_showWhereDeclared (ue);
2178 return uentry_getSref (ue);
2181 /*drl:1/19/2001
2182 oops to 1/8/2000
2183 date is wronge ..
2184 don;t know what the real date is...
2188 /*drl
2189 added 1/8/2000
2190 based on checkSpecClausesId
2191 called by grammar
2194 sRef checkbufferConstraintClausesId (uentry ue)
2196 sRef sr;
2197 cstring s = uentry_rawName (ue);
2199 if (cstring_equalLit (s, "result"))
2201 if (optgenerror
2202 (FLG_SYNTAX,
2203 message ("Function clause list uses %s which is a variable and has special "
2204 "meaning in a modifies list. (Special meaning assumed.)", s),
2205 g_currentloc))
2207 uentry_showWhereDeclared (ue);
2211 sr = uentry_getSref (ue);
2213 if (sRef_isInvalid (sr))
2215 llfatalerrorLoc (cstring_makeLiteral ("Macro defined constants can not be used in function "
2216 "constraints unless they are specifed with the constant "
2217 "annotation. To use a macro defined constant include an "
2218 "annotation of the form /*@constant <type> <name>=<value>@*/ "
2219 "somewhere before the function constraint. This restriction "
2220 "may be removed in future releases."));
2223 /* saveCopy to used to mitigate danger of accessing freed memory*/
2224 return sRef_saveCopy (sr);
2227 void checkModifiesId (uentry ue)
2229 cstring s = uentry_rawName (ue);
2231 if (cstring_equalLit (s, "nothing")
2232 || cstring_equalLit (s, "internalState")
2233 || cstring_equalLit (s, "systemState")
2234 || (cstring_equalLit (s, "fileSystem")))
2236 if (optgenerror
2237 (FLG_SYNTAX,
2238 message ("Modifies list uses %s which is a variable and has special "
2239 "meaning in a modifies list. (Special meaning assumed.)", s),
2240 g_currentloc))
2242 uentry_showWhereDeclared (ue);
2247 /*@exposed@*/ sRef fixModifiesId (cstring s)
2249 sRef ret;
2250 cstring pname = makeParam (s);
2251 uentry ue = usymtab_lookupSafe (pname);
2253 cstring_free (pname);
2255 if (cstring_equalLit (s, "nothing"))
2257 ret = sRef_makeNothing ();
2259 else if (cstring_equalLit (s, "internalState"))
2261 ret = sRef_makeInternalState ();
2263 else if (cstring_equalLit (s, "fileSystem")
2264 || cstring_equalLit (s, "systemState"))
2266 ret = sRef_makeSystemState ();
2268 else
2270 ret = sRef_undefined;
2273 if (sRef_isValid (ret))
2275 if (uentry_isValid (ue))
2277 voptgenerror
2278 (FLG_SYNTAX,
2279 message ("Modifies list uses %s which is a parameter and has special "
2280 "meaning in a modifies list. (Special meaning assumed.)", s),
2281 g_currentloc);
2284 else
2286 if (uentry_isValid (ue))
2288 ret = uentry_getSref (ue);
2290 else
2292 fileloc loc = fileloc_decColumn (g_currentloc, size_toInt (cstring_length (s)));
2293 ret = sRef_undefined;
2295 voptgenerror
2296 (FLG_UNRECOG,
2297 message ("Unrecognized identifier in modifies comment: %s", s),
2298 loc);
2300 fileloc_free (loc);
2304 return ret;
2307 sRef fixStateClausesId (cstring s)
2309 sRef ret;
2310 cstring pname = makeParam (s);
2311 uentry ue = usymtab_lookupSafe (pname);
2313 cstring_free (pname);
2315 if (cstring_equalLit (s, "result"))
2317 ret = sRef_makeResult (ctype_unknown);
2319 else
2321 ret = sRef_undefined;
2324 if (sRef_isValid (ret))
2326 if (uentry_isValid (ue))
2328 voptgenerror
2329 (FLG_SYNTAX,
2330 message ("Function clause uses %s which is a parameter and has special "
2331 "meaning in a function clause. (Special meaning assumed.)", s),
2332 g_currentloc);
2335 else
2337 if (uentry_isValid (ue))
2339 ret = uentry_getSref (ue);
2341 if (sRef_isFileOrGlobalScope (ret))
2343 voptgenerror
2344 (FLG_SYNTAX,
2345 message ("Global variable %s used in function clause. (Global variables "
2346 "are not recognized in function clauses. If there is "
2347 "sufficient interest in support for this, it may be "
2348 "added to a future release. Send mail to "
2349 "info@splint.org.)",
2350 s),
2351 g_currentloc);
2353 ret = sRef_undefined;
2356 else
2359 /* drl This is the code for structure invariants
2361 It is no yet stable enough to be included in a Splint release.
2364 /*check that we're in a structure */
2365 #if 0
2366 /*@unused@*/ uentryList ueL;
2367 /*@unused@*/ uentry ue2;
2368 /*@unused@*/ ctype ct;
2369 #endif
2370 fileloc loc = fileloc_decColumn (g_currentloc, size_toInt (cstring_length (s)));
2371 ret = sRef_undefined;
2372 # if 0
2374 ct = context_getLastStruct ( ct );
2376 llassert( ctype_isStruct(ct) );
2378 ueL = ctype_getFields (ct);
2380 ue2 = uentryList_lookupField (ueL, s);
2382 if (!uentry_isUndefined(ue2) )
2384 ret = uentry_getSref(ue2);
2386 DPRINTF((
2387 message("Got field in structure in the annotation constraint: %s (or sref: %s)", s, sRef_unparse(ret) )
2390 return ret;
2393 #endif
2395 voptgenerror
2396 (FLG_UNRECOG,
2397 message ("Unrecognized identifier in function clause: %s", s),
2398 loc);
2400 fileloc_free (loc);
2404 return ret;
2407 sRef modListArrayFetch (/*@exposed@*/ sRef s, /*@unused@*/ sRef mexp)
2409 ctype ct = sRef_getType (s);
2410 ctype rt = ctype_realType (ct);
2412 if (ctype_isAP (rt))
2414 if (context_inHeader () && ctype_isAbstract (ct))
2416 voptgenerror
2417 (FLG_ABSTRACT,
2418 message
2419 ("Modifies clause in header file indexes abstract "
2420 "type %s (interface modifies clause should not depend "
2421 "on or expose type representation): %q",
2422 ctype_unparse (ct),
2423 sRef_unparse (s)),
2424 g_currentloc);
2427 return (sRef_makeAnyArrayFetch (s));
2429 else
2431 voptgenerror
2432 (FLG_TYPE,
2433 message
2434 ("Implementation modifies clause uses array fetch on non-array (type %s): %q",
2435 ctype_unparse (ct), sRef_unparse (s)),
2436 g_currentloc);
2437 return s;
2441 static void clabstract_prepareFunction (uentry e)
2443 uentry_checkParams (e);
2444 DPRINTF (("After prepare: %s", uentry_unparseFull (e)));
2447 sRef clabstract_checkGlobal (exprNode e)
2449 sRef s;
2450 llassert (exprNode_isInitializer (e));
2452 s = exprNode_getSref (e);
2453 DPRINTF (("Initializer: %s -> %s", exprNode_unparse (e), sRef_unparse (s)));
2455 exprNode_free (e);
2456 return sRef_copy (s);