2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2002 University of Virginia,
4 ** Massachusetts Institute of Technology
6 ** This program is free software; you can redistribute it and/or modify it
7 ** under the terms of the GNU General Public License as published by the
8 ** Free Software Foundation; either version 2 of the License, or (at your
9 ** option) any later version.
11 ** This program is distributed in the hope that it will be useful, but
12 ** WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 ** General Public License for more details.
16 ** The GNU General Public License is available from http://www.gnu.org/ or
17 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 ** MA 02111-1307, USA.
20 ** For information on splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
31 # include "splintMacros.nf"
33 # include "cgrammar.h"
36 # include "usymtab_interface.h"
39 # include "structNames.h"
40 # include "nameChecks.h"
43 # include "sgrammar_tokens.h"
45 # include "cgrammar_tokens.h"
49 ** Lots of variables are needed because of interactions with the
50 ** parser. This is easier than restructuring the grammar so the
51 ** right values are available in the right place.
55 static /*@only@*/ constraintList implicitFcnConstraints = NULL;
57 static void clabstract_prepareFunction (uentry p_e) /*@modifies p_e@*/ ;
58 static bool fcnNoGlobals = FALSE;
59 static void processVariable (/*@temp@*/ idDecl p_t) /*@modifies internalState@*/ ;
61 static bool s_processingVars = FALSE;
62 static bool s_processingParams = FALSE;
63 static bool s_processingGlobals = FALSE;
64 static bool s_processingTypedef = FALSE;
65 static bool s_processingIterVars = FALSE;
66 static /*@only@*/ qtype processingType = qtype_undefined;
67 static uentry currentIter = uentry_undefined;
68 static /*@dependent@*/ uentryList saveParamList; /* for old style functions */
69 static /*@owned@*/ uentry saveFunction = uentry_undefined;
70 static int saveIterParamNo;
71 static idDecl fixStructDecl (/*@returned@*/ idDecl p_d);
72 static void checkTypeDecl (uentry p_e, ctype p_rep);
73 static /*@dependent@*/ fileloc saveStoreLoc = fileloc_undefined;
74 static storageClassCode storageClass = SCNONE;
75 static void declareEnumList (/*@temp@*/ enumNameList p_el, ctype p_c, fileloc p_loc);
76 static void resetGlobals (void);
77 static /*@null@*/ qual specialFunctionCode;
78 static bool argsUsed = FALSE;
80 extern void clabstract_initMod ()
82 specialFunctionCode = qual_createUnknown ();
83 DPRINTF (("Initialized: %s", qual_unparse (specialFunctionCode)));
86 static bool hasSpecialCode (void)
88 return (!qual_isUnknown (specialFunctionCode));
91 extern void setArgsUsed (void)
97 cstring_makeLiteral ("Multiple ARGSUSED comments for one function"),
104 static void reflectArgsUsed (uentry ue)
108 if (uentry_isFunction (ue))
110 uentryList params = uentry_getParams (ue);
112 uentryList_elements (params, el)
114 uentry_setUsed (el, fileloc_undefined);
115 } end_uentryList_elements ;
122 extern void setSpecialFunction (qual qu)
124 if (!qual_isUnknown (specialFunctionCode))
126 voptgenerror (FLG_SYNTAX,
127 message ("Multiple special function codes: %s, %s "
128 "(first code is ignored)",
129 qual_unparse (specialFunctionCode),
134 specialFunctionCode = qu;
137 static void reflectSpecialCode (uentry ue)
139 if (qual_isUnknown (specialFunctionCode)) {
141 } else if (qual_isPrintfLike (specialFunctionCode)) {
142 uentry_setPrintfLike (ue);
143 } else if (qual_isScanfLike (specialFunctionCode)) {
144 uentry_setScanfLike (ue);
145 } else if (qual_isMessageLike (specialFunctionCode)) {
146 uentry_setMessageLike (ue);
151 specialFunctionCode = qual_createUnknown ();
154 static void resetStorageClass (void)
156 qtype_free (processingType);
157 processingType = qtype_undefined;
158 storageClass = SCNONE;
161 static void reflectStorageClass (uentry u)
163 if (storageClass == SCSTATIC)
165 uentry_setStatic (u);
167 else if (storageClass == SCEXTERN)
169 uentry_setExtern (u);
173 ; /* no storage class */
180 saveStoreLoc = g_currentloc;
183 void setFunctionNoGlobals (void)
188 static void reflectGlobalQualifiers (sRef sr, qualList quals)
190 DPRINTF (("Reflect global qualifiers: %s / %s",
191 sRef_unparseFull (sr), qualList_unparse (quals)));
193 qualList_elements (quals, qel)
195 if (qual_isGlobalQual (qel)) /* undef, killed */
197 sstate oldstate = sRef_getDefState (sr);
198 sstate defstate = sstate_fromQual (qel);
200 if ((oldstate == SS_UNDEFGLOB && defstate == SS_KILLED)
201 || (oldstate == SS_KILLED && defstate == SS_UNDEFGLOB))
203 defstate = SS_UNDEFKILLED;
210 sRef_setDefState (sr, defstate, fileloc_undefined);
211 DPRINTF (("State: %s", sRef_unparseFull (sr)));
213 else if (qual_isAllocQual (qel)) /* out, partial, reldef, etc. */
215 ctype realType = sRef_getType (sr);
216 sstate defstate = sstate_fromQual (qel);
218 if (qual_isRelDef (qel))
220 ; /* okay anywhere */
224 if (!ctype_isAP (realType)
225 && !ctype_isSU (realType)
226 && !ctype_isUnknown (realType)
227 && !ctype_isAbstract (sRef_getType (sr)))
231 message ("Qualifier %s used on non-pointer or struct: %q",
232 qual_unparse (qel), sRef_unparse (sr)));
237 sRef_setDefState (sr, defstate, fileloc_undefined);
239 else if (qual_isNull (qel))
241 sRef_setNullState (sr, NS_POSNULL, fileloc_undefined);
243 else if (qual_isRelNull (qel))
245 sRef_setNullState (sr, NS_RELNULL, fileloc_undefined);
247 else if (qual_isNotNull (qel))
249 sRef_setNullState (sr, NS_MNOTNULL, fileloc_undefined);
253 if (qual_isCQual (qel))
260 message ("Qualifier %s cannot be used in a globals list",
261 qual_unparse (qel)));
264 } end_qualList_elements;
267 sRef clabstract_createGlobal (sRef sr, qualList quals)
271 if (sRef_isValid (sr))
273 res = sRef_copy (sr);
274 DPRINTF (("Reflecting quals: %s / %s", sRef_unparse (sr), qualList_unparse (quals)));
275 reflectGlobalQualifiers (res, quals);
276 DPRINTF (("==> %s", sRef_unparseFull (res)));
280 res = sRef_undefined;
283 qualList_free (quals);
287 extern void declareCIter (cstring name, /*@owned@*/ uentryList params)
291 ue = uentry_makeIter (name,
292 ctype_makeFunction (ctype_void, params),
293 fileloc_copy (g_currentloc));
295 usymtab_supEntry (uentry_makeEndIter (name, fileloc_copy (g_currentloc)));
296 ue = usymtab_supGlobalEntryReturn (ue);
299 extern void nextIterParam (void)
301 llassert (s_processingIterVars);
305 extern int iterParamNo (void)
307 llassert (s_processingIterVars);
308 return saveIterParamNo;
312 ** yucky hacks to put it in the right place
316 makeCurrentParam (idDecl t)
320 saveStoreLoc = fileloc_undefined;
322 /* param number unknown */
324 ue = uentry_makeParam (t, 0);
329 declareUnnamedEnum (enumNameList el)
331 ctype ret = usymtab_enumEnumNameListType (el);
335 if (ctype_isDefined (ret))
338 e = uentry_makeEnumTagLoc (ctype_enumTag (rt), ret);
340 reflectStorageClass (e);
341 usymtab_supGlobalEntry (e);
343 declareEnumList (el, ret, g_currentloc);
344 enumNameList_free (el);
348 ctype ct = ctype_createEnum (fakeTag (), el);
350 e = uentry_makeEnumTagLoc (ctype_enumTag (ctype_realType (ct)), ct);
351 reflectStorageClass (e);
353 e = usymtab_supGlobalEntryReturn (e);
354 rt = uentry_getAbstractType (e);
355 declareEnumList (el, ct, g_currentloc);
362 declareEnum (cstring ename, enumNameList el)
367 llassert (cstring_isDefined (ename));
369 cet = ctype_createEnum (ename, el);
370 e = uentry_makeEnumTagLoc (ename, cet);
371 reflectStorageClass (e);
372 e = usymtab_supGlobalEntryReturn (e);
373 cet = uentry_getType (e);
374 declareEnumList (el, cet, uentry_whereLast (e));
375 return (uentry_getAbstractType (e));
379 declareEnumList (enumNameList el, ctype c, fileloc loc)
381 bool boolnames = FALSE;
382 bool othernames = FALSE;
384 (void) context_getSaveLocation (); /* undefine it */
386 if (context_maybeSet (FLG_NUMENUMMEMBERS))
388 int maxnum = context_getValue (FLG_NUMENUMMEMBERS);
389 int num = enumNameList_size (el);
395 message ("Enumerator %s declared with %d members (limit is set to %d)",
396 ctype_unparse (c), num, maxnum),
401 enumNameList_elements (el, e)
403 uentry ue = usymtab_lookupExposeGlob (e);
404 ctype ct = uentry_getType (ue);
406 llassert (uentry_isEnumConstant (ue));
408 if (ctype_isUnknown (ct))
410 uentry_setType (ue, c);
414 if (cstring_equal (e, context_getFalseName ())
415 || cstring_equal (e, context_getTrueName ()))
421 message ("Enumerator mixes boolean name (%s) with "
424 uentry_whereLast (ue)))
431 uentry_setType (ue, ctype_bool);
432 DPRINTF (("Set type: %s / %s",
433 uentry_unparse (ue), ctype_unparse (ctype_bool)));
441 message ("Enumerator mixes boolean names (%s, %s) with "
442 "non-boolean name: %s",
443 context_getTrueName (),
444 context_getFalseName (),
446 uentry_whereLast (ue)))
455 if (!ctype_match (c, ct))
457 if (ctype_isDirectBool (ct))
459 if (cstring_equal (e, context_getFalseName ())
460 || cstring_equal (e, context_getTrueName ()))
462 DPRINTF (("Here we are!"));
468 message ("Enumerator member %s declared with "
469 "inconsistent type: %s",
470 e, ctype_unparse (c)),
471 uentry_whereLast (ue)))
473 uentry_showWhereSpecifiedExtra
474 (ue, cstring_copy (ctype_unparse (ct)));
482 message ("Enumerator member %s declared with "
483 "inconsistent type: %s",
484 e, ctype_unparse (c)),
485 uentry_whereLast (ue)))
487 uentry_showWhereSpecifiedExtra
488 (ue, cstring_copy (ctype_unparse (ct)));
493 } end_enumNameList_elements;
496 static /*@dependent@*/ uentryList currentParamList;
498 /*drl added 3-28-2002*/
499 /* this function takes a list of paramentar and generates a list
501 Currently the only constraints gnerated are MaxSet(p) >= 0 for all pointers
504 void setImplictfcnConstraints (void)
509 params = currentParamList;
511 if (constraintList_isDefined(implicitFcnConstraints) )
512 constraintList_free(implicitFcnConstraints);
514 implicitFcnConstraints = constraintList_makeNew();
516 uentryList_elements (params, el)
518 DPRINTF((message("setImplictfcnConstraints doing: %s", uentry_unparse(el) ) ));
520 s = uentry_getSref(el);
521 if (sRef_isReference (s) )
523 DPRINTF((message ("%s is a pointer", sRef_unparse(s) ) ));
527 DPRINTF((message ("%s is NOT a pointer", sRef_unparse(s) ) ));
530 chagned this is MaxSet(s) == 0 to MaxSet(s) >= 0 */
532 c = constraint_makeSRefWriteSafeInt (s, 0);
533 /* constraint_makeSRefSetBufferSize (s, 0); */
534 implicitFcnConstraints = constraintList_add(implicitFcnConstraints , c);
536 end_uentryList_elements;
540 /*@observer@*/ constraintList getImplicitFcnConstraints (void)
542 return implicitFcnConstraints;
545 void setCurrentParams (/*@dependent@*/ uentryList ue)
547 currentParamList = ue;
550 void clearCurrentParams (void)
552 currentParamList = uentryList_undefined;
556 ** requires: uentry_isFunction (e)
557 ** parameter names for current function are in currentParamList
560 static void enterFunctionParams (uentryList params)
564 uentryList_elements (params, current)
566 if (uentry_hasName (current))
568 uentry_setParamNo (current, paramno);
569 usymtab_supEntry (uentry_copy (current));
573 } end_uentryList_elements;
577 extern void enterParamsTemp (void)
579 usymtab_enterScope ();
580 enterFunctionParams (currentParamList);
583 extern void exitParamsTemp (void)
585 usymtab_quietPlainExitScope ();
588 static /*@exposed@*/ uentry clabstract_globalDeclareFunction (idDecl tid)
590 ctype deftype = idDecl_getCtype (tid);
594 DPRINTF (("Global function: %s", idDecl_unparse (tid)));
596 if (ctype_isFunction (deftype))
598 rettype = ctype_getReturnType (deftype);
602 rettype = ctype_unknown;
606 ** check has been moved here...
609 if (ctype_isFunction (idDecl_getCtype (tid)))
611 ue = uentry_makeIdFunction (tid);
612 reflectSpecialCode (ue);
613 reflectArgsUsed (ue);
614 reflectStorageClass (ue);
615 uentry_checkParams (ue);
617 DPRINTF (("Supercede function: %s", uentry_unparseFull (ue)));
619 ue = usymtab_supGlobalEntryReturn (ue);
620 DPRINTF (("After supercede function: %s", uentry_unparseFull (ue)));
622 DPRINTF (("Enter function: %s", uentry_unparseFull (ue)));
623 context_enterFunction (ue);
624 enterFunctionParams (uentry_getParams (ue));
626 resetStorageClass ();
627 DPRINTF (("Function: %s", uentry_unparseFull (ue)));
632 llparseerror (message ("Non-function declaration: %q",
633 idDecl_unparse (tid)));
634 return (uentry_undefined);
639 ** for now, no type checking
640 ** (must check later though!)
643 static /*@only@*/ uentry globalDeclareOldStyleFunction (idDecl tid)
648 ** check has been moved here...
651 if (cstring_equalLit (idDecl_observeId (tid), "main"))
653 context_setFlagTemp (FLG_MAINTYPE, FALSE);
656 ue = uentry_makeIdFunction (tid);
657 reflectStorageClass (ue);
658 reflectSpecialCode (ue);
659 reflectArgsUsed (ue);
660 uentry_setDefined (ue, g_currentloc);
661 uentry_checkParams (ue);
662 resetStorageClass ();
664 /* context_enterOldStyleScope (); */
669 static void oldStyleDeclareFunction (/*@only@*/ uentry e)
671 uentryList params = saveParamList;
672 ctype rt = uentry_getType (e);
674 llassert (ctype_isFunction (rt));
676 if (uentry_hasStateClauseList (e)
677 || uentry_hasConditions (e))
679 llfatalerror (message ("%q: Old-style function declaration uses a clause (rewrite with function parameters): %q",
680 fileloc_unparse (g_currentloc), uentry_unparse (e)));
683 e = usymtab_supGlobalEntryReturn (e);
685 context_enterFunction (e);
686 enterFunctionParams (params);
687 saveParamList = uentryList_undefined;
688 resetStorageClass ();
691 static void oldStyleCompleteFunction (/*@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_completeOldStyleFunction (e);
708 enterFunctionParams (params);
709 saveParamList = uentryList_undefined;
710 resetStorageClass ();
713 void clabstract_declareFunction (idDecl tid) /*@globals undef saveFunction; @*/
717 DPRINTF (("Declare function: %s", idDecl_unparse (tid)));
719 if (ctype_isUnknown (idDecl_getCtype (tid)))
722 ** No type, its really a plain name (int) declaration
725 voptgenerror (FLG_IMPTYPE,
726 message ("No type before declaration name (implicit int type): %q",
727 idDecl_unparse (tid)),
729 tid = idDecl_replaceCtype (tid, ctype_int);
730 processVariable (tid);
731 saveFunction = uentry_undefined;
735 if (s_processingParams)
737 ue = globalDeclareOldStyleFunction (tid);
739 DPRINTF (("Set save function: %s", uentry_unparseFull (ue)));
743 saveFunction = uentry_undefined;
745 if (context_inRealFunction ())
747 ue = uentry_makeVariableLoc (idDecl_observeId (tid), ctype_unknown);
749 llparseerror (message ("Function declared inside function: %q",
750 idDecl_unparse (tid)));
752 context_quietExitFunction ();
753 ue = usymtab_supEntryReturn (ue);
757 if (context_inInnerScope ())
759 llparseerror (message ("Declaration in inner context: %q",
760 idDecl_unparse (tid)));
762 sRef_setGlobalScope ();
763 ue = uentry_makeVariableLoc (idDecl_observeId (tid),
765 ue = usymtab_supGlobalEntryReturn (ue);
766 sRef_clearGlobalScope ();
770 ue = clabstract_globalDeclareFunction (tid);
777 resetStorageClass ();
783 void declareStaticFunction (idDecl tid) /*@globals undef saveFunction; @*/
787 DPRINTF (("Declare static funciton: %s", idDecl_unparse (tid)));
789 if (s_processingParams)
791 ue = globalDeclareOldStyleFunction (tid);
796 saveFunction = uentry_undefined;
798 if (context_inRealFunction ())
800 ue = uentry_makeVariableLoc (idDecl_observeId (tid), ctype_unknown);
802 llparseerror (message ("Function declared inside function: %q",
803 idDecl_unparse (tid)));
805 context_quietExitFunction ();
806 ue = usymtab_supEntryReturn (ue);
810 if (context_inInnerScope ())
812 llparseerror (message ("Declaration in inner context: %q",
813 idDecl_unparse (tid)));
815 sRef_setGlobalScope ();
816 ue = uentry_makeVariableLoc (idDecl_observeId (tid),
818 ue = usymtab_supGlobalEntryReturn (ue);
819 sRef_clearGlobalScope ();
823 ctype deftype = idDecl_getCtype (tid);
826 if (ctype_isFunction (deftype))
828 rettype = ctype_getReturnType (deftype);
832 rettype = ctype_unknown;
836 ** check has been moved here...
839 if (ctype_isFunction (idDecl_getCtype (tid)))
841 ue = uentry_makeIdFunction (tid);
842 reflectSpecialCode (ue);
843 reflectArgsUsed (ue);
847 DPRINTF (("Here we are!"));
848 llparseerror (message ("Inconsistent function declaration: %q",
849 idDecl_unparse (tid)));
851 tid = idDecl_replaceCtype
852 (tid, ctype_makeFunction (ctype_unknown, uentryList_undefined));
853 ue = uentry_makeIdFunction (tid);
856 reflectStorageClass (ue);
857 uentry_setStatic (ue);
859 uentry_checkParams (ue);
861 DPRINTF (("Sub global entry: %s", uentry_unparse (ue)));
862 ue = usymtab_supGlobalEntryReturn (ue);
864 context_enterFunction (ue);
865 enterFunctionParams (uentry_getParams (ue));
866 resetStorageClass ();
873 resetStorageClass ();
878 checkTypeDecl (uentry e, ctype rep)
880 cstring n = uentry_getName (e);
882 DPRINTF (("Check type decl: %s", uentry_unparseFull (e)));
884 if (cstring_equal (context_getBoolName (), n))
886 ctype rrep = ctype_realType (rep);
889 ** for abstract enum types, we need to fix the enum members:
890 ** they should have the abstract type, not the rep type.
893 if (ctype_isEnum (ctype_realType (rrep)))
895 enumNameList el = ctype_elist (rrep);
897 enumNameList_elements (el, ye)
899 if (usymtab_existsGlob (ye))
901 uentry ue = usymtab_lookupSafe (ye);
902 uentry_setType (ue, ctype_bool);
905 if (cstring_equal (context_getTrueName (), ye)
906 || cstring_equal (context_getFalseName (), ye))
914 message ("Member of boolean enumerated type definition "
915 "does not match name set to represent TRUE "
918 message ("Use -boolfalse and -booltrue to set the "
919 "name of false and true boolean values."),
920 uentry_whereDefined (e));
922 } end_enumNameList_elements;
926 if (usymtab_exists (n))
928 usymId llm = usymtab_getId (n);
929 uentry le = usymtab_getTypeEntry (llm);
931 uentry_setDeclared (e, g_currentloc);
932 uentry_setSref (e, sRef_makeGlobal (llm, uentry_getType (le), stateInfo_currentLoc ()));
934 DPRINTF (("Here we are: %s / %s",
935 n, context_getBoolName ()));
937 if (uentry_isAbstractDatatype (le))
939 ctype rrep = ctype_realType (rep);
941 DPRINTF (("Abstract type: %s", uentry_unparseFull (le)));
944 ** for abstract enum types, we need to fix the enum members:
945 ** they should have the abstract type, not the rep type.
948 if (ctype_isEnum (ctype_realType (rrep)))
950 ctype at = uentry_getAbstractType (le);
951 enumNameList el = ctype_elist (rrep);
953 enumNameList_elements (el, ye)
955 if (usymtab_existsGlob (ye))
957 uentry ue = usymtab_lookupSafe (ye);
959 llassert (uentry_isEitherConstant (ue));
961 /* evans 2002-04-22 */
962 if (ctype_isBool (uentry_getType (ue)))
965 ** If set using -booltrue or -boolfalse, don't change the type.
970 llassertprint (ctype_match (uentry_getType (ue), rrep),
971 ("Bad enum: %s / %s",
973 ctype_unparse (rrep)));
975 uentry_setType (ue, at);
978 } end_enumNameList_elements;
981 if (uentry_isMutableDatatype (le))
983 /* maybe more complicated if abstract and immutable ? */
985 if (!ctype_isRealPointer (rep) && !ctype_isRealAbstract (rep))
989 message ("Mutable abstract type %s declared without pointer "
990 "indirection: %s (violates assignment semantics)",
991 n, ctype_unparse (rep)),
992 uentry_whereDefined (e));
994 uentry_setMutable (e);
1001 fileloc fl = uentry_whereDeclared (e);
1003 if (context_getFlag (FLG_LIKELYBOOL)
1004 && !context_getFlag (FLG_BOOLINT))
1006 if ((cstring_equalLit (n, "BOOL")
1007 || cstring_equalLit (n, "Bool")
1008 || cstring_equalLit (n, "bool")
1009 || cstring_equalLit (n, "boolean")
1010 || cstring_equalLit (n, "Boolean")
1011 || cstring_equalLit (n, "BOOLEAN"))
1012 && !(cstring_equal (n, context_getBoolName ())))
1014 if (context_setBoolName ()) {
1017 message ("Type %s is probably meant as a boolean type, but does "
1018 "not match the boolean type name \"%s\".",
1020 context_getBoolName ()),
1025 message ("Type %s is probably meant as a boolean type, "
1026 "but the boolean type name is not set. "
1027 "Use -booltype %s to set it.",
1034 if (!uentry_isStatic (e)
1035 && !ctype_isFunction (uentry_getType (e))
1036 && !fileloc_isLib (fl)
1037 && !fileloc_isImport (fl)
1038 && fileloc_isHeader (fl))
1040 voptgenerror (FLG_EXPORTTYPE,
1041 message ("Type exported, but not specified: %s\n", n),
1050 fixUentryList (idDeclList tl, qtype q)
1052 uentryList f = uentryList_new ();
1054 idDeclList_elements (tl, i)
1056 if (idDecl_isDefined (i))
1062 (void) idDecl_fixBase (i, q);
1065 ** implicit annotations
1068 (void) fixStructDecl (i);
1070 ue = uentry_makeIdVariable (i);
1071 rt = ctype_realType (uentry_getType (ue));
1074 ** where is this here???
1076 if (ctype_isArray (rt) || ctype_isSU (rt))
1078 sRef_setAllocated (uentry_getSref (ue), uentry_whereDefined (ue));
1084 if (uentry_isValid (old = uentryList_lookupField (f, uentry_rawName (ue))))
1086 if (optgenerror (FLG_SYNTAX,
1087 message ("Field name reused: %s", uentry_rawName (ue)),
1088 uentry_whereDefined (ue)))
1090 llgenmsg (message ("Previous use of %s", uentry_rawName (ue)),
1091 uentry_whereDefined (old));
1095 f = uentryList_add (f, ue);
1097 } end_idDeclList_elements;
1099 idDeclList_free (tl);
1104 ** This is a hack to support unnamed struct/union fields as done by
1105 ** Microsoft VC++. It is not supported by the ANSI standard.
1107 ** The inner fields are added to the outer structure. This is meaningful
1108 ** for nesting structs inside unions, but Splint does no related
1113 fixUnnamedDecl (qtype q)
1115 ctype ct = ctype_realType (qtype_getType (q));
1117 if (ctype_isStruct (ct) || ctype_isUnion (ct))
1119 return uentryList_single (uentry_makeUnnamedVariable (ct));
1121 else if (ctype_isEnum (ct))
1123 /* evans 2002-02-05: nothing to do for unnamed enum lists */
1124 return uentryList_undefined;
1130 message ("Type name in field declarations: %s", qtype_unparse (q)),
1134 return uentryList_undefined;
1137 void setStorageClass (storageClassCode sc)
1143 setProcessingIterVars (uentry iter)
1145 s_processingIterVars = TRUE;
1147 saveIterParamNo = 0;
1151 setProcessingGlobalsList ()
1153 s_processingGlobals = TRUE;
1154 fcnNoGlobals = FALSE;
1157 static bool ProcessingGlobMods = FALSE;
1160 setProcessingGlobMods ()
1162 ProcessingGlobMods = TRUE;
1166 clearProcessingGlobMods ()
1168 ProcessingGlobMods = FALSE;
1172 isProcessingGlobMods ()
1174 return (ProcessingGlobMods);
1177 static void resetGlobals (void)
1179 s_processingGlobals = FALSE;
1180 fcnNoGlobals = FALSE;
1184 unsetProcessingGlobals ()
1186 s_processingGlobals = FALSE;
1190 setProcessingVars (/*@only@*/ qtype q)
1192 s_processingVars = TRUE;
1193 qtype_free (processingType);
1198 setGenericParamList (/*@dependent@*/ uentryList pm)
1200 s_processingParams = TRUE;
1205 setProcessingTypedef (qtype q)
1207 s_processingTypedef = TRUE;
1209 qtype_free (processingType);
1214 unsetProcessingVars ()
1216 resetStorageClass ();
1217 s_processingVars = FALSE;
1221 oldStyleDoneParams ()
1223 if (s_processingParams)
1225 if (uentry_isInvalid (saveFunction))
1227 llbuglit ("unsetProcessingVars: no saved function\n");
1231 ctype ct = ctype_getReturnType (uentry_getType (saveFunction));
1232 uentryList params = uentryList_copy (saveParamList);
1233 ctype ct2 = ctype_makeFunction (ct, params);
1235 uentry_setType (saveFunction, ct2);
1236 s_processingParams = FALSE;
1238 oldStyleCompleteFunction (saveFunction);
1239 saveFunction = uentry_undefined;
1246 ** If the paramlist used a type name, we could be here.
1249 llfatalerror (message ("%q: Old-style function parameter list uses a "
1250 "type name.", fileloc_unparse (g_currentloc)));
1257 if (uentry_isValid (saveFunction))
1260 ** old style declaration
1263 ctype ct = ctype_getReturnType (uentry_getType (saveFunction));
1266 DPRINTF (("save function: %s", uentry_unparseFull (saveFunction)));
1268 uentryList_elements (saveParamList, current)
1270 uentry_setType (current, ctype_int); /* all params are ints */
1271 } end_uentryList_elements;
1273 ct2 = ctype_makeParamsFunction (ct, uentryList_copy (saveParamList));
1275 uentry_setType (saveFunction, ct2);
1276 s_processingParams = FALSE;
1278 oldStyleDeclareFunction (saveFunction);
1279 saveFunction = uentry_undefined;
1283 void clabstract_declareType (/*@only@*/ exprNodeList decls, /*@only@*/ warnClause warn)
1285 llassert (s_processingTypedef);
1287 DPRINTF (("Declare type: %s", exprNodeList_unparse (decls)));
1289 if (warnClause_isDefined (warn))
1291 DPRINTF (("Has a warn clause!"));
1292 DPRINTF (("Warn: %s", warnClause_unparse (warn)));
1294 exprNodeList_elements (decls, el)
1296 uentry ue = exprNode_getUentry (el);
1297 cstring uname = uentry_getName (ue);
1299 DPRINTF (("Entry: %s", exprNode_unparse (el)));
1302 ** Need to lookup again to make sure we have the right one...
1305 ue = usymtab_lookupExposeGlob (uname);
1307 llassert (uentry_isValid (ue));
1308 llassert (uentry_isDatatype (ue));
1310 DPRINTF (("Warning for %s: %s",
1311 uentry_unparse (ue), warnClause_unparse (warn)));
1313 uentry_addWarning (ue, warnClause_copy (warn));
1314 DPRINTF (("After add warning: %s", uentry_unparseFull (ue)));
1315 cstring_free (uname);
1316 } end_exprNodeList_elements;
1319 warnClause_free (warn);
1320 exprNodeList_free (decls);
1321 unsetProcessingTypedef ();
1325 unsetProcessingTypedef ()
1327 s_processingTypedef = FALSE;
1330 void checkConstant (qtype t, idDecl id)
1334 id = idDecl_fixBase (id, t);
1335 e = uentry_makeIdConstant (id);
1337 reflectStorageClass (e);
1338 resetStorageClass ();
1340 DPRINTF (("Constant: %s", uentry_unparseFull (e)));
1341 usymtab_supGlobalEntry (e);
1344 void checkValueConstant (qtype t, idDecl id, exprNode e)
1348 id = idDecl_fixBase (id, t);
1349 ue = uentry_makeIdConstant (id);
1350 reflectStorageClass (ue);
1351 resetStorageClass ();
1353 if (exprNode_isDefined (e))
1355 if (!exprNode_matchType (uentry_getType (ue), e))
1358 (exprNode_getType (e), e,
1359 uentry_getType (ue), exprNode_undefined,
1360 message ("Constant %q initialized to type %t, expects %t: %s",
1361 uentry_getName (ue),
1362 exprNode_getType (e),
1363 uentry_getType (ue),
1364 exprNode_unparse (e)),
1369 if (exprNode_hasValue (e))
1371 uentry_mergeConstantValue (ue, multiVal_copy (exprNode_getValue (e)));
1375 DPRINTF (("No value: %s", exprNode_unparse (e)));
1380 DPRINTF (("Constant value: %s", uentry_unparseFull (ue)));
1381 usymtab_supGlobalEntry (ue);
1384 static void processVariable (idDecl t)
1389 ct = ctype_realType (idDecl_getCtype (t));
1391 if (s_processingParams)
1393 cstring id = idDecl_getName (t);
1394 int paramno = uentryList_lookupRealName (saveParamList, id);
1398 uentry cparam = uentryList_getN (saveParamList, paramno);
1400 DPRINTF (("Processing param: %s", uentry_unparseFull (cparam)));
1401 uentry_setType (cparam, idDecl_getCtype (t));
1402 uentry_reflectQualifiers (cparam, idDecl_getQuals (t));
1403 uentry_setDeclaredOnly (cparam, context_getSaveLocation ());
1404 DPRINTF (("Processing param: %s", uentry_unparseFull (cparam)));
1409 (message ("Old style declaration uses unlisted parameter: %s",
1417 if (context_inIterDef ())
1419 cstring pname = makeParam (idDecl_observeId (t));
1420 uentry p = usymtab_lookupSafe (pname);
1422 cstring_free (pname);
1424 if (uentry_isYield (p))
1426 e = uentry_makeParam (t, sRef_getParam (uentry_getSref (p)));
1427 uentry_checkYieldParam (p, e);
1428 usymtab_supEntrySref (e);
1433 if ((hasSpecialCode () || argsUsed)
1434 && ctype_isFunction (idDecl_getCtype (t)))
1436 e = uentry_makeIdFunction (t);
1437 reflectSpecialCode (e);
1438 reflectArgsUsed (e);
1442 e = uentry_makeIdVariable (t);
1445 loc = uentry_whereDeclared (e);
1448 if (context_inGlobalScope ())
1450 uentry_checkParams was here!
1454 if (ctype_isFunction (uentry_getType (e)))
1456 clabstract_prepareFunction (e);
1459 DPRINTF (("Superceding... %s", uentry_unparseFull (e)));
1460 e = usymtab_supEntrySrefReturn (e);
1461 DPRINTF (("After superceding... %s", uentry_unparseFull (e)));
1463 if (uentry_isExtern (e) && !context_inGlobalScope ())
1467 message ("Declaration using extern inside function scope: %q",
1468 uentry_unparse (e)),
1471 uentry_setDefined (e, fileloc_getExternal ());
1472 sRef_setDefined (uentry_getSref (e), fileloc_getExternal ());
1475 if (uentry_isFunction (e))
1477 if (!context_inXHFile ())
1479 checkParamNames (e);
1483 if (uentry_isVar (e) && uentry_isCheckedUnknown (e))
1485 sRef sr = uentry_getSref (e);
1487 if (sRef_isLocalVar (sr))
1489 if (context_getFlag (FLG_IMPCHECKMODINTERNALS))
1491 uentry_setCheckMod (e);
1495 uentry_setUnchecked (e);
1498 else if (sRef_isFileStatic (sr))
1500 if (context_getFlag (FLG_IMPCHECKEDSTRICTSTATICS))
1502 uentry_setCheckedStrict (e);
1504 else if (context_getFlag (FLG_IMPCHECKEDSTATICS))
1506 uentry_setChecked (e);
1508 else if (context_getFlag (FLG_IMPCHECKMODSTATICS))
1510 uentry_setCheckMod (e);
1517 else /* real global */
1519 llassert (sRef_isRealGlobal (sr));
1521 if (context_getFlag (FLG_IMPCHECKEDSTRICTGLOBALS))
1523 uentry_setCheckedStrict (e);
1525 else if (context_getFlag (FLG_IMPCHECKEDGLOBALS))
1527 uentry_setChecked (e);
1529 else if (context_getFlag (FLG_IMPCHECKMODGLOBALS))
1531 uentry_setCheckMod (e);
1542 void processNamedDecl (idDecl t)
1544 if (qtype_isUndefined (processingType))
1546 processingType = qtype_create (ctype_int);
1547 t = idDecl_fixBase (t, processingType);
1549 voptgenerror (FLG_IMPTYPE,
1550 message ("No type before declaration name (implicit int type): %q",
1551 idDecl_unparse (t)),
1556 t = idDecl_fixBase (t, processingType);
1559 DPRINTF (("Declare: %s", idDecl_unparse (t)));
1561 if (s_processingGlobals)
1563 cstring id = idDecl_getName (t);
1564 uentry ue = usymtab_lookupSafe (id);
1566 if (!uentry_isValid (ue))
1568 llerror (FLG_UNRECOG,
1569 message ("Variable used in globals list is undeclared: %s", id));
1573 if (!ctype_match (uentry_getType (ue), idDecl_getCtype (t)))
1577 message ("Variable %s used in globals list declared %s, "
1579 id, ctype_unparse (uentry_getType (ue)),
1580 ctype_unparse (idDecl_getCtype (t))),
1585 sRef sr = sRef_copy (uentry_getSref (ue));
1586 reflectGlobalQualifiers (sr, idDecl_getQuals (t));
1590 else if (s_processingVars)
1592 processVariable (t);
1594 else if (s_processingTypedef)
1596 ctype ct = idDecl_getCtype (t);
1599 DPRINTF (("Processing typedef: %s", ctype_unparse (ct)));
1601 e = uentry_makeIdDatatype (t);
1603 if (cstring_equal (idDecl_getName (t), context_getBoolName ())) {
1604 ctype rt = ctype_realType (ct);
1606 if (ctype_isEnum (rt)) {
1609 if (!(ctype_isInt (rt)
1610 || ctype_isUnknown (rt)
1611 || ctype_isChar (rt))) {
1614 message ("Boolean type %s defined using non-standard type %s (integral, char or enum type expected)",
1615 context_getBoolName (),
1616 ctype_unparse (ct)),
1617 uentry_whereLast (e));
1621 uentry_setType (e, ct);
1625 reflectStorageClass (e);
1626 checkTypeDecl (e, ct);
1628 e = usymtab_supReturnTypeEntry (e);
1632 llparseerror (message ("Suspect missing struct or union keyword: %q",
1633 idDecl_unparse (t)));
1639 ** moved from grammar
1642 static idDecl fixStructDecl (/*@returned@*/ idDecl d)
1644 if (ctype_isVisiblySharable (idDecl_getCtype (d))
1645 && context_getFlag (FLG_STRUCTIMPONLY))
1647 if (!qualList_hasAliasQualifier (idDecl_getQuals (d)))
1649 if (qualList_hasExposureQualifier (idDecl_getQuals (d)))
1651 idDecl_addQual (d, qual_createDependent ());
1655 idDecl_addQual (d, qual_createImpOnly ());
1664 declareUnnamedStruct (/*@only@*/ uentryList f)
1666 DPRINTF (("Unnamed struct: %s", uentryList_unparse (f)));
1668 if (context_maybeSet (FLG_NUMSTRUCTFIELDS))
1670 int num = uentryList_size (f);
1671 int max = context_getValue (FLG_NUMSTRUCTFIELDS);
1676 (FLG_NUMSTRUCTFIELDS,
1677 message ("Structure declared with %d fields "
1678 "(limit is set to %d)",
1684 return (ctype_createUnnamedStruct (f));
1688 declareUnnamedUnion (/*@only@*/ uentryList f)
1690 DPRINTF (("Unnamed union: %s", uentryList_unparse (f)));
1692 if (context_maybeSet (FLG_NUMSTRUCTFIELDS))
1694 int num = uentryList_size (f);
1695 int max = context_getValue (FLG_NUMSTRUCTFIELDS);
1700 (FLG_NUMSTRUCTFIELDS,
1701 message ("Union declared with %d fields "
1702 "(limit is set to %d)",
1708 return (ctype_createUnnamedUnion (f));
1711 ctype declareStruct (cstring id, /*@only@*/ uentryList f)
1715 int num = uentryList_size (f);
1717 DPRINTF (("Declare struct: %s / %s [%d]", id, uentryList_unparse (f),
1718 uentryList_size (f)));
1720 ct = ctype_createStruct (cstring_copy (id), f);
1722 DPRINTF (("Ctype: %s", ctype_unparse (ct)));
1724 ue = uentry_makeStructTagLoc (id, ct);
1726 DPRINTF (("ue: %s", uentry_unparseFull (ue)));
1728 if (context_maybeSet (FLG_NUMSTRUCTFIELDS))
1730 int max = context_getValue (FLG_NUMSTRUCTFIELDS);
1735 (FLG_NUMSTRUCTFIELDS,
1736 message ("Structure %q declared with %d fields "
1737 "(limit is set to %d)",
1738 uentry_getName (ue), num, max),
1739 uentry_whereLast (ue));
1743 return (usymtab_supTypeEntry (ue));
1746 ctype declareUnion (cstring id, uentryList f)
1750 int num = uentryList_size (f);
1752 ct = ctype_createUnion (cstring_copy (id), f);
1753 ue = uentry_makeUnionTagLoc (id, ct);
1755 if (context_maybeSet (FLG_NUMSTRUCTFIELDS))
1757 int max = context_getValue (FLG_NUMSTRUCTFIELDS);
1762 (FLG_NUMSTRUCTFIELDS,
1763 message ("Union %q declared with %d fields "
1764 "(limit is set to %d)",
1765 uentry_getName (ue), num, max),
1766 uentry_whereLast (ue));
1770 return (usymtab_supTypeEntry (ue));
1773 ctype handleStruct (/*@only@*/ cstring id)
1775 if (usymtab_existsStructTag (id))
1777 ctype ct = uentry_getAbstractType (usymtab_lookupStructTag (id));
1784 return (ctype_createForwardStruct (id));
1788 ctype handleUnion (/*@only@*/ cstring id)
1790 if (usymtab_existsUnionTag (id))
1792 ctype ret = uentry_getAbstractType (usymtab_lookupUnionTag (id));
1798 return (ctype_createForwardUnion (id));
1803 handleEnum (cstring id)
1805 if (usymtab_existsEnumTag (id))
1807 ctype ret = uentry_getAbstractType (usymtab_lookupEnumTag (id));
1813 return (ctype_createForwardEnum (id));
1817 bool processingIterVars (void)
1819 return s_processingIterVars;
1822 uentry getCurrentIter (void)
1827 static bool flipOldStyle = FALSE;
1828 static bool flipNewStyle = TRUE;
1830 void setFlipOldStyle () { flipOldStyle = TRUE; }
1831 bool isFlipOldStyle () { return flipOldStyle; }
1832 bool isNewStyle () { return flipNewStyle; }
1833 void setNewStyle () { flipNewStyle = TRUE; }
1835 /*@dependent@*/ uentryList handleParamIdList (/*@dependent@*/ uentryList params)
1840 ** this is a really YUCKY hack to handle old style
1844 voptgenerror (FLG_OLDSTYLE,
1845 cstring_makeLiteral ("Old style function declaration"),
1848 DPRINTF (("Handle old style params: %s", uentryList_unparseFull (params)));
1850 uentryList_elements (params, current)
1852 uentry_setParam (current);
1853 uentry_setSref (current, sRef_makeParam (paramno, ctype_unknown, stateInfo_makeLoc (uentry_whereLast (current))));
1855 } end_uentryList_elements;
1857 setGenericParamList (params);
1858 g_expectingTypeName = TRUE;
1863 /*@dependent@*/ uentryList handleParamTypeList (/*@returned@*/ uentryList params)
1867 uentryList_fixMissingNames (params);
1869 voptgenerror (FLG_OLDSTYLE,
1870 cstring_makeLiteral ("Old style function declaration."),
1873 setGenericParamList (params);
1874 flipOldStyle = FALSE;
1875 g_expectingTypeName = TRUE;
1884 ctype c = ctype_unknown;
1885 cstring id = cstring_makeLiteral ("va_alist");
1888 if (s_processingParams)
1890 int i = uentryList_lookupRealName (saveParamList, id);
1894 fileloc loc = context_getSaveLocation ();
1895 e = uentry_makeVariableSrefParam (id, c, loc, sRef_makeParam (i, c, stateInfo_makeLoc (loc)));
1899 e = uentry_undefined; /* suppress gcc message */
1900 llfatalerrorLoc (cstring_makeLiteral ("va_dcl used without va_alist"));
1905 llerror (FLG_SYNTAX, cstring_makeLiteral ("va_dcl used outside of function declaration"));
1906 e = uentry_makeVariableLoc (id, c);
1910 uentry_setUsed (e, g_currentloc);
1911 usymtab_supEntrySref (e);
1914 /*@exposed@*/ sRef modListPointer (/*@exposed@*/ sRef s)
1916 ctype ct = sRef_getType (s);
1917 ctype rt = ctype_realType (ct);
1919 if (ctype_isAP (rt))
1921 if (context_inHeader () && ctype_isAbstract (ct))
1926 ("Modifies clause in header file dereferences abstract "
1927 "type %s (interface modifies clause should not depend "
1928 "on or expose type representation): %q",
1934 return (sRef_constructPointer (s));
1938 if (ctype_isKnown (rt))
1942 message ("Implementation modifies clause dereferences non-pointer (type %s): %q",
1952 /*@exposed@*/ sRef modListFieldAccess (sRef s, cstring f)
1954 ctype ct = sRef_getType (s);
1955 ctype rt = ctype_realType (ct);
1957 if (ctype_isStructorUnion (rt))
1959 uentry tf = uentryList_lookupField (ctype_getFields (rt), f);
1961 if (uentry_isUndefined (tf))
1963 voptgenerror (FLG_TYPE,
1964 message ("Modifies list accesses non-existent "
1965 "field %s of %t: %q", f, ct,
1970 return sRef_undefined;
1974 if (ctype_isAbstract (ct) && context_inHeader ())
1979 ("Modifies clause in header file accesses abstract "
1980 "type %s (interface modifies clause should not depend "
1981 "on or expose type representation): %q",
1988 cstring_markOwned (f);
1989 return (sRef_makeField (s, f));
1995 message ("Modifies clause dereferences non-pointer (type %s): %q",
2005 /*@dependent@*/ sRef clabstract_unrecognizedGlobal (cstring s)
2007 if (cstring_equalLit (s, "nothing"))
2009 return sRef_makeNothing ();
2011 else if (cstring_equalLit (s, "internalState"))
2013 return sRef_makeInternalState ();
2015 else if (cstring_equalLit (s, "fileSystem")
2016 || cstring_equalLit (s, "systemState"))
2018 return sRef_makeSystemState ();
2024 message ("Unrecognized identifier in globals list: %s", s),
2027 return sRef_undefined;
2031 /*@exposed@*/ sRef modListArrowAccess (sRef s, cstring f)
2033 ctype ct = sRef_getType (s);
2034 ctype rt = ctype_realType (ct);
2036 if (ctype_isRealPointer (rt))
2038 ctype b = ctype_baseArrayPtr (rt);
2039 ctype rb = ctype_realType (b);
2041 if (ctype_isStructorUnion (rb))
2043 uentry tf = uentryList_lookupField (ctype_getFields (rb), f);
2045 if (uentry_isUndefined (tf))
2047 voptgenerror (FLG_TYPE,
2048 message ("Modifies list arrow accesses non-existent "
2049 "field %s of %t: %q", f, b,
2054 return sRef_undefined;
2058 if (context_inHeader ())
2060 if (ctype_isAbstract (b))
2065 ("Modifies clause in header file arrow accesses abstract "
2066 "type %s (interface modifies clause should not depend "
2067 "on or expose type representation): %q",
2075 if (ctype_isAbstract (rt))
2080 ("Modifies clause arrow accesses inaccessible abstract "
2081 "type %s (interface modifies clause should not depend "
2082 "on or expose type representation): %q",
2090 cstring_markOwned (f);
2091 return (sRef_makeArrow (s, f));
2097 message ("Modifies clause arrow accesses pointer to "
2098 "non-structure (type %s): %q",
2108 message ("Modifies clause arrow accesses non-pointer (type %s): %q",
2118 sRef checkStateClausesId (uentry ue)
2120 cstring s = uentry_rawName (ue);
2122 if (sRef_isFileOrGlobalScope (uentry_getSref (ue)))
2126 message ("Global variable %s used state clause. (Global variables "
2127 "are not recognized in state clauses. If there is "
2128 "sufficient interest in support for this, it may be "
2129 "added to a future release. Send mail to "
2130 "info@splint.org.)",
2134 return sRef_undefined;
2138 if (cstring_equalLit (s, "result"))
2142 message ("Special clause list uses %s which is a variable and has special "
2143 "meaning in a modifies list. (Special meaning assumed.)", s),
2146 uentry_showWhereDeclared (ue);
2150 return uentry_getSref (ue);
2156 don;t know what the real date is...
2162 based on checkSpecClausesId
2166 sRef checkbufferConstraintClausesId (uentry ue)
2168 cstring s = uentry_rawName (ue);
2170 if (cstring_equalLit (s, "result"))
2174 message ("Function clause list uses %s which is a variable and has special "
2175 "meaning in a modifies list. (Special meaning assumed.)", s),
2178 uentry_showWhereDeclared (ue);
2182 DPRINTF (("constrant id: %s", uentry_unparseFull (ue)));
2183 return sRef_saveCopy (uentry_getSref (ue)); /*@i523 why the saveCopy? */
2186 void checkModifiesId (uentry ue)
2188 cstring s = uentry_rawName (ue);
2190 if (cstring_equalLit (s, "nothing")
2191 || cstring_equalLit (s, "internalState")
2192 || cstring_equalLit (s, "systemState")
2193 || (cstring_equalLit (s, "fileSystem")))
2197 message ("Modifies list uses %s which is a variable and has special "
2198 "meaning in a modifies list. (Special meaning assumed.)", s),
2201 uentry_showWhereDeclared (ue);
2206 /*@exposed@*/ sRef fixModifiesId (cstring s)
2209 cstring pname = makeParam (s);
2210 uentry ue = usymtab_lookupSafe (pname);
2212 cstring_free (pname);
2214 if (cstring_equalLit (s, "nothing"))
2216 ret = sRef_makeNothing ();
2218 else if (cstring_equalLit (s, "internalState"))
2220 ret = sRef_makeInternalState ();
2222 else if (cstring_equalLit (s, "fileSystem")
2223 || cstring_equalLit (s, "systemState"))
2225 ret = sRef_makeSystemState ();
2229 ret = sRef_undefined;
2232 if (sRef_isValid (ret))
2234 if (uentry_isValid (ue))
2238 message ("Modifies list uses %s which is a parameter and has special "
2239 "meaning in a modifies list. (Special meaning assumed.)", s),
2245 if (uentry_isValid (ue))
2247 ret = uentry_getSref (ue);
2251 fileloc loc = fileloc_decColumn (g_currentloc, size_toInt (cstring_length (s)));
2252 ret = sRef_undefined;
2256 message ("Unrecognized identifier in modifies comment: %s", s),
2266 sRef fixStateClausesId (cstring s)
2269 cstring pname = makeParam (s);
2270 uentry ue = usymtab_lookupSafe (pname);
2272 cstring_free (pname);
2274 if (cstring_equalLit (s, "result"))
2276 ret = sRef_makeResult (ctype_unknown);
2280 ret = sRef_undefined;
2283 if (sRef_isValid (ret))
2285 if (uentry_isValid (ue))
2289 message ("Function clause uses %s which is a parameter and has special "
2290 "meaning in a function clause. (Special meaning assumed.)", s),
2296 if (uentry_isValid (ue))
2298 ret = uentry_getSref (ue);
2300 if (sRef_isFileOrGlobalScope (ret))
2304 message ("Global variable %s used in function clause. (Global variables "
2305 "are not recognized in function clauses. If there is "
2306 "sufficient interest in support for this, it may be "
2307 "added to a future release. Send mail to "
2308 "info@splint.org.)",
2312 ret = sRef_undefined;
2318 /*drl handle structure invariant */
2321 /*check that we're in a structure */
2323 /*@unused@*/ uentryList ueL;
2324 /*@unused@*/ uentry ue2;
2325 /*@unused@*/ ctype ct;
\r
2327 fileloc loc = fileloc_decColumn (g_currentloc, size_toInt (cstring_length (s)));
2328 ret = sRef_undefined;
2330 /*drl commenting this out for now
2331 ct = context_getLastStruct ( ct );
2333 llassert( ctype_isStruct(ct) );
2335 ueL = ctype_getFields (ct);
2337 ue2 = uentryList_lookupField (ueL, s);
2339 if (!uentry_isUndefined(ue2) )
2341 ret = uentry_getSref(ue2);
2344 message("Got field in structure in the annotation constraint: %s (or sref: %s)", s, sRef_unparse(ret) )
2354 message ("Unrecognized identifier in function clause: %s", s),
2364 sRef modListArrayFetch (/*@exposed@*/ sRef s, /*@unused@*/ sRef mexp)
2366 ctype ct = sRef_getType (s);
2367 ctype rt = ctype_realType (ct);
2369 if (ctype_isAP (rt))
2371 if (context_inHeader () && ctype_isAbstract (ct))
2376 ("Modifies clause in header file indexes abstract "
2377 "type %s (interface modifies clause should not depend "
2378 "on or expose type representation): %q",
2384 return (sRef_makeAnyArrayFetch (s));
2391 ("Implementation modifies clause uses array fetch on non-array (type %s): %q",
2392 ctype_unparse (ct), sRef_unparse (s)),
2398 static void clabstract_prepareFunction (uentry e)
2400 uentry_checkParams (e);
2401 DPRINTF (("After prepare: %s", uentry_unparseFull (e)));
2404 sRef clabstract_checkGlobal (exprNode e)
2407 llassert (exprNode_isInitializer (e));
2409 s = exprNode_getSref (e);
2410 DPRINTF (("Initializer: %s -> %s", exprNode_unparse (e), sRef_unparse (s)));
2413 return sRef_copy (s);