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"
34 # include "usymtab_interface.h"
36 # include "structNames.h"
37 # include "nameChecks.h"
40 # include "sgrammar_tokens.h"
42 # include "cgrammar_tokens.h"
46 ** Lots of variables are needed because of interactions with the
47 ** parser. This is easier than restructuring the grammar so the
48 ** right values are available in the right place.
52 static /*@only@*/ constraintList implicitFcnConstraints = NULL;
54 static void clabstract_prepareFunction (uentry p_e) /*@modifies p_e@*/ ;
55 static bool fcnNoGlobals = FALSE;
56 static void processVariable (/*@temp@*/ idDecl p_t) /*@modifies internalState@*/ ;
58 static bool s_processingVars = FALSE;
59 static bool s_processingParams = FALSE;
60 static bool s_processingGlobals = FALSE;
61 static bool s_processingTypedef = FALSE;
62 static bool s_processingIterVars = FALSE;
63 static /*@only@*/ qtype processingType = qtype_undefined;
64 static uentry currentIter = uentry_undefined;
65 static /*@dependent@*/ uentryList saveParamList; /* for old style functions */
66 static /*@owned@*/ uentry saveFunction = uentry_undefined;
67 static int saveIterParamNo;
68 static idDecl fixStructDecl (/*@returned@*/ idDecl p_d);
69 static void checkTypeDecl (uentry p_e, ctype p_rep);
70 static /*@dependent@*/ fileloc saveStoreLoc = fileloc_undefined;
71 static storageClassCode storageClass = SCNONE;
72 static void declareEnumList (/*@temp@*/ enumNameList p_el, ctype p_c, fileloc p_loc);
73 static void resetGlobals (void);
74 static /*@null@*/ qual specialFunctionCode;
75 static bool argsUsed = FALSE;
77 extern void clabstract_initMod ()
79 specialFunctionCode = qual_createUnknown ();
80 DPRINTF (("Initialized: %s", qual_unparse (specialFunctionCode)));
83 static bool hasSpecialCode (void)
85 return (!qual_isUnknown (specialFunctionCode));
88 extern void setArgsUsed (void)
94 cstring_makeLiteral ("Multiple ARGSUSED comments for one function"),
101 static void reflectArgsUsed (uentry ue)
105 if (uentry_isFunction (ue))
107 uentryList params = uentry_getParams (ue);
109 uentryList_elements (params, el)
111 uentry_setUsed (el, fileloc_undefined);
112 } end_uentryList_elements ;
119 extern void setSpecialFunction (qual qu)
121 if (!qual_isUnknown (specialFunctionCode))
123 voptgenerror (FLG_SYNTAX,
124 message ("Multiple special function codes: %s, %s "
125 "(first code is ignored)",
126 qual_unparse (specialFunctionCode),
131 specialFunctionCode = qu;
134 static void reflectSpecialCode (uentry ue)
136 if (qual_isUnknown (specialFunctionCode)) {
138 } else if (qual_isPrintfLike (specialFunctionCode)) {
139 uentry_setPrintfLike (ue);
140 } else if (qual_isScanfLike (specialFunctionCode)) {
141 uentry_setScanfLike (ue);
142 } else if (qual_isMessageLike (specialFunctionCode)) {
143 uentry_setMessageLike (ue);
148 specialFunctionCode = qual_createUnknown ();
151 static void resetStorageClass (void)
153 qtype_free (processingType);
154 processingType = qtype_undefined;
155 storageClass = SCNONE;
158 static void reflectStorageClass (uentry u)
160 if (storageClass == SCSTATIC)
162 uentry_setStatic (u);
164 else if (storageClass == SCEXTERN)
166 uentry_setExtern (u);
170 ; /* no storage class */
177 saveStoreLoc = g_currentloc;
180 void setFunctionNoGlobals (void)
185 static void reflectGlobalQualifiers (sRef sr, qualList quals)
187 DPRINTF (("Reflect global qualifiers: %s / %s",
188 sRef_unparseFull (sr), qualList_unparse (quals)));
190 qualList_elements (quals, qel)
192 if (qual_isGlobalQual (qel)) /* undef, killed */
194 sstate oldstate = sRef_getDefState (sr);
195 sstate defstate = sstate_fromQual (qel);
197 if ((oldstate == SS_UNDEFGLOB && defstate == SS_KILLED)
198 || (oldstate == SS_KILLED && defstate == SS_UNDEFGLOB))
200 defstate = SS_UNDEFKILLED;
207 sRef_setDefState (sr, defstate, fileloc_undefined);
208 DPRINTF (("State: %s", sRef_unparseFull (sr)));
210 else if (qual_isAllocQual (qel)) /* out, partial, reldef, etc. */
212 ctype realType = sRef_getType (sr);
213 sstate defstate = sstate_fromQual (qel);
215 if (qual_isRelDef (qel))
217 ; /* okay anywhere */
221 if (!ctype_isAP (realType)
222 && !ctype_isSU (realType)
223 && !ctype_isUnknown (realType)
224 && !ctype_isAbstract (sRef_getType (sr)))
228 message ("Qualifier %s used on non-pointer or struct: %q",
229 qual_unparse (qel), sRef_unparse (sr)));
234 sRef_setDefState (sr, defstate, fileloc_undefined);
236 else if (qual_isNull (qel))
238 sRef_setNullState (sr, NS_POSNULL, fileloc_undefined);
240 else if (qual_isRelNull (qel))
242 sRef_setNullState (sr, NS_RELNULL, fileloc_undefined);
244 else if (qual_isNotNull (qel))
246 sRef_setNullState (sr, NS_MNOTNULL, fileloc_undefined);
250 if (qual_isCQual (qel))
257 message ("Qualifier %s cannot be used in a globals list",
258 qual_unparse (qel)));
261 } end_qualList_elements;
264 sRef clabstract_createGlobal (sRef sr, qualList quals)
268 if (sRef_isValid (sr))
270 res = sRef_copy (sr);
271 DPRINTF (("Reflecting quals: %s / %s", sRef_unparse (sr), qualList_unparse (quals)));
272 reflectGlobalQualifiers (res, quals);
273 DPRINTF (("==> %s", sRef_unparseFull (res)));
277 res = sRef_undefined;
280 qualList_free (quals);
284 extern void declareCIter (cstring name, /*@owned@*/ uentryList params)
288 ue = uentry_makeIter (name,
289 ctype_makeFunction (ctype_void, params),
290 fileloc_copy (g_currentloc));
292 usymtab_supEntry (uentry_makeEndIter (name, fileloc_copy (g_currentloc)));
293 ue = usymtab_supGlobalEntryReturn (ue);
296 extern void nextIterParam (void)
298 llassert (s_processingIterVars);
302 extern int iterParamNo (void)
304 llassert (s_processingIterVars);
305 return saveIterParamNo;
309 ** yucky hacks to put it in the right place
313 makeCurrentParam (idDecl t)
317 saveStoreLoc = fileloc_undefined;
319 /* param number unknown */
321 ue = uentry_makeParam (t, 0);
326 declareUnnamedEnum (enumNameList el)
328 ctype ret = usymtab_enumEnumNameListType (el);
332 if (ctype_isDefined (ret))
335 e = uentry_makeEnumTagLoc (ctype_enumTag (rt), ret);
337 reflectStorageClass (e);
338 usymtab_supGlobalEntry (e);
340 declareEnumList (el, ret, g_currentloc);
341 enumNameList_free (el);
345 ctype ct = ctype_createEnum (fakeTag (), el);
347 e = uentry_makeEnumTagLoc (ctype_enumTag (ctype_realType (ct)), ct);
348 reflectStorageClass (e);
350 e = usymtab_supGlobalEntryReturn (e);
351 rt = uentry_getAbstractType (e);
352 declareEnumList (el, ct, g_currentloc);
359 declareEnum (cstring ename, enumNameList el)
364 llassert (cstring_isDefined (ename));
366 cet = ctype_createEnum (ename, el);
367 e = uentry_makeEnumTagLoc (ename, cet);
368 reflectStorageClass (e);
369 e = usymtab_supGlobalEntryReturn (e);
370 cet = uentry_getType (e);
371 declareEnumList (el, cet, uentry_whereLast (e));
372 return (uentry_getAbstractType (e));
376 declareEnumList (enumNameList el, ctype c, fileloc loc)
378 bool boolnames = FALSE;
379 bool othernames = FALSE;
381 (void) context_getSaveLocation (); /* undefine it */
383 if (context_maybeSet (FLG_NUMENUMMEMBERS))
385 int maxnum = context_getValue (FLG_NUMENUMMEMBERS);
386 int num = enumNameList_size (el);
392 message ("Enumerator %s declared with %d members (limit is set to %d)",
393 ctype_unparse (c), num, maxnum),
398 enumNameList_elements (el, e)
400 uentry ue = usymtab_lookupExposeGlob (e);
401 ctype ct = uentry_getType (ue);
403 llassert (uentry_isEnumConstant (ue));
405 if (ctype_isUnknown (ct))
407 uentry_setType (ue, c);
411 if (cstring_equal (e, context_getFalseName ())
412 || cstring_equal (e, context_getTrueName ()))
418 message ("Enumerator mixes boolean name (%s) with "
421 uentry_whereLast (ue)))
428 uentry_setType (ue, ctype_bool);
429 DPRINTF (("Set type: %s / %s",
430 uentry_unparse (ue), ctype_unparse (ctype_bool)));
438 message ("Enumerator mixes boolean names (%s, %s) with "
439 "non-boolean name: %s",
440 context_getTrueName (),
441 context_getFalseName (),
443 uentry_whereLast (ue)))
452 if (!ctype_match (c, ct))
454 if (ctype_isDirectBool (ct))
456 if (cstring_equal (e, context_getFalseName ())
457 || cstring_equal (e, context_getTrueName ()))
459 DPRINTF (("Here we are!"));
465 message ("Enumerator member %s declared with "
466 "inconsistent type: %s",
467 e, ctype_unparse (c)),
468 uentry_whereLast (ue)))
470 uentry_showWhereSpecifiedExtra
471 (ue, cstring_copy (ctype_unparse (ct)));
479 message ("Enumerator member %s declared with "
480 "inconsistent type: %s",
481 e, ctype_unparse (c)),
482 uentry_whereLast (ue)))
484 uentry_showWhereSpecifiedExtra
485 (ue, cstring_copy (ctype_unparse (ct)));
490 } end_enumNameList_elements;
493 static /*@dependent@*/ uentryList currentParamList;
495 /*drl added 3-28-2002*/
496 /* this function takes a list of paramentar and generates a list
500 /* drl modified 10/23/2002
502 The current semantics are generated constraints of the form MaxSet(p) >= 0 and MaxRead(p) >= 0 for all pointers
503 unless the @out@ annotation has been applied to a parameter, then we only want to generate maxSet(p) > = 0
506 void setImplictfcnConstraints (void)
511 params = currentParamList;
513 if (constraintList_isDefined(implicitFcnConstraints) )
514 constraintList_free(implicitFcnConstraints);
516 implicitFcnConstraints = constraintList_makeNew();
518 uentryList_elements (params, el)
520 DPRINTF((message("setImplictfcnConstraints doing: %s", uentry_unparse(el) ) ));
522 if ( uentry_isVariable (el) )
524 s = uentry_getSref(el);
525 if (sRef_isReference (s) )
528 DPRINTF((message ("%s is a pointer", sRef_unparse(s) ) ));
530 chagned this from MaxSet(s) == 0 to MaxSet(s) >= 0 */
531 c = constraint_makeSRefWriteSafeInt (s, 0);
533 implicitFcnConstraints = constraintList_add(implicitFcnConstraints , c);
535 /*drl 10/23/2002 added support for out*/
537 if (!uentry_isOut(el) )
539 c = constraint_makeSRefReadSafeInt (s, 0);
541 implicitFcnConstraints = constraintList_add(implicitFcnConstraints , c);
546 DPRINTF((message ("%s is NOT a pointer", sRef_unparse(s) ) ));
548 } /*end uentry_isVariable*/
550 else if (uentry_isElipsisMarker (el) )
552 /*just ignore these*/
559 I'm not sure if this is possible though
561 /*@warning take this out befor@*/
566 end_uentryList_elements;
567 DPRINTF((message("implicitFcnConstraints has been set to %s\n",
568 constraintList_print(implicitFcnConstraints) ) ));
573 /*@observer@*/ constraintList getImplicitFcnConstraints (void)
575 return implicitFcnConstraints;
578 void setCurrentParams (/*@dependent@*/ uentryList ue)
580 currentParamList = ue;
583 void clearCurrentParams (void)
585 currentParamList = uentryList_undefined;
589 ** requires: uentry_isFunction (e)
590 ** parameter names for current function are in currentParamList
593 static void enterFunctionParams (uentryList params)
597 uentryList_elements (params, current)
599 if (uentry_hasName (current))
601 uentry_setParamNo (current, paramno);
602 usymtab_supEntry (uentry_copy (current));
606 } end_uentryList_elements;
610 extern void enterParamsTemp (void)
612 usymtab_enterScope ();
613 enterFunctionParams (currentParamList);
616 extern void exitParamsTemp (void)
618 usymtab_quietPlainExitScope ();
621 static /*@exposed@*/ uentry clabstract_globalDeclareFunction (idDecl tid)
623 ctype deftype = idDecl_getCtype (tid);
627 DPRINTF (("Global function: %s", idDecl_unparse (tid)));
629 if (ctype_isFunction (deftype))
631 rettype = ctype_getReturnType (deftype);
635 rettype = ctype_unknown;
639 ** check has been moved here...
642 if (ctype_isFunction (idDecl_getCtype (tid)))
644 ue = uentry_makeIdFunction (tid);
645 reflectSpecialCode (ue);
646 reflectArgsUsed (ue);
647 reflectStorageClass (ue);
648 uentry_checkParams (ue);
650 DPRINTF (("Supercede function: %s", uentry_unparseFull (ue)));
652 ue = usymtab_supGlobalEntryReturn (ue);
653 DPRINTF (("After supercede function: %s", uentry_unparseFull (ue)));
655 DPRINTF (("Enter function: %s", uentry_unparseFull (ue)));
656 context_enterFunction (ue);
657 enterFunctionParams (uentry_getParams (ue));
659 resetStorageClass ();
660 DPRINTF (("Function: %s", uentry_unparseFull (ue)));
665 llparseerror (message ("Non-function declaration: %q",
666 idDecl_unparse (tid)));
667 return (uentry_undefined);
672 ** for now, no type checking
673 ** (must check later though!)
676 static /*@only@*/ uentry globalDeclareOldStyleFunction (idDecl tid)
681 ** check has been moved here...
684 if (cstring_equalLit (idDecl_observeId (tid), "main"))
686 context_setFlagTemp (FLG_MAINTYPE, FALSE);
689 ue = uentry_makeIdFunction (tid);
690 reflectStorageClass (ue);
691 reflectSpecialCode (ue);
692 reflectArgsUsed (ue);
693 uentry_setDefined (ue, g_currentloc);
694 uentry_checkParams (ue);
695 resetStorageClass ();
697 /* context_enterOldStyleScope (); */
702 static void oldStyleDeclareFunction (/*@only@*/ uentry e)
704 uentryList params = saveParamList;
705 ctype rt = uentry_getType (e);
707 llassert (ctype_isFunction (rt));
709 if (uentry_hasStateClauseList (e)
710 || uentry_hasConditions (e))
712 llfatalerror (message ("%q: Old-style function declaration uses a clause (rewrite with function parameters): %q",
713 fileloc_unparse (g_currentloc), uentry_unparse (e)));
716 e = usymtab_supGlobalEntryReturn (e);
718 context_enterFunction (e);
719 enterFunctionParams (params);
720 saveParamList = uentryList_undefined;
721 resetStorageClass ();
724 static void oldStyleCompleteFunction (/*@only@*/ uentry e)
726 uentryList params = saveParamList;
727 ctype rt = uentry_getType (e);
729 llassert (ctype_isFunction (rt));
731 if (uentry_hasStateClauseList (e)
732 || uentry_hasConditions (e))
734 llfatalerror (message ("%q: Old-style function declaration uses a clause (rewrite with function parameters): %q",
735 fileloc_unparse (g_currentloc), uentry_unparse (e)));
738 e = usymtab_supGlobalEntryReturn (e);
740 context_completeOldStyleFunction (e);
741 enterFunctionParams (params);
742 saveParamList = uentryList_undefined;
743 resetStorageClass ();
746 void clabstract_declareFunction (idDecl tid) /*@globals undef saveFunction; @*/
750 DPRINTF (("Declare function: %s", idDecl_unparse (tid)));
752 if (ctype_isUnknown (idDecl_getCtype (tid)))
755 ** No type, its really a plain name (int) declaration
758 voptgenerror (FLG_IMPTYPE,
759 message ("No type before declaration name (implicit int type): %q",
760 idDecl_unparse (tid)),
762 tid = idDecl_replaceCtype (tid, ctype_int);
763 processVariable (tid);
764 saveFunction = uentry_undefined;
768 if (s_processingParams)
770 ue = globalDeclareOldStyleFunction (tid);
772 DPRINTF (("Set save function: %s", uentry_unparseFull (ue)));
776 saveFunction = uentry_undefined;
778 if (context_inRealFunction ())
780 ue = uentry_makeVariableLoc (idDecl_observeId (tid), ctype_unknown);
782 llparseerror (message ("Function declared inside function: %q",
783 idDecl_unparse (tid)));
785 context_quietExitFunction ();
786 ue = usymtab_supEntryReturn (ue);
790 if (context_inInnerScope ())
792 llparseerror (message ("Declaration in inner context: %q",
793 idDecl_unparse (tid)));
795 sRef_setGlobalScope ();
796 ue = uentry_makeVariableLoc (idDecl_observeId (tid),
798 ue = usymtab_supGlobalEntryReturn (ue);
799 sRef_clearGlobalScope ();
803 ue = clabstract_globalDeclareFunction (tid);
810 resetStorageClass ();
816 void declareStaticFunction (idDecl tid) /*@globals undef saveFunction; @*/
820 DPRINTF (("Declare static funciton: %s", idDecl_unparse (tid)));
822 if (s_processingParams)
824 ue = globalDeclareOldStyleFunction (tid);
829 saveFunction = uentry_undefined;
831 if (context_inRealFunction ())
833 ue = uentry_makeVariableLoc (idDecl_observeId (tid), ctype_unknown);
835 llparseerror (message ("Function declared inside function: %q",
836 idDecl_unparse (tid)));
838 context_quietExitFunction ();
839 ue = usymtab_supEntryReturn (ue);
843 if (context_inInnerScope ())
845 llparseerror (message ("Declaration in inner context: %q",
846 idDecl_unparse (tid)));
848 sRef_setGlobalScope ();
849 ue = uentry_makeVariableLoc (idDecl_observeId (tid),
851 ue = usymtab_supGlobalEntryReturn (ue);
852 sRef_clearGlobalScope ();
856 ctype deftype = idDecl_getCtype (tid);
859 if (ctype_isFunction (deftype))
861 rettype = ctype_getReturnType (deftype);
865 rettype = ctype_unknown;
869 ** check has been moved here...
872 if (ctype_isFunction (idDecl_getCtype (tid)))
874 ue = uentry_makeIdFunction (tid);
875 reflectSpecialCode (ue);
876 reflectArgsUsed (ue);
880 DPRINTF (("Here we are!"));
881 llparseerror (message ("Inconsistent function declaration: %q",
882 idDecl_unparse (tid)));
884 tid = idDecl_replaceCtype
885 (tid, ctype_makeFunction (ctype_unknown, uentryList_undefined));
886 ue = uentry_makeIdFunction (tid);
889 reflectStorageClass (ue);
890 uentry_setStatic (ue);
892 uentry_checkParams (ue);
894 DPRINTF (("Sub global entry: %s", uentry_unparse (ue)));
895 ue = usymtab_supGlobalEntryReturn (ue);
897 context_enterFunction (ue);
898 enterFunctionParams (uentry_getParams (ue));
899 resetStorageClass ();
906 resetStorageClass ();
911 checkTypeDecl (uentry e, ctype rep)
913 cstring n = uentry_getName (e);
915 DPRINTF (("Check type decl: %s", uentry_unparseFull (e)));
917 if (cstring_equal (context_getBoolName (), n))
919 ctype rrep = ctype_realType (rep);
922 ** for abstract enum types, we need to fix the enum members:
923 ** they should have the abstract type, not the rep type.
926 if (ctype_isEnum (ctype_realType (rrep)))
928 enumNameList el = ctype_elist (rrep);
930 enumNameList_elements (el, ye)
932 if (usymtab_existsGlob (ye))
934 uentry ue = usymtab_lookupSafe (ye);
935 uentry_setType (ue, ctype_bool);
938 if (cstring_equal (context_getTrueName (), ye)
939 || cstring_equal (context_getFalseName (), ye))
947 message ("Member of boolean enumerated type definition "
948 "does not match name set to represent TRUE "
951 message ("Use -boolfalse and -booltrue to set the "
952 "name of false and true boolean values."),
953 uentry_whereDefined (e));
955 } end_enumNameList_elements;
959 if (usymtab_exists (n))
961 usymId llm = usymtab_getId (n);
962 uentry le = usymtab_getTypeEntry (llm);
964 uentry_setDeclared (e, g_currentloc);
965 uentry_setSref (e, sRef_makeGlobal (llm, uentry_getType (le), stateInfo_currentLoc ()));
967 DPRINTF (("Here we are: %s / %s",
968 n, context_getBoolName ()));
970 if (uentry_isAbstractDatatype (le))
972 ctype rrep = ctype_realType (rep);
974 DPRINTF (("Abstract type: %s", uentry_unparseFull (le)));
977 ** for abstract enum types, we need to fix the enum members:
978 ** they should have the abstract type, not the rep type.
981 if (ctype_isEnum (ctype_realType (rrep)))
983 ctype at = uentry_getAbstractType (le);
984 enumNameList el = ctype_elist (rrep);
986 enumNameList_elements (el, ye)
988 if (usymtab_existsGlob (ye))
990 uentry ue = usymtab_lookupSafe (ye);
992 llassert (uentry_isEitherConstant (ue));
994 /* evans 2002-04-22 */
995 if (ctype_isBool (uentry_getType (ue)))
998 ** If set using -booltrue or -boolfalse, don't change the type.
1003 llassertprint (ctype_match (uentry_getType (ue), rrep),
1004 ("Bad enum: %s / %s",
1005 uentry_unparse (ue),
1006 ctype_unparse (rrep)));
1008 uentry_setType (ue, at);
1011 } end_enumNameList_elements;
1014 if (uentry_isMutableDatatype (le))
1016 /* maybe more complicated if abstract and immutable ? */
1018 if (!ctype_isRealPointer (rep) && !ctype_isRealAbstract (rep))
1022 message ("Mutable abstract type %s declared without pointer "
1023 "indirection: %s (violates assignment semantics)",
1024 n, ctype_unparse (rep)),
1025 uentry_whereDefined (e));
1027 uentry_setMutable (e);
1034 fileloc fl = uentry_whereDeclared (e);
1036 if (context_getFlag (FLG_LIKELYBOOL)
1037 && !context_getFlag (FLG_BOOLINT))
1039 if ((cstring_equalLit (n, "BOOL")
1040 || cstring_equalLit (n, "Bool")
1041 || cstring_equalLit (n, "bool")
1042 || cstring_equalLit (n, "boolean")
1043 || cstring_equalLit (n, "Boolean")
1044 || cstring_equalLit (n, "BOOLEAN"))
1045 && !(cstring_equal (n, context_getBoolName ())))
1047 if (context_setBoolName ()) {
1050 message ("Type %s is probably meant as a boolean type, but does "
1051 "not match the boolean type name \"%s\".",
1053 context_getBoolName ()),
1058 message ("Type %s is probably meant as a boolean type, "
1059 "but the boolean type name is not set. "
1060 "Use -booltype %s to set it.",
1067 if (!uentry_isStatic (e)
1068 && !ctype_isFunction (uentry_getType (e))
1069 && !fileloc_isLib (fl)
1070 && !fileloc_isImport (fl)
1071 && fileloc_isHeader (fl))
1073 voptgenerror (FLG_EXPORTTYPE,
1074 message ("Type exported, but not specified: %s\n", n),
1083 fixUentryList (idDeclList tl, qtype q)
1085 uentryList f = uentryList_new ();
1087 idDeclList_elements (tl, i)
1089 if (idDecl_isDefined (i))
1095 (void) idDecl_fixBase (i, q);
1098 ** implicit annotations
1101 (void) fixStructDecl (i);
1103 ue = uentry_makeIdVariable (i);
1104 rt = ctype_realType (uentry_getType (ue));
1107 ** where is this here???
1109 if (ctype_isArray (rt) || ctype_isSU (rt))
1111 sRef_setAllocated (uentry_getSref (ue), uentry_whereDefined (ue));
1117 if (uentry_isValid (old = uentryList_lookupField (f, uentry_rawName (ue))))
1119 if (optgenerror (FLG_SYNTAX,
1120 message ("Field name reused: %s", uentry_rawName (ue)),
1121 uentry_whereDefined (ue)))
1123 llgenmsg (message ("Previous use of %s", uentry_rawName (ue)),
1124 uentry_whereDefined (old));
1128 f = uentryList_add (f, ue);
1130 } end_idDeclList_elements;
1132 idDeclList_free (tl);
1137 ** This is a hack to support unnamed struct/union fields as done by
1138 ** Microsoft VC++. It is not supported by the ANSI standard.
1140 ** The inner fields are added to the outer structure. This is meaningful
1141 ** for nesting structs inside unions, but Splint does no related
1146 fixUnnamedDecl (qtype q)
1148 ctype ct = ctype_realType (qtype_getType (q));
1150 if (ctype_isStruct (ct) || ctype_isUnion (ct))
1152 return uentryList_single (uentry_makeUnnamedVariable (ct));
1154 else if (ctype_isEnum (ct))
1156 /* evans 2002-02-05: nothing to do for unnamed enum lists */
1157 return uentryList_undefined;
1163 message ("Type name in field declarations: %s", qtype_unparse (q)),
1167 return uentryList_undefined;
1170 void setStorageClass (storageClassCode sc)
1176 setProcessingIterVars (uentry iter)
1178 s_processingIterVars = TRUE;
1180 saveIterParamNo = 0;
1184 setProcessingGlobalsList ()
1186 s_processingGlobals = TRUE;
1187 fcnNoGlobals = FALSE;
1190 static bool ProcessingGlobMods = FALSE;
1193 setProcessingGlobMods ()
1195 ProcessingGlobMods = TRUE;
1199 clearProcessingGlobMods ()
1201 ProcessingGlobMods = FALSE;
1205 isProcessingGlobMods ()
1207 return (ProcessingGlobMods);
1210 static void resetGlobals (void)
1212 s_processingGlobals = FALSE;
1213 fcnNoGlobals = FALSE;
1217 unsetProcessingGlobals ()
1219 s_processingGlobals = FALSE;
1223 setProcessingVars (/*@only@*/ qtype q)
1225 s_processingVars = TRUE;
1226 qtype_free (processingType);
1231 setGenericParamList (/*@dependent@*/ uentryList pm)
1233 s_processingParams = TRUE;
1238 setProcessingTypedef (qtype q)
1240 s_processingTypedef = TRUE;
1242 qtype_free (processingType);
1247 unsetProcessingVars ()
1249 resetStorageClass ();
1250 s_processingVars = FALSE;
1254 oldStyleDoneParams ()
1256 if (s_processingParams)
1258 if (uentry_isInvalid (saveFunction))
1260 llbuglit ("unsetProcessingVars: no saved function\n");
1264 ctype ct = ctype_getReturnType (uentry_getType (saveFunction));
1265 uentryList params = uentryList_copy (saveParamList);
1266 ctype ct2 = ctype_makeFunction (ct, params);
1268 uentry_setType (saveFunction, ct2);
1269 s_processingParams = FALSE;
1271 oldStyleCompleteFunction (saveFunction);
1272 saveFunction = uentry_undefined;
1279 ** If the paramlist used a type name, we could be here.
1282 llfatalerror (message ("%q: Old-style function parameter list uses a "
1283 "type name.", fileloc_unparse (g_currentloc)));
1290 if (uentry_isValid (saveFunction))
1293 ** old style declaration
1296 ctype ct = ctype_getReturnType (uentry_getType (saveFunction));
1299 DPRINTF (("save function: %s", uentry_unparseFull (saveFunction)));
1301 uentryList_elements (saveParamList, current)
1303 uentry_setType (current, ctype_int); /* all params are ints */
1304 } end_uentryList_elements;
1306 ct2 = ctype_makeParamsFunction (ct, uentryList_copy (saveParamList));
1308 uentry_setType (saveFunction, ct2);
1309 s_processingParams = FALSE;
1311 oldStyleDeclareFunction (saveFunction);
1312 saveFunction = uentry_undefined;
1316 void clabstract_declareType (/*@only@*/ exprNodeList decls, /*@only@*/ warnClause warn)
1318 llassert (s_processingTypedef);
1320 DPRINTF (("Declare type: %s", exprNodeList_unparse (decls)));
1322 if (warnClause_isDefined (warn))
1324 DPRINTF (("Has a warn clause!"));
1325 DPRINTF (("Warn: %s", warnClause_unparse (warn)));
1327 exprNodeList_elements (decls, el)
1329 uentry ue = exprNode_getUentry (el);
1330 cstring uname = uentry_getName (ue);
1332 DPRINTF (("Entry: %s", exprNode_unparse (el)));
1335 ** Need to lookup again to make sure we have the right one...
1338 ue = usymtab_lookupExposeGlob (uname);
1340 llassert (uentry_isValid (ue));
1341 llassert (uentry_isDatatype (ue));
1343 DPRINTF (("Warning for %s: %s",
1344 uentry_unparse (ue), warnClause_unparse (warn)));
1346 uentry_addWarning (ue, warnClause_copy (warn));
1347 DPRINTF (("After add warning: %s", uentry_unparseFull (ue)));
1348 cstring_free (uname);
1349 } end_exprNodeList_elements;
1352 warnClause_free (warn);
1353 exprNodeList_free (decls);
1354 unsetProcessingTypedef ();
1358 unsetProcessingTypedef ()
1360 s_processingTypedef = FALSE;
1363 void checkConstant (qtype t, idDecl id)
1367 id = idDecl_fixBase (id, t);
1368 e = uentry_makeIdConstant (id);
1370 reflectStorageClass (e);
1371 resetStorageClass ();
1373 DPRINTF (("Constant: %s", uentry_unparseFull (e)));
1374 usymtab_supGlobalEntry (e);
1377 void checkValueConstant (qtype t, idDecl id, exprNode e)
1381 id = idDecl_fixBase (id, t);
1382 ue = uentry_makeIdConstant (id);
1383 reflectStorageClass (ue);
1384 resetStorageClass ();
1386 if (exprNode_isDefined (e))
1388 if (!exprNode_matchType (uentry_getType (ue), e))
1391 (exprNode_getType (e), e,
1392 uentry_getType (ue), exprNode_undefined,
1393 message ("Constant %q initialized to type %t, expects %t: %s",
1394 uentry_getName (ue),
1395 exprNode_getType (e),
1396 uentry_getType (ue),
1397 exprNode_unparse (e)),
1402 if (exprNode_hasValue (e))
1404 uentry_mergeConstantValue (ue, multiVal_copy (exprNode_getValue (e)));
1408 DPRINTF (("No value: %s", exprNode_unparse (e)));
1413 DPRINTF (("Constant value: %s", uentry_unparseFull (ue)));
1414 usymtab_supGlobalEntry (ue);
1417 static void processVariable (idDecl t)
1422 ct = ctype_realType (idDecl_getCtype (t));
1424 if (s_processingParams)
1426 cstring id = idDecl_getName (t);
1427 int paramno = uentryList_lookupRealName (saveParamList, id);
1431 uentry cparam = uentryList_getN (saveParamList, paramno);
1433 DPRINTF (("Processing param: %s", uentry_unparseFull (cparam)));
1434 uentry_setType (cparam, idDecl_getCtype (t));
1435 uentry_reflectQualifiers (cparam, idDecl_getQuals (t));
1436 uentry_setDeclaredOnly (cparam, context_getSaveLocation ());
1437 DPRINTF (("Processing param: %s", uentry_unparseFull (cparam)));
1442 (message ("Old style declaration uses unlisted parameter: %s",
1450 if (context_inIterDef ())
1452 cstring pname = makeParam (idDecl_observeId (t));
1453 uentry p = usymtab_lookupSafe (pname);
1455 cstring_free (pname);
1457 if (uentry_isYield (p))
1459 e = uentry_makeParam (t, sRef_getParam (uentry_getSref (p)));
1460 uentry_checkYieldParam (p, e);
1461 usymtab_supEntrySref (e);
1466 if ((hasSpecialCode () || argsUsed)
1467 && ctype_isFunction (idDecl_getCtype (t)))
1469 e = uentry_makeIdFunction (t);
1470 reflectSpecialCode (e);
1471 reflectArgsUsed (e);
1475 e = uentry_makeIdVariable (t);
1478 loc = uentry_whereDeclared (e);
1481 if (context_inGlobalScope ())
1483 uentry_checkParams was here!
1487 if (ctype_isFunction (uentry_getType (e)))
1489 clabstract_prepareFunction (e);
1492 DPRINTF (("Superceding... %s", uentry_unparseFull (e)));
1493 e = usymtab_supEntrySrefReturn (e);
1494 DPRINTF (("After superceding... %s", uentry_unparseFull (e)));
1496 if (uentry_isExtern (e) && !context_inGlobalScope ())
1500 message ("Declaration using extern inside function scope: %q",
1501 uentry_unparse (e)),
1504 uentry_setDefined (e, fileloc_getExternal ());
1505 sRef_setDefined (uentry_getSref (e), fileloc_getExternal ());
1508 if (uentry_isFunction (e))
1510 if (!context_inXHFile ())
1512 checkParamNames (e);
1516 if (uentry_isVar (e) && uentry_isCheckedUnknown (e))
1518 sRef sr = uentry_getSref (e);
1520 if (sRef_isLocalVar (sr))
1522 if (context_getFlag (FLG_IMPCHECKMODINTERNALS))
1524 uentry_setCheckMod (e);
1528 uentry_setUnchecked (e);
1531 else if (sRef_isFileStatic (sr))
1533 if (context_getFlag (FLG_IMPCHECKEDSTRICTSTATICS))
1535 uentry_setCheckedStrict (e);
1537 else if (context_getFlag (FLG_IMPCHECKEDSTATICS))
1539 uentry_setChecked (e);
1541 else if (context_getFlag (FLG_IMPCHECKMODSTATICS))
1543 uentry_setCheckMod (e);
1550 else /* real global */
1552 llassert (sRef_isRealGlobal (sr));
1554 if (context_getFlag (FLG_IMPCHECKEDSTRICTGLOBALS))
1556 uentry_setCheckedStrict (e);
1558 else if (context_getFlag (FLG_IMPCHECKEDGLOBALS))
1560 uentry_setChecked (e);
1562 else if (context_getFlag (FLG_IMPCHECKMODGLOBALS))
1564 uentry_setCheckMod (e);
1575 void processNamedDecl (idDecl t)
1577 if (qtype_isUndefined (processingType))
1579 processingType = qtype_create (ctype_int);
1580 t = idDecl_fixBase (t, processingType);
1582 voptgenerror (FLG_IMPTYPE,
1583 message ("No type before declaration name (implicit int type): %q",
1584 idDecl_unparse (t)),
1589 t = idDecl_fixBase (t, processingType);
1592 DPRINTF (("Declare: %s", idDecl_unparse (t)));
1594 if (s_processingGlobals)
1596 cstring id = idDecl_getName (t);
1597 uentry ue = usymtab_lookupSafe (id);
1599 if (!uentry_isValid (ue))
1601 llerror (FLG_UNRECOG,
1602 message ("Variable used in globals list is undeclared: %s", id));
1606 if (!ctype_match (uentry_getType (ue), idDecl_getCtype (t)))
1610 message ("Variable %s used in globals list declared %s, "
1612 id, ctype_unparse (uentry_getType (ue)),
1613 ctype_unparse (idDecl_getCtype (t))),
1618 sRef sr = sRef_copy (uentry_getSref (ue));
1619 reflectGlobalQualifiers (sr, idDecl_getQuals (t));
1623 else if (s_processingVars)
1625 processVariable (t);
1627 else if (s_processingTypedef)
1629 ctype ct = idDecl_getCtype (t);
1632 DPRINTF (("Processing typedef: %s", ctype_unparse (ct)));
1634 e = uentry_makeIdDatatype (t);
1636 if (cstring_equal (idDecl_getName (t), context_getBoolName ())) {
1637 ctype rt = ctype_realType (ct);
1639 if (ctype_isEnum (rt)) {
1642 if (!(ctype_isInt (rt)
1643 || ctype_isUnknown (rt)
1644 || ctype_isChar (rt))) {
1647 message ("Boolean type %s defined using non-standard type %s (integral, char or enum type expected)",
1648 context_getBoolName (),
1649 ctype_unparse (ct)),
1650 uentry_whereLast (e));
1654 uentry_setType (e, ct);
1658 reflectStorageClass (e);
1659 checkTypeDecl (e, ct);
1661 e = usymtab_supReturnTypeEntry (e);
1665 llparseerror (message ("Suspect missing struct or union keyword: %q",
1666 idDecl_unparse (t)));
1672 ** moved from grammar
1675 static idDecl fixStructDecl (/*@returned@*/ idDecl d)
1677 if (ctype_isVisiblySharable (idDecl_getCtype (d))
1678 && context_getFlag (FLG_STRUCTIMPONLY))
1680 if (!qualList_hasAliasQualifier (idDecl_getQuals (d)))
1682 if (qualList_hasExposureQualifier (idDecl_getQuals (d)))
1684 idDecl_addQual (d, qual_createDependent ());
1688 idDecl_addQual (d, qual_createImpOnly ());
1697 declareUnnamedStruct (/*@only@*/ uentryList f)
1699 DPRINTF (("Unnamed struct: %s", uentryList_unparse (f)));
1701 if (context_maybeSet (FLG_NUMSTRUCTFIELDS))
1703 int num = uentryList_size (f);
1704 int max = context_getValue (FLG_NUMSTRUCTFIELDS);
1709 (FLG_NUMSTRUCTFIELDS,
1710 message ("Structure declared with %d fields "
1711 "(limit is set to %d)",
1717 return (ctype_createUnnamedStruct (f));
1721 declareUnnamedUnion (/*@only@*/ uentryList f)
1723 DPRINTF (("Unnamed union: %s", uentryList_unparse (f)));
1725 if (context_maybeSet (FLG_NUMSTRUCTFIELDS))
1727 int num = uentryList_size (f);
1728 int max = context_getValue (FLG_NUMSTRUCTFIELDS);
1733 (FLG_NUMSTRUCTFIELDS,
1734 message ("Union declared with %d fields "
1735 "(limit is set to %d)",
1741 return (ctype_createUnnamedUnion (f));
1744 ctype declareStruct (cstring id, /*@only@*/ uentryList f)
1748 int num = uentryList_size (f);
1750 DPRINTF (("Declare struct: %s / %s [%d]", id, uentryList_unparse (f),
1751 uentryList_size (f)));
1753 ct = ctype_createStruct (cstring_copy (id), f);
1755 DPRINTF (("Ctype: %s", ctype_unparse (ct)));
1757 ue = uentry_makeStructTagLoc (id, ct);
1759 DPRINTF (("ue: %s", uentry_unparseFull (ue)));
1761 if (context_maybeSet (FLG_NUMSTRUCTFIELDS))
1763 int max = context_getValue (FLG_NUMSTRUCTFIELDS);
1768 (FLG_NUMSTRUCTFIELDS,
1769 message ("Structure %q declared with %d fields "
1770 "(limit is set to %d)",
1771 uentry_getName (ue), num, max),
1772 uentry_whereLast (ue));
1776 return (usymtab_supTypeEntry (ue));
1779 ctype declareUnion (cstring id, uentryList f)
1783 int num = uentryList_size (f);
1785 ct = ctype_createUnion (cstring_copy (id), f);
1786 ue = uentry_makeUnionTagLoc (id, ct);
1788 if (context_maybeSet (FLG_NUMSTRUCTFIELDS))
1790 int max = context_getValue (FLG_NUMSTRUCTFIELDS);
1795 (FLG_NUMSTRUCTFIELDS,
1796 message ("Union %q declared with %d fields "
1797 "(limit is set to %d)",
1798 uentry_getName (ue), num, max),
1799 uentry_whereLast (ue));
1803 return (usymtab_supTypeEntry (ue));
1806 ctype handleStruct (/*@only@*/ cstring id)
1808 if (usymtab_existsStructTag (id))
1810 ctype ct = uentry_getAbstractType (usymtab_lookupStructTag (id));
1817 return (ctype_createForwardStruct (id));
1821 ctype handleUnion (/*@only@*/ cstring id)
1823 if (usymtab_existsUnionTag (id))
1825 ctype ret = uentry_getAbstractType (usymtab_lookupUnionTag (id));
1831 return (ctype_createForwardUnion (id));
1836 handleEnum (cstring id)
1838 if (usymtab_existsEnumTag (id))
1840 ctype ret = uentry_getAbstractType (usymtab_lookupEnumTag (id));
1846 return (ctype_createForwardEnum (id));
1850 bool processingIterVars (void)
1852 return s_processingIterVars;
1855 uentry getCurrentIter (void)
1860 static bool flipOldStyle = FALSE;
1861 static bool flipNewStyle = TRUE;
1863 void setFlipOldStyle () { flipOldStyle = TRUE; }
1864 bool isFlipOldStyle () { return flipOldStyle; }
1865 bool isNewStyle () { return flipNewStyle; }
1866 void setNewStyle () { flipNewStyle = TRUE; }
1868 /*@dependent@*/ uentryList handleParamIdList (/*@dependent@*/ uentryList params)
1873 ** this is a really YUCKY hack to handle old style
1877 voptgenerror (FLG_OLDSTYLE,
1878 cstring_makeLiteral ("Old style function declaration"),
1881 DPRINTF (("Handle old style params: %s", uentryList_unparseFull (params)));
1883 uentryList_elements (params, current)
1885 uentry_setParam (current);
1886 uentry_setSref (current, sRef_makeParam
1887 (paramno, ctype_unknown,
1888 stateInfo_makeLoc (uentry_whereLast (current), SA_DECLARED)));
1890 } end_uentryList_elements;
1892 setGenericParamList (params);
1893 cscannerHelp_setExpectingTypeName ();
1898 /*@dependent@*/ uentryList handleParamTypeList (/*@returned@*/ uentryList params)
1902 uentryList_fixMissingNames (params);
1904 voptgenerror (FLG_OLDSTYLE,
1905 cstring_makeLiteral ("Old style function declaration."),
1908 setGenericParamList (params);
1909 flipOldStyle = FALSE;
1910 cscannerHelp_setExpectingTypeName ();
1919 ctype c = ctype_unknown;
1920 cstring id = cstring_makeLiteral ("va_alist");
1923 if (s_processingParams)
1925 int i = uentryList_lookupRealName (saveParamList, id);
1929 fileloc loc = context_getSaveLocation ();
1930 e = uentry_makeVariableSrefParam
1932 sRef_makeParam (i, c, stateInfo_makeLoc (loc, SA_DECLARED)));
1936 e = uentry_undefined; /* suppress gcc message */
1937 llfatalerrorLoc (cstring_makeLiteral ("va_dcl used without va_alist"));
1942 llerror (FLG_SYNTAX, cstring_makeLiteral ("va_dcl used outside of function declaration"));
1943 e = uentry_makeVariableLoc (id, c);
1947 uentry_setUsed (e, g_currentloc);
1948 usymtab_supEntrySref (e);
1951 /*@exposed@*/ sRef modListPointer (/*@exposed@*/ sRef s)
1953 ctype ct = sRef_getType (s);
1954 ctype rt = ctype_realType (ct);
1956 if (ctype_isAP (rt))
1958 if (context_inHeader () && ctype_isAbstract (ct))
1963 ("Modifies clause in header file dereferences abstract "
1964 "type %s (interface modifies clause should not depend "
1965 "on or expose type representation): %q",
1971 return (sRef_constructPointer (s));
1975 if (ctype_isKnown (rt))
1979 message ("Implementation modifies clause dereferences non-pointer (type %s): %q",
1989 /*@exposed@*/ sRef modListFieldAccess (sRef s, cstring f)
1991 ctype ct = sRef_getType (s);
1992 ctype rt = ctype_realType (ct);
1994 if (ctype_isStructorUnion (rt))
1996 uentry tf = uentryList_lookupField (ctype_getFields (rt), f);
1998 if (uentry_isUndefined (tf))
2000 voptgenerror (FLG_TYPE,
2001 message ("Modifies list accesses non-existent "
2002 "field %s of %t: %q", f, ct,
2007 return sRef_undefined;
2011 if (ctype_isAbstract (ct) && context_inHeader ())
2016 ("Modifies clause in header file accesses abstract "
2017 "type %s (interface modifies clause should not depend "
2018 "on or expose type representation): %q",
2025 cstring_markOwned (f);
2026 return (sRef_makeField (s, f));
2032 message ("Modifies clause dereferences non-pointer (type %s): %q",
2042 /*@dependent@*/ sRef clabstract_unrecognizedGlobal (cstring s)
2044 if (cstring_equalLit (s, "nothing"))
2046 return sRef_makeNothing ();
2048 else if (cstring_equalLit (s, "internalState"))
2050 return sRef_makeInternalState ();
2052 else if (cstring_equalLit (s, "fileSystem")
2053 || cstring_equalLit (s, "systemState"))
2055 return sRef_makeSystemState ();
2061 message ("Unrecognized identifier in globals list: %s", s),
2064 return sRef_undefined;
2068 /*@exposed@*/ sRef modListArrowAccess (sRef s, cstring f)
2070 ctype ct = sRef_getType (s);
2071 ctype rt = ctype_realType (ct);
2073 if (ctype_isRealPointer (rt))
2075 ctype b = ctype_baseArrayPtr (rt);
2076 ctype rb = ctype_realType (b);
2078 if (ctype_isStructorUnion (rb))
2080 uentry tf = uentryList_lookupField (ctype_getFields (rb), f);
2082 if (uentry_isUndefined (tf))
2084 voptgenerror (FLG_TYPE,
2085 message ("Modifies list arrow accesses non-existent "
2086 "field %s of %t: %q", f, b,
2091 return sRef_undefined;
2095 if (context_inHeader ())
2097 if (ctype_isAbstract (b))
2102 ("Modifies clause in header file arrow accesses abstract "
2103 "type %s (interface modifies clause should not depend "
2104 "on or expose type representation): %q",
2112 if (ctype_isAbstract (rt))
2117 ("Modifies clause arrow accesses inaccessible abstract "
2118 "type %s (interface modifies clause should not depend "
2119 "on or expose type representation): %q",
2127 cstring_markOwned (f);
2128 return (sRef_makeArrow (s, f));
2134 message ("Modifies clause arrow accesses pointer to "
2135 "non-structure (type %s): %q",
2145 message ("Modifies clause arrow accesses non-pointer (type %s): %q",
2155 sRef checkStateClausesId (uentry ue)
2157 cstring s = uentry_rawName (ue);
2159 if (sRef_isFileOrGlobalScope (uentry_getSref (ue)))
2163 message ("Global variable %s used state clause. (Global variables "
2164 "are not recognized in state clauses. If there is "
2165 "sufficient interest in support for this, it may be "
2166 "added to a future release. Send mail to "
2167 "info@splint.org.)",
2171 return sRef_undefined;
2175 if (cstring_equalLit (s, "result"))
2179 message ("Special clause list uses %s which is a variable and has special "
2180 "meaning in a modifies list. (Special meaning assumed.)", s),
2183 uentry_showWhereDeclared (ue);
2187 return uentry_getSref (ue);
2193 don;t know what the real date is...
2199 based on checkSpecClausesId
2203 sRef checkbufferConstraintClausesId (uentry ue)
2206 cstring s = uentry_rawName (ue);
2208 if (cstring_equalLit (s, "result"))
2212 message ("Function clause list uses %s which is a variable and has special "
2213 "meaning in a modifies list. (Special meaning assumed.)", s),
2216 uentry_showWhereDeclared (ue);
2220 DPRINTF (("constraint id: %s", uentry_unparseFull (ue)));
2221 sr = uentry_getSref (ue);
2223 if (sRef_isInvalid (sr) )
2225 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." ));
2227 return sRef_saveCopy (sr); /*@i523 why the saveCopy? */
2230 void checkModifiesId (uentry ue)
2232 cstring s = uentry_rawName (ue);
2234 if (cstring_equalLit (s, "nothing")
2235 || cstring_equalLit (s, "internalState")
2236 || cstring_equalLit (s, "systemState")
2237 || (cstring_equalLit (s, "fileSystem")))
2241 message ("Modifies list uses %s which is a variable and has special "
2242 "meaning in a modifies list. (Special meaning assumed.)", s),
2245 uentry_showWhereDeclared (ue);
2250 /*@exposed@*/ sRef fixModifiesId (cstring s)
2253 cstring pname = makeParam (s);
2254 uentry ue = usymtab_lookupSafe (pname);
2256 cstring_free (pname);
2258 if (cstring_equalLit (s, "nothing"))
2260 ret = sRef_makeNothing ();
2262 else if (cstring_equalLit (s, "internalState"))
2264 ret = sRef_makeInternalState ();
2266 else if (cstring_equalLit (s, "fileSystem")
2267 || cstring_equalLit (s, "systemState"))
2269 ret = sRef_makeSystemState ();
2273 ret = sRef_undefined;
2276 if (sRef_isValid (ret))
2278 if (uentry_isValid (ue))
2282 message ("Modifies list uses %s which is a parameter and has special "
2283 "meaning in a modifies list. (Special meaning assumed.)", s),
2289 if (uentry_isValid (ue))
2291 ret = uentry_getSref (ue);
2295 fileloc loc = fileloc_decColumn (g_currentloc, size_toInt (cstring_length (s)));
2296 ret = sRef_undefined;
2300 message ("Unrecognized identifier in modifies comment: %s", s),
2310 sRef fixStateClausesId (cstring s)
2313 cstring pname = makeParam (s);
2314 uentry ue = usymtab_lookupSafe (pname);
2316 cstring_free (pname);
2318 if (cstring_equalLit (s, "result"))
2320 ret = sRef_makeResult (ctype_unknown);
2324 ret = sRef_undefined;
2327 if (sRef_isValid (ret))
2329 if (uentry_isValid (ue))
2333 message ("Function clause uses %s which is a parameter and has special "
2334 "meaning in a function clause. (Special meaning assumed.)", s),
2340 if (uentry_isValid (ue))
2342 ret = uentry_getSref (ue);
2344 if (sRef_isFileOrGlobalScope (ret))
2348 message ("Global variable %s used in function clause. (Global variables "
2349 "are not recognized in function clauses. If there is "
2350 "sufficient interest in support for this, it may be "
2351 "added to a future release. Send mail to "
2352 "info@splint.org.)",
2356 ret = sRef_undefined;
2362 /*drl handle structure invariant */
2365 /*check that we're in a structure */
2367 /*@unused@*/ uentryList ueL;
2368 /*@unused@*/ uentry ue2;
2369 /*@unused@*/ ctype ct;
\r
2371 fileloc loc = fileloc_decColumn (g_currentloc, size_toInt (cstring_length (s)));
2372 ret = sRef_undefined;
2374 /*drl commenting this out for now
2375 ct = context_getLastStruct ( ct );
2377 llassert( ctype_isStruct(ct) );
2379 ueL = ctype_getFields (ct);
2381 ue2 = uentryList_lookupField (ueL, s);
2383 if (!uentry_isUndefined(ue2) )
2385 ret = uentry_getSref(ue2);
2388 message("Got field in structure in the annotation constraint: %s (or sref: %s)", s, sRef_unparse(ret) )
2398 message ("Unrecognized identifier in function clause: %s", s),
2408 sRef modListArrayFetch (/*@exposed@*/ sRef s, /*@unused@*/ sRef mexp)
2410 ctype ct = sRef_getType (s);
2411 ctype rt = ctype_realType (ct);
2413 if (ctype_isAP (rt))
2415 if (context_inHeader () && ctype_isAbstract (ct))
2420 ("Modifies clause in header file indexes abstract "
2421 "type %s (interface modifies clause should not depend "
2422 "on or expose type representation): %q",
2428 return (sRef_makeAnyArrayFetch (s));
2435 ("Implementation modifies clause uses array fetch on non-array (type %s): %q",
2436 ctype_unparse (ct), sRef_unparse (s)),
2442 static void clabstract_prepareFunction (uentry e)
2444 uentry_checkParams (e);
2445 DPRINTF (("After prepare: %s", uentry_unparseFull (e)));
2448 sRef clabstract_checkGlobal (exprNode e)
2451 llassert (exprNode_isInitializer (e));
2453 s = exprNode_getSref (e);
2454 DPRINTF (("Initializer: %s -> %s", exprNode_unparse (e), sRef_unparse (s)));
2457 return sRef_copy (s);