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