2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 University of Virginia,
4 ** Massachusetts Institute of Technology
6 ** This program is free software; you can redistribute it and/or modify it
7 ** under the terms of the GNU General Public License as published by the
8 ** Free Software Foundation; either version 2 of the License, or (at your
9 ** option) any later version.
11 ** This program is distributed in the hope that it will be useful, but
12 ** WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 ** General Public License for more details.
16 ** The GNU General Public License is available from http://www.gnu.org/ or
17 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 ** MA 02111-1307, USA.
20 ** For information on splint: 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"
34 # include "usymtab_interface.h"
36 # include "structNames.h"
37 # include "nameChecks.h"
39 # include "cscannerHelp.h"
42 # include "sgrammar_tokens.h"
44 # include "cgrammar_tokens.h"
48 ** Lots of variables are needed because of interactions with the
49 ** parser. This is easier than restructuring the grammar so the
50 ** right values are available in the right place.
54 static /*@only@*/ constraintList implicitFcnConstraints = NULL;
56 static void clabstract_prepareFunction (uentry p_e) /*@modifies p_e@*/ ;
57 static bool fcnNoGlobals = FALSE;
58 static void processVariable (/*@temp@*/ idDecl p_t) /*@modifies internalState@*/ ;
60 static bool s_processingVars = FALSE;
61 static bool s_processingParams = FALSE;
62 static bool s_processingGlobals = FALSE;
63 static bool s_processingTypedef = FALSE;
64 static bool s_processingIterVars = FALSE;
65 static /*@only@*/ qtype processingType = qtype_undefined;
66 static uentry currentIter = uentry_undefined;
67 static /*@dependent@*/ uentryList saveParamList; /* for old style functions */
68 static /*@owned@*/ uentry saveFunction = uentry_undefined;
69 static int saveIterParamNo;
70 static idDecl fixStructDecl (/*@returned@*/ idDecl p_d);
71 static void checkTypeDecl (uentry p_e, ctype p_rep);
72 static /*@dependent@*/ fileloc saveStoreLoc = fileloc_undefined;
73 static storageClassCode storageClass = SCNONE;
74 static void declareEnumList (/*@temp@*/ enumNameList p_el, ctype p_c, fileloc p_loc);
75 static void resetGlobals (void);
76 static /*@null@*/ qual specialFunctionCode;
77 static bool argsUsed = FALSE;
79 extern void clabstract_initMod ()
81 specialFunctionCode = qual_createUnknown ();
82 DPRINTF (("Initialized: %s", qual_unparse (specialFunctionCode)));
85 static bool hasSpecialCode (void)
87 return (!qual_isUnknown (specialFunctionCode));
90 extern void setArgsUsed (void)
96 cstring_makeLiteral ("Multiple ARGSUSED comments for one function"),
103 static void reflectArgsUsed (uentry ue)
107 if (uentry_isFunction (ue))
109 uentryList params = uentry_getParams (ue);
111 uentryList_elements (params, el)
113 uentry_setUsed (el, fileloc_undefined);
114 } end_uentryList_elements ;
121 extern void setSpecialFunction (qual qu)
123 if (!qual_isUnknown (specialFunctionCode))
125 voptgenerror (FLG_SYNTAX,
126 message ("Multiple special function codes: %s, %s "
127 "(first code is ignored)",
128 qual_unparse (specialFunctionCode),
133 specialFunctionCode = qu;
136 static void reflectSpecialCode (uentry ue)
138 if (qual_isUnknown (specialFunctionCode)) {
140 } else if (qual_isPrintfLike (specialFunctionCode)) {
141 uentry_setPrintfLike (ue);
142 } else if (qual_isScanfLike (specialFunctionCode)) {
143 uentry_setScanfLike (ue);
144 } else if (qual_isMessageLike (specialFunctionCode)) {
145 uentry_setMessageLike (ue);
150 specialFunctionCode = qual_createUnknown ();
153 static void resetStorageClass (void)
155 qtype_free (processingType);
156 processingType = qtype_undefined;
157 storageClass = SCNONE;
160 static void reflectStorageClass (uentry u)
162 if (storageClass == SCSTATIC)
164 uentry_setStatic (u);
166 else if (storageClass == SCEXTERN)
168 uentry_setExtern (u);
172 ; /* no storage class */
179 saveStoreLoc = g_currentloc;
182 void setFunctionNoGlobals (void)
187 static void reflectGlobalQualifiers (sRef sr, qualList quals)
189 DPRINTF (("Reflect global qualifiers: %s / %s",
190 sRef_unparseFull (sr), qualList_unparse (quals)));
192 qualList_elements (quals, qel)
194 if (qual_isGlobalQual (qel)) /* undef, killed */
196 sstate oldstate = sRef_getDefState (sr);
197 sstate defstate = sstate_fromQual (qel);
199 if ((oldstate == SS_UNDEFGLOB && defstate == SS_KILLED)
200 || (oldstate == SS_KILLED && defstate == SS_UNDEFGLOB))
202 defstate = SS_UNDEFKILLED;
209 sRef_setDefState (sr, defstate, fileloc_undefined);
210 DPRINTF (("State: %s", sRef_unparseFull (sr)));
212 else if (qual_isAllocQual (qel)) /* out, partial, reldef, etc. */
214 ctype realType = sRef_getType (sr);
215 sstate defstate = sstate_fromQual (qel);
217 if (qual_isRelDef (qel))
219 ; /* okay anywhere */
223 if (!ctype_isAP (realType)
224 && !ctype_isSU (realType)
225 && !ctype_isUnknown (realType)
226 && !ctype_isAbstract (sRef_getType (sr)))
230 message ("Qualifier %s used on non-pointer or struct: %q",
231 qual_unparse (qel), sRef_unparse (sr)));
236 sRef_setDefState (sr, defstate, fileloc_undefined);
238 else if (qual_isNull (qel))
240 sRef_setNullState (sr, NS_POSNULL, fileloc_undefined);
242 else if (qual_isRelNull (qel))
244 sRef_setNullState (sr, NS_RELNULL, fileloc_undefined);
246 else if (qual_isNotNull (qel))
248 sRef_setNullState (sr, NS_MNOTNULL, fileloc_undefined);
252 if (qual_isCQual (qel))
259 message ("Qualifier %s cannot be used in a globals list",
260 qual_unparse (qel)));
263 } end_qualList_elements;
266 sRef clabstract_createGlobal (sRef sr, qualList quals)
270 if (sRef_isValid (sr))
272 res = sRef_copy (sr);
273 DPRINTF (("Reflecting quals: %s / %s", sRef_unparse (sr), qualList_unparse (quals)));
274 reflectGlobalQualifiers (res, quals);
275 DPRINTF (("==> %s", sRef_unparseFull (res)));
279 res = sRef_undefined;
282 qualList_free (quals);
286 extern void declareCIter (cstring name, /*@owned@*/ uentryList params)
290 ue = uentry_makeIter (name,
291 ctype_makeFunction (ctype_void, params),
292 fileloc_copy (g_currentloc));
294 usymtab_supEntry (uentry_makeEndIter (name, fileloc_copy (g_currentloc)));
295 ue = usymtab_supGlobalEntryReturn (ue);
298 extern void nextIterParam (void)
300 llassert (s_processingIterVars);
304 extern int iterParamNo (void)
306 llassert (s_processingIterVars);
307 return saveIterParamNo;
311 ** yucky hacks to put it in the right place
315 makeCurrentParam (idDecl t)
319 saveStoreLoc = fileloc_undefined;
321 /* param number unknown */
323 ue = uentry_makeParam (t, 0);
328 declareUnnamedEnum (enumNameList el)
330 ctype ret = usymtab_enumEnumNameListType (el);
334 if (ctype_isDefined (ret))
337 e = uentry_makeEnumTagLoc (ctype_enumTag (rt), ret);
339 reflectStorageClass (e);
340 usymtab_supGlobalEntry (e);
342 declareEnumList (el, ret, g_currentloc);
343 enumNameList_free (el);
347 ctype ct = ctype_createEnum (fakeTag (), el);
349 e = uentry_makeEnumTagLoc (ctype_enumTag (ctype_realType (ct)), ct);
350 reflectStorageClass (e);
352 e = usymtab_supGlobalEntryReturn (e);
353 rt = uentry_getAbstractType (e);
354 declareEnumList (el, ct, g_currentloc);
361 declareEnum (cstring ename, enumNameList el)
366 llassert (cstring_isDefined (ename));
368 cet = ctype_createEnum (ename, el);
369 e = uentry_makeEnumTagLoc (ename, cet);
370 reflectStorageClass (e);
371 e = usymtab_supGlobalEntryReturn (e);
372 cet = uentry_getType (e);
373 declareEnumList (el, cet, uentry_whereLast (e));
374 return (uentry_getAbstractType (e));
378 declareEnumList (enumNameList el, ctype c, fileloc loc)
380 bool boolnames = FALSE;
381 bool othernames = FALSE;
383 (void) context_getSaveLocation (); /* undefine it */
385 if (context_maybeSet (FLG_NUMENUMMEMBERS))
387 int maxnum = context_getValue (FLG_NUMENUMMEMBERS);
388 int num = enumNameList_size (el);
394 message ("Enumerator %s declared with %d members (limit is set to %d)",
395 ctype_unparse (c), num, maxnum),
400 enumNameList_elements (el, e)
402 uentry ue = usymtab_lookupExposeGlob (e);
403 ctype ct = uentry_getType (ue);
405 llassert (uentry_isEnumConstant (ue));
407 if (ctype_isUnknown (ct))
409 uentry_setType (ue, c);
413 if (cstring_equal (e, context_getFalseName ())
414 || cstring_equal (e, context_getTrueName ()))
420 message ("Enumerator mixes boolean name (%s) with "
423 uentry_whereLast (ue)))
430 uentry_setType (ue, ctype_bool);
431 DPRINTF (("Set type: %s / %s",
432 uentry_unparse (ue), ctype_unparse (ctype_bool)));
440 message ("Enumerator mixes boolean names (%s, %s) with "
441 "non-boolean name: %s",
442 context_getTrueName (),
443 context_getFalseName (),
445 uentry_whereLast (ue)))
454 if (!ctype_match (c, ct))
456 if (ctype_isDirectBool (ct))
458 if (cstring_equal (e, context_getFalseName ())
459 || cstring_equal (e, context_getTrueName ()))
461 DPRINTF (("Here we are!"));
467 message ("Enumerator member %s declared with "
468 "inconsistent type: %s",
469 e, ctype_unparse (c)),
470 uentry_whereLast (ue)))
472 uentry_showWhereSpecifiedExtra
473 (ue, cstring_copy (ctype_unparse (ct)));
481 message ("Enumerator member %s declared with "
482 "inconsistent type: %s",
483 e, ctype_unparse (c)),
484 uentry_whereLast (ue)))
486 uentry_showWhereSpecifiedExtra
487 (ue, cstring_copy (ctype_unparse (ct)));
492 } end_enumNameList_elements;
495 static /*@dependent@*/ uentryList currentParamList;
497 /*drl added 3-28-2002*/
498 /* this function takes a list of paramentar and generates a list
502 /* drl modified 10/23/2002
504 The current semantics are generated constraints of the form MaxSet(p) >= 0 and MaxRead(p) >= 0 for all pointers
505 unless the @out@ annotation has been applied to a parameter, then we only want to generate maxSet(p) > = 0
508 void setImplictfcnConstraints (void)
513 params = currentParamList;
515 if (constraintList_isDefined(implicitFcnConstraints) )
516 constraintList_free(implicitFcnConstraints);
518 implicitFcnConstraints = constraintList_makeNew();
520 uentryList_elements (params, el)
522 DPRINTF((message("setImplictfcnConstraints doing: %s", uentry_unparse(el) ) ));
524 if ( uentry_isVariable (el) )
526 s = uentry_getSref(el);
527 if (sRef_isReference (s) )
530 DPRINTF((message ("%s is a pointer", sRef_unparse(s) ) ));
532 chagned this from MaxSet(s) == 0 to MaxSet(s) >= 0 */
533 c = constraint_makeSRefWriteSafeInt (s, 0);
535 implicitFcnConstraints = constraintList_add(implicitFcnConstraints , c);
537 /*drl 10/23/2002 added support for out*/
539 if (!uentry_isOut(el) )
541 c = constraint_makeSRefReadSafeInt (s, 0);
543 implicitFcnConstraints = constraintList_add(implicitFcnConstraints , c);
548 DPRINTF((message ("%s is NOT a pointer", sRef_unparse(s) ) ));
550 } /*end uentry_isVariable*/
552 else if (uentry_isElipsisMarker (el) )
554 /*just ignore these*/
561 I'm not sure if this is possible though
563 /*@warning take this out befor@*/
568 end_uentryList_elements;
569 DPRINTF((message("implicitFcnConstraints has been set to %s\n",
570 constraintList_print(implicitFcnConstraints) ) ));
575 /*@observer@*/ constraintList getImplicitFcnConstraints (void)
577 return implicitFcnConstraints;
580 void setCurrentParams (/*@dependent@*/ uentryList ue)
582 currentParamList = ue;
585 void clearCurrentParams (void)
587 currentParamList = uentryList_undefined;
591 ** requires: uentry_isFunction (e)
592 ** parameter names for current function are in currentParamList
595 static void enterFunctionParams (uentryList params)
599 uentryList_elements (params, current)
601 if (uentry_hasName (current))
603 uentry_setParamNo (current, paramno);
604 usymtab_supEntry (uentry_copy (current));
608 } end_uentryList_elements;
612 extern void enterParamsTemp (void)
614 usymtab_enterScope ();
615 enterFunctionParams (currentParamList);
618 extern void exitParamsTemp (void)
620 usymtab_quietPlainExitScope ();
623 static /*@exposed@*/ uentry clabstract_globalDeclareFunction (idDecl tid)
625 ctype deftype = idDecl_getCtype (tid);
629 DPRINTF (("Global function: %s", idDecl_unparse (tid)));
631 if (ctype_isFunction (deftype))
633 rettype = ctype_getReturnType (deftype);
637 rettype = ctype_unknown;
641 ** check has been moved here...
644 if (ctype_isFunction (idDecl_getCtype (tid)))
646 ue = uentry_makeIdFunction (tid);
647 reflectSpecialCode (ue);
648 reflectArgsUsed (ue);
649 reflectStorageClass (ue);
650 uentry_checkParams (ue);
652 DPRINTF (("Supercede function: %s", uentry_unparseFull (ue)));
654 ue = usymtab_supGlobalEntryReturn (ue);
655 DPRINTF (("After supercede function: %s", uentry_unparseFull (ue)));
657 DPRINTF (("Enter function: %s", uentry_unparseFull (ue)));
658 context_enterFunction (ue);
659 enterFunctionParams (uentry_getParams (ue));
661 resetStorageClass ();
662 DPRINTF (("Function: %s", uentry_unparseFull (ue)));
667 llparseerror (message ("Non-function declaration: %q",
668 idDecl_unparse (tid)));
669 return (uentry_undefined);
674 ** for now, no type checking
675 ** (must check later though!)
678 static /*@only@*/ uentry globalDeclareOldStyleFunction (idDecl tid)
683 ** check has been moved here...
686 if (cstring_equalLit (idDecl_observeId (tid), "main"))
688 context_setFlagTemp (FLG_MAINTYPE, FALSE);
691 ue = uentry_makeIdFunction (tid);
692 reflectStorageClass (ue);
693 reflectSpecialCode (ue);
694 reflectArgsUsed (ue);
695 uentry_setDefined (ue, g_currentloc);
696 uentry_checkParams (ue);
697 resetStorageClass ();
699 /* context_enterOldStyleScope (); */
704 static void oldStyleDeclareFunction (/*@only@*/ uentry e)
706 uentryList params = saveParamList;
707 ctype rt = uentry_getType (e);
709 llassert (ctype_isFunction (rt));
711 if (uentry_hasStateClauseList (e)
712 || uentry_hasConditions (e))
714 llfatalerror (message ("%q: Old-style function declaration uses a clause (rewrite with function parameters): %q",
715 fileloc_unparse (g_currentloc), uentry_unparse (e)));
718 e = usymtab_supGlobalEntryReturn (e);
720 context_enterFunction (e);
721 enterFunctionParams (params);
722 saveParamList = uentryList_undefined;
723 resetStorageClass ();
726 static void oldStyleCompleteFunction (/*@only@*/ uentry e)
728 uentryList params = saveParamList;
729 ctype rt = uentry_getType (e);
731 llassert (ctype_isFunction (rt));
733 if (uentry_hasStateClauseList (e)
734 || uentry_hasConditions (e))
736 llfatalerror (message ("%q: Old-style function declaration uses a clause (rewrite with function parameters): %q",
737 fileloc_unparse (g_currentloc), uentry_unparse (e)));
740 e = usymtab_supGlobalEntryReturn (e);
742 context_completeOldStyleFunction (e);
743 enterFunctionParams (params);
744 saveParamList = uentryList_undefined;
745 resetStorageClass ();
748 void clabstract_declareFunction (idDecl tid) /*@globals undef saveFunction; @*/
752 DPRINTF (("Declare function: %s", idDecl_unparse (tid)));
754 if (ctype_isUnknown (idDecl_getCtype (tid)))
757 ** No type, its really a plain name (int) declaration
760 voptgenerror (FLG_IMPTYPE,
761 message ("No type before declaration name (implicit int type): %q",
762 idDecl_unparse (tid)),
764 tid = idDecl_replaceCtype (tid, ctype_int);
765 processVariable (tid);
766 saveFunction = uentry_undefined;
770 if (s_processingParams)
772 ue = globalDeclareOldStyleFunction (tid);
774 DPRINTF (("Set save function: %s", uentry_unparseFull (ue)));
778 saveFunction = uentry_undefined;
780 if (context_inRealFunction ())
782 ue = uentry_makeVariableLoc (idDecl_observeId (tid), ctype_unknown);
784 llparseerror (message ("Function declared inside function: %q",
785 idDecl_unparse (tid)));
787 context_quietExitFunction ();
788 ue = usymtab_supEntryReturn (ue);
792 if (context_inInnerScope ())
794 llparseerror (message ("Declaration in inner context: %q",
795 idDecl_unparse (tid)));
797 sRef_setGlobalScope ();
798 ue = uentry_makeVariableLoc (idDecl_observeId (tid),
800 ue = usymtab_supGlobalEntryReturn (ue);
801 sRef_clearGlobalScope ();
805 ue = clabstract_globalDeclareFunction (tid);
812 resetStorageClass ();
818 void declareStaticFunction (idDecl tid) /*@globals undef saveFunction; @*/
822 DPRINTF (("Declare static funciton: %s", idDecl_unparse (tid)));
824 if (s_processingParams)
826 ue = globalDeclareOldStyleFunction (tid);
831 saveFunction = uentry_undefined;
833 if (context_inRealFunction ())
835 ue = uentry_makeVariableLoc (idDecl_observeId (tid), ctype_unknown);
837 llparseerror (message ("Function declared inside function: %q",
838 idDecl_unparse (tid)));
840 context_quietExitFunction ();
841 ue = usymtab_supEntryReturn (ue);
845 if (context_inInnerScope ())
847 llparseerror (message ("Declaration in inner context: %q",
848 idDecl_unparse (tid)));
850 sRef_setGlobalScope ();
851 ue = uentry_makeVariableLoc (idDecl_observeId (tid),
853 ue = usymtab_supGlobalEntryReturn (ue);
854 sRef_clearGlobalScope ();
858 ctype deftype = idDecl_getCtype (tid);
861 if (ctype_isFunction (deftype))
863 rettype = ctype_getReturnType (deftype);
867 rettype = ctype_unknown;
871 ** check has been moved here...
874 if (ctype_isFunction (idDecl_getCtype (tid)))
876 ue = uentry_makeIdFunction (tid);
877 reflectSpecialCode (ue);
878 reflectArgsUsed (ue);
882 DPRINTF (("Here we are!"));
883 llparseerror (message ("Inconsistent function declaration: %q",
884 idDecl_unparse (tid)));
886 tid = idDecl_replaceCtype
887 (tid, ctype_makeFunction (ctype_unknown, uentryList_undefined));
888 ue = uentry_makeIdFunction (tid);
891 reflectStorageClass (ue);
892 uentry_setStatic (ue);
894 uentry_checkParams (ue);
896 DPRINTF (("Sub global entry: %s", uentry_unparse (ue)));
897 ue = usymtab_supGlobalEntryReturn (ue);
899 context_enterFunction (ue);
900 enterFunctionParams (uentry_getParams (ue));
901 resetStorageClass ();
908 resetStorageClass ();
913 checkTypeDecl (uentry e, ctype rep)
915 cstring n = uentry_getName (e);
917 DPRINTF (("Check type decl: %s", uentry_unparseFull (e)));
919 if (cstring_equal (context_getBoolName (), n))
921 ctype rrep = ctype_realType (rep);
924 ** for abstract enum types, we need to fix the enum members:
925 ** they should have the abstract type, not the rep type.
928 if (ctype_isEnum (ctype_realType (rrep)))
930 enumNameList el = ctype_elist (rrep);
932 enumNameList_elements (el, ye)
934 if (usymtab_existsGlob (ye))
936 uentry ue = usymtab_lookupSafe (ye);
937 uentry_setType (ue, ctype_bool);
940 if (cstring_equal (context_getTrueName (), ye)
941 || cstring_equal (context_getFalseName (), ye))
949 message ("Member of boolean enumerated type definition "
950 "does not match name set to represent TRUE "
953 message ("Use -boolfalse and -booltrue to set the "
954 "name of false and true boolean values."),
955 uentry_whereDefined (e));
957 } end_enumNameList_elements;
961 if (usymtab_exists (n))
963 usymId llm = usymtab_getId (n);
964 uentry le = usymtab_getTypeEntry (llm);
966 uentry_setDeclared (e, g_currentloc);
967 uentry_setSref (e, sRef_makeGlobal (llm, uentry_getType (le), stateInfo_currentLoc ()));
969 DPRINTF (("Here we are: %s / %s",
970 n, context_getBoolName ()));
972 if (uentry_isAbstractDatatype (le))
974 ctype rrep = ctype_realType (rep);
976 DPRINTF (("Abstract type: %s", uentry_unparseFull (le)));
979 ** for abstract enum types, we need to fix the enum members:
980 ** they should have the abstract type, not the rep type.
983 if (ctype_isEnum (ctype_realType (rrep)))
985 ctype at = uentry_getAbstractType (le);
986 enumNameList el = ctype_elist (rrep);
988 enumNameList_elements (el, ye)
990 if (usymtab_existsGlob (ye))
992 uentry ue = usymtab_lookupSafe (ye);
994 llassert (uentry_isEitherConstant (ue));
996 /* evans 2002-04-22 */
997 if (ctype_isBool (uentry_getType (ue)))
1000 ** If set using -booltrue or -boolfalse, don't change the type.
1005 llassertprint (ctype_match (uentry_getType (ue), rrep),
1006 ("Bad enum: %s / %s",
1007 uentry_unparse (ue),
1008 ctype_unparse (rrep)));
1010 uentry_setType (ue, at);
1013 } end_enumNameList_elements;
1016 if (uentry_isMutableDatatype (le))
1018 /* maybe more complicated if abstract and immutable ? */
1020 if (!ctype_isRealPointer (rep) && !ctype_isRealAbstract (rep))
1024 message ("Mutable abstract type %s declared without pointer "
1025 "indirection: %s (violates assignment semantics)",
1026 n, ctype_unparse (rep)),
1027 uentry_whereDefined (e));
1029 uentry_setMutable (e);
1036 fileloc fl = uentry_whereDeclared (e);
1038 if (context_getFlag (FLG_LIKELYBOOL)
1039 && !context_getFlag (FLG_BOOLINT))
1041 if ((cstring_equalLit (n, "BOOL")
1042 || cstring_equalLit (n, "Bool")
1043 || cstring_equalLit (n, "bool")
1044 || cstring_equalLit (n, "boolean")
1045 || cstring_equalLit (n, "Boolean")
1046 || cstring_equalLit (n, "BOOLEAN"))
1047 && !(cstring_equal (n, context_getBoolName ())))
1049 if (context_setBoolName ()) {
1052 message ("Type %s is probably meant as a boolean type, but does "
1053 "not match the boolean type name \"%s\".",
1055 context_getBoolName ()),
1060 message ("Type %s is probably meant as a boolean type, "
1061 "but the boolean type name is not set. "
1062 "Use -booltype %s to set it.",
1069 if (!uentry_isStatic (e)
1070 && !ctype_isFunction (uentry_getType (e))
1071 && !fileloc_isLib (fl)
1072 && !fileloc_isImport (fl)
1073 && fileloc_isHeader (fl))
1075 voptgenerror (FLG_EXPORTTYPE,
1076 message ("Type exported, but not specified: %s\n", n),
1085 fixUentryList (idDeclList tl, qtype q)
1087 uentryList f = uentryList_new ();
1089 idDeclList_elements (tl, i)
1091 if (idDecl_isDefined (i))
1097 (void) idDecl_fixBase (i, q);
1100 ** implicit annotations
1103 (void) fixStructDecl (i);
1105 ue = uentry_makeIdVariable (i);
1106 rt = ctype_realType (uentry_getType (ue));
1109 ** where is this here???
1111 if (ctype_isArray (rt) || ctype_isSU (rt))
1113 sRef_setAllocated (uentry_getSref (ue), uentry_whereDefined (ue));
1119 if (uentry_isValid (old = uentryList_lookupField (f, uentry_rawName (ue))))
1121 if (optgenerror (FLG_SYNTAX,
1122 message ("Field name reused: %s", uentry_rawName (ue)),
1123 uentry_whereDefined (ue)))
1125 llgenmsg (message ("Previous use of %s", uentry_rawName (ue)),
1126 uentry_whereDefined (old));
1130 f = uentryList_add (f, ue);
1132 } end_idDeclList_elements;
1134 idDeclList_free (tl);
1139 ** This is a hack to support unnamed struct/union fields as done by
1140 ** Microsoft VC++. It is not supported by the ANSI standard.
1142 ** The inner fields are added to the outer structure. This is meaningful
1143 ** for nesting structs inside unions, but Splint does no related
1148 fixUnnamedDecl (qtype q)
1150 ctype ct = ctype_realType (qtype_getType (q));
1152 if (ctype_isStruct (ct) || ctype_isUnion (ct))
1154 return uentryList_single (uentry_makeUnnamedVariable (ct));
1156 else if (ctype_isEnum (ct))
1158 /* evans 2002-02-05: nothing to do for unnamed enum lists */
1159 return uentryList_undefined;
1165 message ("Type name in field declarations: %s", qtype_unparse (q)),
1169 return uentryList_undefined;
1172 void setStorageClass (storageClassCode sc)
1178 setProcessingIterVars (uentry iter)
1180 s_processingIterVars = TRUE;
1182 saveIterParamNo = 0;
1186 setProcessingGlobalsList ()
1188 s_processingGlobals = TRUE;
1189 fcnNoGlobals = FALSE;
1192 static bool ProcessingGlobMods = FALSE;
1195 setProcessingGlobMods ()
1197 ProcessingGlobMods = TRUE;
1201 clearProcessingGlobMods ()
1203 ProcessingGlobMods = FALSE;
1207 isProcessingGlobMods ()
1209 return (ProcessingGlobMods);
1212 static void resetGlobals (void)
1214 s_processingGlobals = FALSE;
1215 fcnNoGlobals = FALSE;
1219 unsetProcessingGlobals ()
1221 s_processingGlobals = FALSE;
1225 setProcessingVars (/*@only@*/ qtype q)
1227 s_processingVars = TRUE;
1228 qtype_free (processingType);
1233 setGenericParamList (/*@dependent@*/ uentryList pm)
1235 s_processingParams = TRUE;
1240 setProcessingTypedef (qtype q)
1242 s_processingTypedef = TRUE;
1244 qtype_free (processingType);
1249 unsetProcessingVars ()
1251 resetStorageClass ();
1252 s_processingVars = FALSE;
1256 oldStyleDoneParams ()
1258 if (s_processingParams)
1260 if (uentry_isInvalid (saveFunction))
1262 llbuglit ("unsetProcessingVars: no saved function\n");
1266 ctype ct = ctype_getReturnType (uentry_getType (saveFunction));
1267 uentryList params = uentryList_copy (saveParamList);
1268 ctype ct2 = ctype_makeFunction (ct, params);
1270 uentry_setType (saveFunction, ct2);
1271 s_processingParams = FALSE;
1273 oldStyleCompleteFunction (saveFunction);
1274 saveFunction = uentry_undefined;
1281 ** If the paramlist used a type name, we could be here.
1284 llfatalerror (message ("%q: Old-style function parameter list uses a "
1285 "type name.", fileloc_unparse (g_currentloc)));
1292 if (uentry_isValid (saveFunction))
1295 ** old style declaration
1298 ctype ct = ctype_getReturnType (uentry_getType (saveFunction));
1301 DPRINTF (("save function: %s", uentry_unparseFull (saveFunction)));
1303 uentryList_elements (saveParamList, current)
1305 uentry_setType (current, ctype_int); /* all params are ints */
1306 } end_uentryList_elements;
1308 ct2 = ctype_makeParamsFunction (ct, uentryList_copy (saveParamList));
1310 uentry_setType (saveFunction, ct2);
1311 s_processingParams = FALSE;
1313 oldStyleDeclareFunction (saveFunction);
1314 saveFunction = uentry_undefined;
1318 void clabstract_declareType (/*@only@*/ exprNodeList decls, /*@only@*/ warnClause warn)
1320 llassert (s_processingTypedef);
1322 DPRINTF (("Declare type: %s", exprNodeList_unparse (decls)));
1324 if (warnClause_isDefined (warn))
1326 DPRINTF (("Has a warn clause!"));
1327 DPRINTF (("Warn: %s", warnClause_unparse (warn)));
1329 exprNodeList_elements (decls, el)
1331 uentry ue = exprNode_getUentry (el);
1332 cstring uname = uentry_getName (ue);
1334 DPRINTF (("Entry: %s", exprNode_unparse (el)));
1337 ** Need to lookup again to make sure we have the right one...
1340 ue = usymtab_lookupExposeGlob (uname);
1342 llassert (uentry_isValid (ue));
1343 llassert (uentry_isDatatype (ue));
1345 DPRINTF (("Warning for %s: %s",
1346 uentry_unparse (ue), warnClause_unparse (warn)));
1348 uentry_addWarning (ue, warnClause_copy (warn));
1349 DPRINTF (("After add warning: %s", uentry_unparseFull (ue)));
1350 cstring_free (uname);
1351 } end_exprNodeList_elements;
1354 warnClause_free (warn);
1355 exprNodeList_free (decls);
1356 unsetProcessingTypedef ();
1360 unsetProcessingTypedef ()
1362 s_processingTypedef = FALSE;
1365 void checkConstant (qtype t, idDecl id)
1369 id = idDecl_fixBase (id, t);
1370 e = uentry_makeIdConstant (id);
1372 reflectStorageClass (e);
1373 resetStorageClass ();
1375 DPRINTF (("Constant: %s", uentry_unparseFull (e)));
1376 usymtab_supGlobalEntry (e);
1379 void checkValueConstant (qtype t, idDecl id, exprNode e)
1383 id = idDecl_fixBase (id, t);
1384 ue = uentry_makeIdConstant (id);
1385 reflectStorageClass (ue);
1386 resetStorageClass ();
1388 if (exprNode_isDefined (e))
1390 if (!exprNode_matchType (uentry_getType (ue), e))
1393 (exprNode_getType (e), e,
1394 uentry_getType (ue), exprNode_undefined,
1395 message ("Constant %q initialized to type %t, expects %t: %s",
1396 uentry_getName (ue),
1397 exprNode_getType (e),
1398 uentry_getType (ue),
1399 exprNode_unparse (e)),
1404 if (exprNode_hasValue (e))
1406 uentry_mergeConstantValue (ue, multiVal_copy (exprNode_getValue (e)));
1410 DPRINTF (("No value: %s", exprNode_unparse (e)));
1415 DPRINTF (("Constant value: %s", uentry_unparseFull (ue)));
1416 usymtab_supGlobalEntry (ue);
1419 static void processVariable (idDecl t)
1424 ct = ctype_realType (idDecl_getCtype (t));
1426 if (s_processingParams)
1428 cstring id = idDecl_getName (t);
1429 int paramno = uentryList_lookupRealName (saveParamList, id);
1433 uentry cparam = uentryList_getN (saveParamList, paramno);
1435 DPRINTF (("Processing param: %s", uentry_unparseFull (cparam)));
1436 uentry_setType (cparam, idDecl_getCtype (t));
1437 uentry_reflectQualifiers (cparam, idDecl_getQuals (t));
1438 uentry_setDeclaredOnly (cparam, context_getSaveLocation ());
1439 DPRINTF (("Processing param: %s", uentry_unparseFull (cparam)));
1444 (message ("Old style declaration uses unlisted parameter: %s",
1452 if (context_inIterDef ())
1454 cstring pname = makeParam (idDecl_observeId (t));
1455 uentry p = usymtab_lookupSafe (pname);
1457 cstring_free (pname);
1459 if (uentry_isYield (p))
1461 e = uentry_makeParam (t, sRef_getParam (uentry_getSref (p)));
1462 uentry_checkYieldParam (p, e);
1463 usymtab_supEntrySref (e);
1468 if ((hasSpecialCode () || argsUsed)
1469 && ctype_isFunction (idDecl_getCtype (t)))
1471 e = uentry_makeIdFunction (t);
1472 reflectSpecialCode (e);
1473 reflectArgsUsed (e);
1477 e = uentry_makeIdVariable (t);
1480 loc = uentry_whereDeclared (e);
1483 if (context_inGlobalScope ())
1485 uentry_checkParams was here!
1489 if (ctype_isFunction (uentry_getType (e)))
1491 clabstract_prepareFunction (e);
1494 DPRINTF (("Superceding... %s", uentry_unparseFull (e)));
1495 e = usymtab_supEntrySrefReturn (e);
1496 DPRINTF (("After superceding... %s", uentry_unparseFull (e)));
1498 if (uentry_isExtern (e) && !context_inGlobalScope ())
1502 message ("Declaration using extern inside function scope: %q",
1503 uentry_unparse (e)),
1506 uentry_setDefined (e, fileloc_getExternal ());
1507 sRef_setDefined (uentry_getSref (e), fileloc_getExternal ());
1510 if (uentry_isFunction (e))
1512 if (!context_inXHFile ())
1514 checkParamNames (e);
1518 if (uentry_isVar (e) && uentry_isCheckedUnknown (e))
1520 sRef sr = uentry_getSref (e);
1522 if (sRef_isLocalVar (sr))
1524 if (context_getFlag (FLG_IMPCHECKMODINTERNALS))
1526 uentry_setCheckMod (e);
1530 uentry_setUnchecked (e);
1533 else if (sRef_isFileStatic (sr))
1535 if (context_getFlag (FLG_IMPCHECKEDSTRICTSTATICS))
1537 uentry_setCheckedStrict (e);
1539 else if (context_getFlag (FLG_IMPCHECKEDSTATICS))
1541 uentry_setChecked (e);
1543 else if (context_getFlag (FLG_IMPCHECKMODSTATICS))
1545 uentry_setCheckMod (e);
1552 else /* real global */
1554 llassert (sRef_isRealGlobal (sr));
1556 if (context_getFlag (FLG_IMPCHECKEDSTRICTGLOBALS))
1558 uentry_setCheckedStrict (e);
1560 else if (context_getFlag (FLG_IMPCHECKEDGLOBALS))
1562 uentry_setChecked (e);
1564 else if (context_getFlag (FLG_IMPCHECKMODGLOBALS))
1566 uentry_setCheckMod (e);
1577 void processNamedDecl (idDecl t)
1579 if (qtype_isUndefined (processingType))
1581 processingType = qtype_create (ctype_int);
1582 t = idDecl_fixBase (t, processingType);
1584 voptgenerror (FLG_IMPTYPE,
1585 message ("No type before declaration name (implicit int type): %q",
1586 idDecl_unparse (t)),
1591 t = idDecl_fixBase (t, processingType);
1594 DPRINTF (("Declare: %s", idDecl_unparse (t)));
1596 if (s_processingGlobals)
1598 cstring id = idDecl_getName (t);
1599 uentry ue = usymtab_lookupSafe (id);
1601 if (!uentry_isValid (ue))
1603 llerror (FLG_UNRECOG,
1604 message ("Variable used in globals list is undeclared: %s", id));
1608 if (!ctype_match (uentry_getType (ue), idDecl_getCtype (t)))
1612 message ("Variable %s used in globals list declared %s, "
1614 id, ctype_unparse (uentry_getType (ue)),
1615 ctype_unparse (idDecl_getCtype (t))),
1620 sRef sr = sRef_copy (uentry_getSref (ue));
1621 reflectGlobalQualifiers (sr, idDecl_getQuals (t));
1625 else if (s_processingVars)
1627 processVariable (t);
1629 else if (s_processingTypedef)
1631 ctype ct = idDecl_getCtype (t);
1634 DPRINTF (("Processing typedef: %s", ctype_unparse (ct)));
1636 e = uentry_makeIdDatatype (t);
1638 if (cstring_equal (idDecl_getName (t), context_getBoolName ())) {
1639 ctype rt = ctype_realType (ct);
1641 if (ctype_isEnum (rt)) {
1644 if (!(ctype_isInt (rt)
1645 || ctype_isUnknown (rt)
1646 || ctype_isChar (rt))) {
1649 message ("Boolean type %s defined using non-standard type %s (integral, char or enum type expected)",
1650 context_getBoolName (),
1651 ctype_unparse (ct)),
1652 uentry_whereLast (e));
1656 uentry_setType (e, ct);
1660 reflectStorageClass (e);
1661 checkTypeDecl (e, ct);
1663 e = usymtab_supReturnTypeEntry (e);
1667 llparseerror (message ("Suspect missing struct or union keyword: %q",
1668 idDecl_unparse (t)));
1674 ** moved from grammar
1677 static idDecl fixStructDecl (/*@returned@*/ idDecl d)
1679 if (ctype_isVisiblySharable (idDecl_getCtype (d))
1680 && context_getFlag (FLG_STRUCTIMPONLY))
1682 if (!qualList_hasAliasQualifier (idDecl_getQuals (d)))
1684 if (qualList_hasExposureQualifier (idDecl_getQuals (d)))
1686 idDecl_addQual (d, qual_createDependent ());
1690 idDecl_addQual (d, qual_createImpOnly ());
1699 declareUnnamedStruct (/*@only@*/ uentryList f)
1701 DPRINTF (("Unnamed struct: %s", uentryList_unparse (f)));
1703 if (context_maybeSet (FLG_NUMSTRUCTFIELDS))
1705 int num = uentryList_size (f);
1706 int max = context_getValue (FLG_NUMSTRUCTFIELDS);
1711 (FLG_NUMSTRUCTFIELDS,
1712 message ("Structure declared with %d fields "
1713 "(limit is set to %d)",
1719 return (ctype_createUnnamedStruct (f));
1723 declareUnnamedUnion (/*@only@*/ uentryList f)
1725 DPRINTF (("Unnamed union: %s", uentryList_unparse (f)));
1727 if (context_maybeSet (FLG_NUMSTRUCTFIELDS))
1729 int num = uentryList_size (f);
1730 int max = context_getValue (FLG_NUMSTRUCTFIELDS);
1735 (FLG_NUMSTRUCTFIELDS,
1736 message ("Union declared with %d fields "
1737 "(limit is set to %d)",
1743 return (ctype_createUnnamedUnion (f));
1746 ctype declareStruct (cstring id, /*@only@*/ uentryList f)
1750 int num = uentryList_size (f);
1752 DPRINTF (("Declare struct: %s / %s [%d]", id, uentryList_unparse (f),
1753 uentryList_size (f)));
1755 ct = ctype_createStruct (cstring_copy (id), f);
1757 DPRINTF (("Ctype: %s", ctype_unparse (ct)));
1759 ue = uentry_makeStructTagLoc (id, ct);
1761 DPRINTF (("ue: %s", uentry_unparseFull (ue)));
1763 if (context_maybeSet (FLG_NUMSTRUCTFIELDS))
1765 int max = context_getValue (FLG_NUMSTRUCTFIELDS);
1770 (FLG_NUMSTRUCTFIELDS,
1771 message ("Structure %q declared with %d fields "
1772 "(limit is set to %d)",
1773 uentry_getName (ue), num, max),
1774 uentry_whereLast (ue));
1778 return (usymtab_supTypeEntry (ue));
1781 ctype declareUnion (cstring id, uentryList f)
1785 int num = uentryList_size (f);
1787 ct = ctype_createUnion (cstring_copy (id), f);
1788 ue = uentry_makeUnionTagLoc (id, ct);
1790 if (context_maybeSet (FLG_NUMSTRUCTFIELDS))
1792 int max = context_getValue (FLG_NUMSTRUCTFIELDS);
1797 (FLG_NUMSTRUCTFIELDS,
1798 message ("Union %q declared with %d fields "
1799 "(limit is set to %d)",
1800 uentry_getName (ue), num, max),
1801 uentry_whereLast (ue));
1805 return (usymtab_supTypeEntry (ue));
1808 ctype handleStruct (/*@only@*/ cstring id)
1810 if (usymtab_existsStructTag (id))
1812 ctype ct = uentry_getAbstractType (usymtab_lookupStructTag (id));
1819 return (ctype_createForwardStruct (id));
1823 ctype handleUnion (/*@only@*/ cstring id)
1825 if (usymtab_existsUnionTag (id))
1827 ctype ret = uentry_getAbstractType (usymtab_lookupUnionTag (id));
1833 return (ctype_createForwardUnion (id));
1838 handleEnum (cstring id)
1840 if (usymtab_existsEnumTag (id))
1842 ctype ret = uentry_getAbstractType (usymtab_lookupEnumTag (id));
1848 return (ctype_createForwardEnum (id));
1852 bool processingIterVars (void)
1854 return s_processingIterVars;
1857 uentry getCurrentIter (void)
1862 static bool flipOldStyle = FALSE;
1863 static bool flipNewStyle = TRUE;
1865 void setFlipOldStyle () { flipOldStyle = TRUE; }
1866 bool isFlipOldStyle () { return flipOldStyle; }
1867 bool isNewStyle () { return flipNewStyle; }
1868 void setNewStyle () { flipNewStyle = TRUE; }
1870 /*@dependent@*/ uentryList handleParamIdList (/*@dependent@*/ uentryList params)
1875 ** this is a really YUCKY hack to handle old style
1879 voptgenerror (FLG_OLDSTYLE,
1880 cstring_makeLiteral ("Old style function declaration"),
1883 DPRINTF (("Handle old style params: %s", uentryList_unparseFull (params)));
1885 uentryList_elements (params, current)
1887 uentry_setParam (current);
1888 uentry_setSref (current, sRef_makeParam
1889 (paramno, ctype_unknown,
1890 stateInfo_makeLoc (uentry_whereLast (current), SA_DECLARED)));
1892 } end_uentryList_elements;
1894 setGenericParamList (params);
1895 cscannerHelp_setExpectingTypeName ();
1900 /*@dependent@*/ uentryList handleParamTypeList (/*@returned@*/ uentryList params)
1904 uentryList_fixMissingNames (params);
1906 voptgenerror (FLG_OLDSTYLE,
1907 cstring_makeLiteral ("Old style function declaration."),
1910 setGenericParamList (params);
1911 flipOldStyle = FALSE;
1912 cscannerHelp_setExpectingTypeName ();
1921 ctype c = ctype_unknown;
1922 cstring id = cstring_makeLiteral ("va_alist");
1925 if (s_processingParams)
1927 int i = uentryList_lookupRealName (saveParamList, id);
1931 fileloc loc = context_getSaveLocation ();
1932 e = uentry_makeVariableSrefParam
1934 sRef_makeParam (i, c, stateInfo_makeLoc (loc, SA_DECLARED)));
1938 e = uentry_undefined; /* suppress gcc message */
1939 llfatalerrorLoc (cstring_makeLiteral ("va_dcl used without va_alist"));
1944 llerror (FLG_SYNTAX, cstring_makeLiteral ("va_dcl used outside of function declaration"));
1945 e = uentry_makeVariableLoc (id, c);
1949 uentry_setUsed (e, g_currentloc);
1950 usymtab_supEntrySref (e);
1953 /*@exposed@*/ sRef modListPointer (/*@exposed@*/ sRef s)
1955 ctype ct = sRef_getType (s);
1956 ctype rt = ctype_realType (ct);
1958 if (ctype_isAP (rt))
1960 if (context_inHeader () && ctype_isAbstract (ct))
1965 ("Modifies clause in header file dereferences abstract "
1966 "type %s (interface modifies clause should not depend "
1967 "on or expose type representation): %q",
1973 return (sRef_constructPointer (s));
1977 if (ctype_isKnown (rt))
1981 message ("Implementation modifies clause dereferences non-pointer (type %s): %q",
1991 /*@exposed@*/ sRef modListFieldAccess (sRef s, cstring f)
1993 ctype ct = sRef_getType (s);
1994 ctype rt = ctype_realType (ct);
1996 if (ctype_isStructorUnion (rt))
1998 uentry tf = uentryList_lookupField (ctype_getFields (rt), f);
2000 if (uentry_isUndefined (tf))
2002 voptgenerror (FLG_TYPE,
2003 message ("Modifies list accesses non-existent "
2004 "field %s of %t: %q", f, ct,
2009 return sRef_undefined;
2013 if (ctype_isAbstract (ct) && context_inHeader ())
2018 ("Modifies clause in header file accesses abstract "
2019 "type %s (interface modifies clause should not depend "
2020 "on or expose type representation): %q",
2027 cstring_markOwned (f);
2028 return (sRef_makeField (s, f));
2034 message ("Modifies clause dereferences non-pointer (type %s): %q",
2044 /*@dependent@*/ sRef clabstract_unrecognizedGlobal (cstring s)
2046 if (cstring_equalLit (s, "nothing"))
2048 return sRef_makeNothing ();
2050 else if (cstring_equalLit (s, "internalState"))
2052 return sRef_makeInternalState ();
2054 else if (cstring_equalLit (s, "fileSystem")
2055 || cstring_equalLit (s, "systemState"))
2057 return sRef_makeSystemState ();
2063 message ("Unrecognized identifier in globals list: %s", s),
2066 return sRef_undefined;
2070 /*@exposed@*/ sRef modListArrowAccess (sRef s, cstring f)
2072 ctype ct = sRef_getType (s);
2073 ctype rt = ctype_realType (ct);
2075 if (ctype_isRealPointer (rt))
2077 ctype b = ctype_baseArrayPtr (rt);
2078 ctype rb = ctype_realType (b);
2080 if (ctype_isStructorUnion (rb))
2082 uentry tf = uentryList_lookupField (ctype_getFields (rb), f);
2084 if (uentry_isUndefined (tf))
2086 voptgenerror (FLG_TYPE,
2087 message ("Modifies list arrow accesses non-existent "
2088 "field %s of %t: %q", f, b,
2093 return sRef_undefined;
2097 if (context_inHeader ())
2099 if (ctype_isAbstract (b))
2104 ("Modifies clause in header file arrow accesses abstract "
2105 "type %s (interface modifies clause should not depend "
2106 "on or expose type representation): %q",
2114 if (ctype_isAbstract (rt))
2119 ("Modifies clause arrow accesses inaccessible abstract "
2120 "type %s (interface modifies clause should not depend "
2121 "on or expose type representation): %q",
2129 cstring_markOwned (f);
2130 return (sRef_makeArrow (s, f));
2136 message ("Modifies clause arrow accesses pointer to "
2137 "non-structure (type %s): %q",
2147 message ("Modifies clause arrow accesses non-pointer (type %s): %q",
2157 sRef checkStateClausesId (uentry ue)
2159 cstring s = uentry_rawName (ue);
2161 if (sRef_isFileOrGlobalScope (uentry_getSref (ue)))
2165 message ("Global variable %s used state clause. (Global variables "
2166 "are not recognized in state clauses. If they are present "
2167 "they are ignored. "
2169 "sufficient interest in support for this, it may be "
2170 "added to a future release. Send mail to "
2171 "info@splint.org.)",
2175 return sRef_undefined;
2179 if (cstring_equalLit (s, "result"))
2183 message ("Special clause list uses %s which is a variable and has special "
2184 "meaning in a modifies list. (Special meaning assumed.)", s),
2187 uentry_showWhereDeclared (ue);
2191 return uentry_getSref (ue);
2197 don;t know what the real date is...
2203 based on checkSpecClausesId
2207 sRef checkbufferConstraintClausesId (uentry ue)
2210 cstring s = uentry_rawName (ue);
2212 if (cstring_equalLit (s, "result"))
2216 message ("Function clause list uses %s which is a variable and has special "
2217 "meaning in a modifies list. (Special meaning assumed.)", s),
2220 uentry_showWhereDeclared (ue);
2224 DPRINTF (("constraint id: %s", uentry_unparseFull (ue)));
2225 sr = uentry_getSref (ue);
2227 if (sRef_isInvalid (sr) )
2229 llfatalerrorLoc (cstring_makeLiteral("Macro defined constants can not be used in function constraints unless they are specifed with the constant annotation. To use a macro defined constant include an annotation of the form /*@constant <type> <name>=<value>@*/ somewhere before the function constraint. This restriction may be removed in future releases if it is determined to be excessively burdensome." ));
2232 /*@ savedCopy to used to mitigate danger of accessing freed memory*/
2233 return sRef_saveCopy (sr);
2236 void checkModifiesId (uentry ue)
2238 cstring s = uentry_rawName (ue);
2240 if (cstring_equalLit (s, "nothing")
2241 || cstring_equalLit (s, "internalState")
2242 || cstring_equalLit (s, "systemState")
2243 || (cstring_equalLit (s, "fileSystem")))
2247 message ("Modifies list uses %s which is a variable and has special "
2248 "meaning in a modifies list. (Special meaning assumed.)", s),
2251 uentry_showWhereDeclared (ue);
2256 /*@exposed@*/ sRef fixModifiesId (cstring s)
2259 cstring pname = makeParam (s);
2260 uentry ue = usymtab_lookupSafe (pname);
2262 cstring_free (pname);
2264 if (cstring_equalLit (s, "nothing"))
2266 ret = sRef_makeNothing ();
2268 else if (cstring_equalLit (s, "internalState"))
2270 ret = sRef_makeInternalState ();
2272 else if (cstring_equalLit (s, "fileSystem")
2273 || cstring_equalLit (s, "systemState"))
2275 ret = sRef_makeSystemState ();
2279 ret = sRef_undefined;
2282 if (sRef_isValid (ret))
2284 if (uentry_isValid (ue))
2288 message ("Modifies list uses %s which is a parameter and has special "
2289 "meaning in a modifies list. (Special meaning assumed.)", s),
2295 if (uentry_isValid (ue))
2297 ret = uentry_getSref (ue);
2301 fileloc loc = fileloc_decColumn (g_currentloc, size_toInt (cstring_length (s)));
2302 ret = sRef_undefined;
2306 message ("Unrecognized identifier in modifies comment: %s", s),
2316 sRef fixStateClausesId (cstring s)
2319 cstring pname = makeParam (s);
2320 uentry ue = usymtab_lookupSafe (pname);
2322 cstring_free (pname);
2324 if (cstring_equalLit (s, "result"))
2326 ret = sRef_makeResult (ctype_unknown);
2330 ret = sRef_undefined;
2333 if (sRef_isValid (ret))
2335 if (uentry_isValid (ue))
2339 message ("Function clause uses %s which is a parameter and has special "
2340 "meaning in a function clause. (Special meaning assumed.)", s),
2346 if (uentry_isValid (ue))
2348 ret = uentry_getSref (ue);
2350 if (sRef_isFileOrGlobalScope (ret))
2354 message ("Global variable %s used in function clause. (Global variables "
2355 "are not recognized in function clauses. If there is "
2356 "sufficient interest in support for this, it may be "
2357 "added to a future release. Send mail to "
2358 "info@splint.org.)",
2362 ret = sRef_undefined;
2368 /* drl This is the code for structure invariants
2370 It is no yet stable enough to be included in a Splint release.
2373 /*check that we're in a structure */
2375 /*@unused@*/ uentryList ueL;
2376 /*@unused@*/ uentry ue2;
2377 /*@unused@*/ ctype ct;
\r
2379 fileloc loc = fileloc_decColumn (g_currentloc, size_toInt (cstring_length (s)));
2380 ret = sRef_undefined;
2383 ct = context_getLastStruct ( ct );
2385 llassert( ctype_isStruct(ct) );
2387 ueL = ctype_getFields (ct);
2389 ue2 = uentryList_lookupField (ueL, s);
2391 if (!uentry_isUndefined(ue2) )
2393 ret = uentry_getSref(ue2);
2396 message("Got field in structure in the annotation constraint: %s (or sref: %s)", s, sRef_unparse(ret) )
2406 message ("Unrecognized identifier in function clause: %s", s),
2416 sRef modListArrayFetch (/*@exposed@*/ sRef s, /*@unused@*/ sRef mexp)
2418 ctype ct = sRef_getType (s);
2419 ctype rt = ctype_realType (ct);
2421 if (ctype_isAP (rt))
2423 if (context_inHeader () && ctype_isAbstract (ct))
2428 ("Modifies clause in header file indexes abstract "
2429 "type %s (interface modifies clause should not depend "
2430 "on or expose type representation): %q",
2436 return (sRef_makeAnyArrayFetch (s));
2443 ("Implementation modifies clause uses array fetch on non-array (type %s): %q",
2444 ctype_unparse (ct), sRef_unparse (s)),
2450 static void clabstract_prepareFunction (uentry e)
2452 uentry_checkParams (e);
2453 DPRINTF (("After prepare: %s", uentry_unparseFull (e)));
2456 sRef clabstract_checkGlobal (exprNode e)
2459 llassert (exprNode_isInitializer (e));
2461 s = exprNode_getSref (e);
2462 DPRINTF (("Initializer: %s -> %s", exprNode_unparse (e), sRef_unparse (s)));
2465 return sRef_copy (s);