2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2002 University of Virginia,
4 ** Massachusetts Institute of Technology
6 ** This program is free software; you can redistribute it and/or modify it
7 ** under the terms of the GNU General Public License as published by the
8 ** Free Software Foundation; either version 2 of the License, or (at your
9 ** option) any later version.
11 ** This program is distributed in the hope that it will be useful, but
12 ** WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 ** General Public License for more details.
16 ** The GNU General Public License is available from http://www.gnu.org/ or
17 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 ** MA 02111-1307, USA.
20 ** For information on splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
31 # include "splintMacros.nf"
33 # include "cgrammar.h"
36 # include "usymtab_interface.h"
39 # include "structNames.h"
40 # include "nameChecks.h"
43 # include "sgrammar_tokens.h"
45 # include "cgrammar_tokens.h"
49 ** Lots of variables are needed because of interactions with the
50 ** parser. This is easier than restructuring the grammar so the
51 ** right values are available in the right place.
55 static /*@only@*/ constraintList implicitFcnConstraints = NULL;
57 static void clabstract_prepareFunction (uentry p_e) /*@modifies p_e@*/ ;
58 static bool fcnNoGlobals = FALSE;
59 static bool ProcessingVars = FALSE;
60 static bool ProcessingParams = FALSE;
61 static bool ProcessingGlobals = FALSE;
62 static bool ProcessingTypedef = FALSE;
63 static bool ProcessingIterVars = FALSE;
64 static /*@only@*/ qtype processingType = qtype_undefined;
65 static uentry currentIter = uentry_undefined;
66 static /*@dependent@*/ uentryList saveParamList; /* for old style functions */
67 static /*@owned@*/ uentry saveFunction = uentry_undefined;
68 static int saveIterParamNo;
69 static idDecl fixStructDecl (/*@returned@*/ idDecl p_d);
70 static void checkTypeDecl (uentry p_e, ctype p_rep);
71 static /*@dependent@*/ fileloc saveStoreLoc = fileloc_undefined;
72 static storageClassCode storageClass = SCNONE;
73 static void declareEnumList (/*@temp@*/ enumNameList p_el, ctype p_c, fileloc p_loc);
74 static void resetGlobals (void);
75 static /*@null@*/ qual specialFunctionCode;
76 static bool argsUsed = FALSE;
78 extern void clabstract_initMod ()
80 specialFunctionCode = qual_createUnknown ();
81 DPRINTF (("Initialized: %s", qual_unparse (specialFunctionCode)));
84 static bool hasSpecialCode (void)
86 return (!qual_isUnknown (specialFunctionCode));
89 extern void setArgsUsed (void)
95 cstring_makeLiteral ("Multiple ARGSUSED comments for one function"),
102 static void reflectArgsUsed (uentry ue)
106 if (uentry_isFunction (ue))
108 uentryList params = uentry_getParams (ue);
110 uentryList_elements (params, el)
112 uentry_setUsed (el, fileloc_undefined);
113 } end_uentryList_elements ;
120 extern void setSpecialFunction (qual qu)
122 if (!qual_isUnknown (specialFunctionCode))
124 voptgenerror (FLG_SYNTAX,
125 message ("Multiple special function codes: %s, %s "
126 "(first code is ignored)",
127 qual_unparse (specialFunctionCode),
132 specialFunctionCode = qu;
135 static void reflectSpecialCode (uentry ue)
137 if (qual_isUnknown (specialFunctionCode)) {
139 } else if (qual_isPrintfLike (specialFunctionCode)) {
140 uentry_setPrintfLike (ue);
141 } else if (qual_isScanfLike (specialFunctionCode)) {
142 uentry_setScanfLike (ue);
143 } else if (qual_isMessageLike (specialFunctionCode)) {
144 uentry_setMessageLike (ue);
149 specialFunctionCode = qual_createUnknown ();
152 static void resetStorageClass (void)
154 qtype_free (processingType);
155 processingType = qtype_undefined;
156 storageClass = SCNONE;
159 static void reflectStorageClass (uentry u)
161 if (storageClass == SCSTATIC)
163 uentry_setStatic (u);
165 else if (storageClass == SCEXTERN)
167 uentry_setExtern (u);
171 ; /* no storage class */
178 saveStoreLoc = g_currentloc;
181 void setFunctionNoGlobals (void)
186 static void reflectGlobalQualifiers (sRef sr, qualList quals)
188 DPRINTF (("Reflect global qualifiers: %s / %s",
189 sRef_unparseFull (sr), qualList_unparse (quals)));
191 qualList_elements (quals, qel)
193 if (qual_isGlobalQual (qel)) /* undef, killed */
195 sstate oldstate = sRef_getDefState (sr);
196 sstate defstate = sstate_fromQual (qel);
198 if ((oldstate == SS_UNDEFGLOB && defstate == SS_KILLED)
199 || (oldstate == SS_KILLED && defstate == SS_UNDEFGLOB))
201 defstate = SS_UNDEFKILLED;
208 sRef_setDefState (sr, defstate, fileloc_undefined);
209 DPRINTF (("State: %s", sRef_unparseFull (sr)));
211 else if (qual_isAllocQual (qel)) /* out, partial, reldef, etc. */
213 ctype realType = sRef_getType (sr);
214 sstate defstate = sstate_fromQual (qel);
216 if (qual_isRelDef (qel))
218 ; /* okay anywhere */
222 if (!ctype_isAP (realType)
223 && !ctype_isSU (realType)
224 && !ctype_isUnknown (realType)
225 && !ctype_isAbstract (sRef_getType (sr)))
229 message ("Qualifier %s used on non-pointer or struct: %q",
230 qual_unparse (qel), sRef_unparse (sr)));
235 sRef_setDefState (sr, defstate, fileloc_undefined);
237 else if (qual_isNull (qel))
239 sRef_setNullState (sr, NS_POSNULL, fileloc_undefined);
241 else if (qual_isRelNull (qel))
243 sRef_setNullState (sr, NS_RELNULL, fileloc_undefined);
245 else if (qual_isNotNull (qel))
247 sRef_setNullState (sr, NS_MNOTNULL, fileloc_undefined);
251 if (qual_isCQual (qel))
258 message ("Qualifier %s cannot be used in a globals list",
259 qual_unparse (qel)));
262 } end_qualList_elements;
265 sRef clabstract_createGlobal (sRef sr, qualList quals)
269 if (sRef_isValid (sr))
271 res = sRef_copy (sr);
272 DPRINTF (("Reflecting quals: %s / %s", sRef_unparse (sr), qualList_unparse (quals)));
273 reflectGlobalQualifiers (res, quals);
274 DPRINTF (("==> %s", sRef_unparseFull (res)));
278 res = sRef_undefined;
281 qualList_free (quals);
285 extern void declareCIter (cstring name, /*@owned@*/ uentryList params)
289 ue = uentry_makeIter (name,
290 ctype_makeFunction (ctype_void, params),
291 fileloc_copy (g_currentloc));
293 usymtab_supEntry (uentry_makeEndIter (name, fileloc_copy (g_currentloc)));
294 ue = usymtab_supGlobalEntryReturn (ue);
297 extern void nextIterParam (void)
299 llassert (ProcessingIterVars);
303 extern int iterParamNo (void)
305 llassert (ProcessingIterVars);
306 return saveIterParamNo;
310 ** yucky hacks to put it in the right place
314 makeCurrentParam (idDecl t)
318 saveStoreLoc = fileloc_undefined;
320 /* param number unknown */
322 ue = uentry_makeParam (t, 0);
327 declareUnnamedEnum (enumNameList el)
329 ctype ret = usymtab_enumEnumNameListType (el);
333 if (ctype_isDefined (ret))
336 e = uentry_makeEnumTagLoc (ctype_enumTag (rt), ret);
338 reflectStorageClass (e);
339 usymtab_supGlobalEntry (e);
341 declareEnumList (el, ret, g_currentloc);
342 enumNameList_free (el);
346 ctype ct = ctype_createEnum (fakeTag (), el);
348 e = uentry_makeEnumTagLoc (ctype_enumTag (ctype_realType (ct)), ct);
349 reflectStorageClass (e);
351 e = usymtab_supGlobalEntryReturn (e);
352 rt = uentry_getAbstractType (e);
353 declareEnumList (el, ct, g_currentloc);
360 declareEnum (cstring ename, enumNameList el)
365 llassert (cstring_isDefined (ename));
367 cet = ctype_createEnum (ename, el);
368 e = uentry_makeEnumTagLoc (ename, cet);
369 reflectStorageClass (e);
370 e = usymtab_supGlobalEntryReturn (e);
371 cet = uentry_getType (e);
372 declareEnumList (el, cet, uentry_whereLast (e));
373 return (uentry_getAbstractType (e));
377 declareEnumList (enumNameList el, ctype c, fileloc loc)
379 bool boolnames = FALSE;
380 bool othernames = FALSE;
382 (void) context_getSaveLocation (); /* undefine it */
384 if (context_maybeSet (FLG_NUMENUMMEMBERS))
386 int maxnum = context_getValue (FLG_NUMENUMMEMBERS);
387 int num = enumNameList_size (el);
393 message ("Enumerator %s declared with %d members (limit is set to %d)",
394 ctype_unparse (c), num, maxnum),
399 enumNameList_elements (el, e)
401 uentry ue = usymtab_lookupExposeGlob (e);
402 ctype ct = uentry_getType (ue);
404 llassert (uentry_isEnumConstant (ue));
406 if (ctype_isUnknown (ct))
408 uentry_setType (ue, c);
412 if (cstring_equal (e, context_getFalseName ())
413 || cstring_equal (e, context_getTrueName ()))
419 message ("Enumerator mixes boolean name (%s) with "
422 uentry_whereLast (ue)))
429 uentry_setType (ue, ctype_bool);
430 DPRINTF (("Set type: %s / %s",
431 uentry_unparse (ue), ctype_unparse (ctype_bool)));
439 message ("Enumerator mixes boolean names (%s, %s) with "
440 "non-boolean name: %s",
441 context_getTrueName (),
442 context_getFalseName (),
444 uentry_whereLast (ue)))
453 if (!ctype_match (c, ct))
455 if (ctype_isDirectBool (ct))
457 if (cstring_equal (e, context_getFalseName ())
458 || cstring_equal (e, context_getTrueName ()))
460 DPRINTF (("Here we are!"));
466 message ("Enumerator member %s declared with "
467 "inconsistent type: %s",
468 e, ctype_unparse (c)),
469 uentry_whereLast (ue)))
471 uentry_showWhereSpecifiedExtra
472 (ue, cstring_copy (ctype_unparse (ct)));
480 message ("Enumerator member %s declared with "
481 "inconsistent type: %s",
482 e, ctype_unparse (c)),
483 uentry_whereLast (ue)))
485 uentry_showWhereSpecifiedExtra
486 (ue, cstring_copy (ctype_unparse (ct)));
491 } end_enumNameList_elements;
494 static /*@dependent@*/ uentryList currentParamList;
496 /*drl added 3-28-2002*/
497 /* this function takes a list of paramentar and generates a list
499 Currently the only constraints gnerated are MaxSet(p) >= 0 for all pointers
502 void setImplictfcnConstraints (void)
507 params = currentParamList;
509 if (constraintList_isDefined(implicitFcnConstraints) )
510 constraintList_free(implicitFcnConstraints);
512 implicitFcnConstraints = constraintList_makeNew();
514 uentryList_elements (params, el)
516 DPRINTF((message("setImplictfcnConstraints doing: %s", uentry_unparse(el) ) ));
518 s = uentry_getSref(el);
519 if (sRef_isReference (s) )
521 DPRINTF((message ("%s is a pointer", sRef_unparse(s) ) ));
525 DPRINTF((message ("%s is NOT a pointer", sRef_unparse(s) ) ));
528 chagned this is MaxSet(s) == 0 to MaxSet(s) >= 0 */
530 c = constraint_makeSRefWriteSafeInt (s, 0);
531 /* constraint_makeSRefSetBufferSize (s, 0); */
532 implicitFcnConstraints = constraintList_add(implicitFcnConstraints , c);
534 end_uentryList_elements;
538 /*@observer@*/ constraintList getImplicitFcnConstraints (void)
540 return implicitFcnConstraints;
543 void setCurrentParams (/*@dependent@*/ uentryList ue)
545 currentParamList = ue;
548 void clearCurrentParams (void)
550 currentParamList = uentryList_undefined;
554 ** requires: uentry_isFunction (e)
555 ** parameter names for current function are in currentParamList
558 static void enterFunctionParams (uentryList params)
562 uentryList_elements (params, current)
564 if (uentry_hasName (current))
566 uentry_setParamNo (current, paramno);
567 usymtab_supEntry (uentry_copy (current));
571 } end_uentryList_elements;
575 extern void enterParamsTemp (void)
577 usymtab_enterScope ();
578 enterFunctionParams (currentParamList);
581 extern void exitParamsTemp (void)
583 usymtab_quietPlainExitScope ();
586 static /*@exposed@*/ uentry clabstract_globalDeclareFunction (idDecl tid)
588 ctype deftype = idDecl_getCtype (tid);
592 DPRINTF (("Global function: %s", idDecl_unparse (tid)));
594 if (ctype_isFunction (deftype))
596 rettype = ctype_getReturnType (deftype);
600 rettype = ctype_unknown;
604 ** check has been moved here...
607 if (ctype_isFunction (idDecl_getCtype (tid)))
609 ue = uentry_makeIdFunction (tid);
610 reflectSpecialCode (ue);
611 reflectArgsUsed (ue);
615 llparseerror (message ("Inconsistent function declaration: %q",
616 idDecl_unparse (tid)));
618 tid = idDecl_replaceCtype
619 (tid, ctype_makeFunction (ctype_unknown, uentryList_undefined));
620 ue = uentry_makeIdFunction (tid);
623 reflectStorageClass (ue);
624 uentry_checkParams (ue);
626 DPRINTF (("Supercede function: %s", uentry_unparseFull (ue)));
628 ue = usymtab_supGlobalEntryReturn (ue);
629 DPRINTF (("After supercede function: %s", uentry_unparseFull (ue)));
631 DPRINTF (("Enter function: %s", uentry_unparseFull (ue)));
632 context_enterFunction (ue);
633 enterFunctionParams (uentry_getParams (ue));
635 resetStorageClass ();
636 DPRINTF (("Function: %s", uentry_unparseFull (ue)));
641 ** for now, no type checking
642 ** (must check later though!)
645 static /*@only@*/ uentry globalDeclareOldStyleFunction (idDecl tid)
650 ** check has been moved here...
653 if (cstring_equalLit (idDecl_observeId (tid), "main"))
655 context_setFlagTemp (FLG_MAINTYPE, FALSE);
658 ue = uentry_makeIdFunction (tid);
659 reflectStorageClass (ue);
660 reflectSpecialCode (ue);
661 reflectArgsUsed (ue);
662 uentry_setDefined (ue, g_currentloc);
663 uentry_checkParams (ue);
664 resetStorageClass ();
666 /* context_enterOldStyleScope (); */
671 static void oldStyleDeclareFunction (/*@only@*/ uentry e)
673 uentryList params = saveParamList;
674 ctype rt = uentry_getType (e);
676 llassert (ctype_isFunction (rt));
678 if (uentry_hasStateClauseList (e)
679 || uentry_hasConditions (e))
681 llfatalerror (message ("%q: Old-style function declaration uses a clause (rewrite with function parameters): %q",
682 fileloc_unparse (g_currentloc), uentry_unparse (e)));
685 e = usymtab_supGlobalEntryReturn (e);
687 context_enterFunction (e);
688 enterFunctionParams (params);
689 saveParamList = uentryList_undefined;
690 resetStorageClass ();
693 static void oldStyleCompleteFunction (/*@only@*/ uentry e)
695 uentryList params = saveParamList;
696 ctype rt = uentry_getType (e);
698 llassert (ctype_isFunction (rt));
700 if (uentry_hasStateClauseList (e)
701 || uentry_hasConditions (e))
703 llfatalerror (message ("%q: Old-style function declaration uses a clause (rewrite with function parameters): %q",
704 fileloc_unparse (g_currentloc), uentry_unparse (e)));
707 e = usymtab_supGlobalEntryReturn (e);
709 context_completeOldStyleFunction (e);
710 enterFunctionParams (params);
711 saveParamList = uentryList_undefined;
712 resetStorageClass ();
715 void clabstract_declareFunction (idDecl tid) /*@globals undef saveFunction; @*/
719 DPRINTF (("Declare function: %s", idDecl_unparse (tid)));
721 if (ProcessingParams)
723 ue = globalDeclareOldStyleFunction (tid);
725 DPRINTF (("Set save function: %s", uentry_unparseFull (ue)));
729 saveFunction = uentry_undefined;
731 if (context_inRealFunction ())
733 ue = uentry_makeVariableLoc (idDecl_observeId (tid), ctype_unknown);
735 llparseerror (message ("Function declared inside function: %q",
736 idDecl_unparse (tid)));
738 context_quietExitFunction ();
739 ue = usymtab_supEntryReturn (ue);
743 if (context_inInnerScope ())
745 llparseerror (message ("Declaration in inner context: %q",
746 idDecl_unparse (tid)));
748 sRef_setGlobalScope ();
749 ue = uentry_makeVariableLoc (idDecl_observeId (tid),
751 ue = usymtab_supGlobalEntryReturn (ue);
752 sRef_clearGlobalScope ();
756 ue = clabstract_globalDeclareFunction (tid);
763 resetStorageClass ();
767 void declareStaticFunction (idDecl tid) /*@globals undef saveFunction; @*/
771 DPRINTF (("Declare static funciton: %s", idDecl_unparse (tid)));
773 if (ProcessingParams)
775 ue = globalDeclareOldStyleFunction (tid);
780 saveFunction = uentry_undefined;
782 if (context_inRealFunction ())
784 ue = uentry_makeVariableLoc (idDecl_observeId (tid), ctype_unknown);
786 llparseerror (message ("Function declared inside function: %q",
787 idDecl_unparse (tid)));
789 context_quietExitFunction ();
790 ue = usymtab_supEntryReturn (ue);
794 if (context_inInnerScope ())
796 llparseerror (message ("Declaration in inner context: %q",
797 idDecl_unparse (tid)));
799 sRef_setGlobalScope ();
800 ue = uentry_makeVariableLoc (idDecl_observeId (tid),
802 ue = usymtab_supGlobalEntryReturn (ue);
803 sRef_clearGlobalScope ();
807 ctype deftype = idDecl_getCtype (tid);
810 if (ctype_isFunction (deftype))
812 rettype = ctype_getReturnType (deftype);
816 rettype = ctype_unknown;
820 ** check has been moved here...
823 if (ctype_isFunction (idDecl_getCtype (tid)))
825 ue = uentry_makeIdFunction (tid);
826 reflectSpecialCode (ue);
827 reflectArgsUsed (ue);
831 llparseerror (message ("Inconsistent function declaration: %q",
832 idDecl_unparse (tid)));
834 tid = idDecl_replaceCtype
835 (tid, ctype_makeFunction (ctype_unknown, uentryList_undefined));
836 ue = uentry_makeIdFunction (tid);
839 reflectStorageClass (ue);
840 uentry_setStatic (ue);
842 uentry_checkParams (ue);
844 DPRINTF (("Sub global entry: %s", uentry_unparse (ue)));
845 ue = usymtab_supGlobalEntryReturn (ue);
847 context_enterFunction (ue);
848 enterFunctionParams (uentry_getParams (ue));
849 resetStorageClass ();
856 resetStorageClass ();
861 checkTypeDecl (uentry e, ctype rep)
863 cstring n = uentry_getName (e);
865 DPRINTF (("Check type decl: %s", uentry_unparseFull (e)));
867 if (cstring_equal (context_getBoolName (), n))
869 ctype rrep = ctype_realType (rep);
872 ** for abstract enum types, we need to fix the enum members:
873 ** they should have the abstract type, not the rep type.
876 if (ctype_isEnum (ctype_realType (rrep)))
878 enumNameList el = ctype_elist (rrep);
880 enumNameList_elements (el, ye)
882 if (usymtab_existsGlob (ye))
884 uentry ue = usymtab_lookupSafe (ye);
885 uentry_setType (ue, ctype_bool);
888 if (cstring_equal (context_getTrueName (), ye)
889 || cstring_equal (context_getFalseName (), ye))
897 message ("Member of boolean enumerated type definition "
898 "does not match name set to represent TRUE "
901 message ("Use -boolfalse and -booltrue to set the "
902 "name of false and true boolean values."),
903 uentry_whereDefined (e));
905 } end_enumNameList_elements;
909 if (usymtab_exists (n))
911 usymId llm = usymtab_getId (n);
912 uentry le = usymtab_getTypeEntry (llm);
914 uentry_setDeclared (e, g_currentloc);
915 uentry_setSref (e, sRef_makeGlobal (llm, uentry_getType (le), stateInfo_currentLoc ()));
917 DPRINTF (("Here we are: %s / %s",
918 n, context_getBoolName ()));
920 if (uentry_isAbstractDatatype (le))
922 ctype rrep = ctype_realType (rep);
924 DPRINTF (("Abstract type: %s", uentry_unparseFull (le)));
927 ** for abstract enum types, we need to fix the enum members:
928 ** they should have the abstract type, not the rep type.
931 if (ctype_isEnum (ctype_realType (rrep)))
933 ctype at = uentry_getAbstractType (le);
934 enumNameList el = ctype_elist (rrep);
936 enumNameList_elements (el, ye)
938 if (usymtab_existsGlob (ye))
940 uentry ue = usymtab_lookupSafe (ye);
942 llassert (uentry_isEitherConstant (ue));
943 llassertprint (ctype_match (uentry_getType (ue), rrep),
944 ("Bad enum: %s / %s",
946 ctype_unparse (rrep)));
948 uentry_setType (ue, at);
950 } end_enumNameList_elements;
953 if (uentry_isMutableDatatype (le))
955 /* maybe more complicated if abstract and immutable ? */
957 if (!ctype_isRealPointer (rep) && !ctype_isRealAbstract (rep))
961 message ("Mutable abstract type %s declared without pointer "
962 "indirection: %s (violates assignment semantics)",
963 n, ctype_unparse (rep)),
964 uentry_whereDefined (e));
966 uentry_setMutable (e);
973 fileloc fl = uentry_whereDeclared (e);
975 if (context_getFlag (FLG_LIKELYBOOL)
976 && !context_getFlag (FLG_BOOLINT))
978 if ((cstring_equalLit (n, "BOOL")
979 || cstring_equalLit (n, "Bool")
980 || cstring_equalLit (n, "bool")
981 || cstring_equalLit (n, "boolean")
982 || cstring_equalLit (n, "Boolean")
983 || cstring_equalLit (n, "BOOLEAN"))
984 && !(cstring_equal (n, context_getBoolName ())))
986 if (context_setBoolName ()) {
989 message ("Type %s is probably meant as a boolean type, but does "
990 "not match the boolean type name \"%s\".",
992 context_getBoolName ()),
997 message ("Type %s is probably meant as a boolean type, "
998 "but the boolean type name is not set. "
999 "Use -booltype %s to set it.",
1006 if (!uentry_isStatic (e)
1007 && !ctype_isFunction (uentry_getType (e))
1008 && !fileloc_isLib (fl)
1009 && !fileloc_isImport (fl)
1010 && fileloc_isHeader (fl))
1012 voptgenerror (FLG_EXPORTTYPE,
1013 message ("Type exported, but not specified: %s\n", n),
1022 fixUentryList (idDeclList tl, qtype q)
1024 uentryList f = uentryList_new ();
1026 idDeclList_elements (tl, i)
1028 if (idDecl_isDefined (i))
1034 (void) idDecl_fixBase (i, q);
1037 ** implicit annotations
1040 (void) fixStructDecl (i);
1042 ue = uentry_makeIdVariable (i);
1043 rt = ctype_realType (uentry_getType (ue));
1046 ** where is this here???
1048 if (ctype_isArray (rt) || ctype_isSU (rt))
1050 sRef_setAllocated (uentry_getSref (ue), uentry_whereDefined (ue));
1056 if (uentry_isValid (old = uentryList_lookupField (f, uentry_rawName (ue))))
1058 if (optgenerror (FLG_SYNTAX,
1059 message ("Field name reused: %s", uentry_rawName (ue)),
1060 uentry_whereDefined (ue)))
1062 llgenmsg (message ("Previous use of %s", uentry_rawName (ue)),
1063 uentry_whereDefined (old));
1067 f = uentryList_add (f, ue);
1069 } end_idDeclList_elements;
1071 idDeclList_free (tl);
1076 ** This is a hack to support unnamed struct/union fields as done by
1077 ** Microsoft VC++. It is not supported by the ANSI standard.
1079 ** The inner fields are added to the outer structure. This is meaningful
1080 ** for nesting structs inside unions, but Splint does no related
1085 fixUnnamedDecl (qtype q)
1087 ctype ct = ctype_realType (qtype_getType (q));
1089 if (ctype_isStruct (ct) || ctype_isUnion (ct))
1091 uentryList res = ctype_getFields (ct);
1093 return (uentryList_copy (res));
1095 else if (ctype_isEnum (ct))
1097 /* evans 2002-02-05: nothing to do for unnamed enum lists */
1098 return uentryList_undefined;
1105 return uentryList_undefined;
1108 void setStorageClass (storageClassCode sc)
1114 setProcessingIterVars (uentry iter)
1116 ProcessingIterVars = TRUE;
1118 saveIterParamNo = 0;
1122 setProcessingGlobalsList ()
1124 ProcessingGlobals = TRUE;
1125 fcnNoGlobals = FALSE;
1128 static bool ProcessingGlobMods = FALSE;
1131 setProcessingGlobMods ()
1133 ProcessingGlobMods = TRUE;
1137 clearProcessingGlobMods ()
1139 ProcessingGlobMods = FALSE;
1143 isProcessingGlobMods ()
1145 return (ProcessingGlobMods);
1148 static void resetGlobals (void)
1150 ProcessingGlobals = FALSE;
1151 fcnNoGlobals = FALSE;
1155 unsetProcessingGlobals ()
1157 ProcessingGlobals = FALSE;
1161 setProcessingVars (/*@only@*/ qtype q)
1163 ProcessingVars = TRUE;
1164 qtype_free (processingType);
1169 setGenericParamList (/*@dependent@*/ uentryList pm)
1171 ProcessingParams = TRUE;
1176 setProcessingTypedef (qtype q)
1178 ProcessingTypedef = TRUE;
1180 qtype_free (processingType);
1185 unsetProcessingVars ()
1187 resetStorageClass ();
1188 ProcessingVars = FALSE;
1192 oldStyleDoneParams ()
1194 if (ProcessingParams)
1196 if (uentry_isInvalid (saveFunction))
1198 llbuglit ("unsetProcessingVars: no saved function\n");
1202 ctype ct = ctype_getReturnType (uentry_getType (saveFunction));
1203 uentryList params = uentryList_copy (saveParamList);
1204 ctype ct2 = ctype_makeFunction (ct, params);
1206 uentry_setType (saveFunction, ct2);
1207 ProcessingParams = FALSE;
1209 oldStyleCompleteFunction (saveFunction);
1210 saveFunction = uentry_undefined;
1217 ** If the paramlist used a type name, we could be here.
1220 llfatalerror (message ("%q: Old-style function parameter list uses a "
1221 "type name.", fileloc_unparse (g_currentloc)));
1228 if (uentry_isValid (saveFunction))
1231 ** old style declaration
1234 ctype ct = ctype_getReturnType (uentry_getType (saveFunction));
1237 DPRINTF (("save function: %s", uentry_unparseFull (saveFunction)));
1239 uentryList_elements (saveParamList, current)
1241 uentry_setType (current, ctype_int); /* all params are ints */
1242 } end_uentryList_elements;
1244 ct2 = ctype_makeParamsFunction (ct, uentryList_copy (saveParamList));
1246 uentry_setType (saveFunction, ct2);
1247 ProcessingParams = FALSE;
1249 oldStyleDeclareFunction (saveFunction);
1250 saveFunction = uentry_undefined;
1254 void clabstract_declareType (/*@only@*/ exprNodeList decls, /*@only@*/ warnClause warn)
1256 llassert (ProcessingTypedef);
1258 DPRINTF (("Declare type: %s", exprNodeList_unparse (decls)));
1260 if (warnClause_isDefined (warn))
1262 DPRINTF (("Has a warn clause!"));
1263 DPRINTF (("Warn: %s", warnClause_unparse (warn)));
1265 exprNodeList_elements (decls, el)
1267 uentry ue = exprNode_getUentry (el);
1268 cstring uname = uentry_getName (ue);
1270 DPRINTF (("Entry: %s", exprNode_unparse (el)));
1273 ** Need to lookup again to make sure we have the right one...
1276 ue = usymtab_lookupExposeGlob (uname);
1278 llassert (uentry_isValid (ue));
1279 llassert (uentry_isDatatype (ue));
1281 DPRINTF (("Warning for %s: %s",
1282 uentry_unparse (ue), warnClause_unparse (warn)));
1284 uentry_addWarning (ue, warnClause_copy (warn));
1285 DPRINTF (("After add warning: %s", uentry_unparseFull (ue)));
1286 cstring_free (uname);
1287 } end_exprNodeList_elements;
1290 warnClause_free (warn);
1291 exprNodeList_free (decls);
1292 unsetProcessingTypedef ();
1296 unsetProcessingTypedef ()
1298 ProcessingTypedef = FALSE;
1301 void checkConstant (qtype t, idDecl id)
1305 id = idDecl_fixBase (id, t);
1306 e = uentry_makeIdConstant (id);
1308 reflectStorageClass (e);
1309 resetStorageClass ();
1311 DPRINTF (("Constant: %s", uentry_unparseFull (e)));
1312 usymtab_supGlobalEntry (e);
1315 void checkValueConstant (qtype t, idDecl id, exprNode e)
1319 id = idDecl_fixBase (id, t);
1320 ue = uentry_makeIdConstant (id);
1321 reflectStorageClass (ue);
1322 resetStorageClass ();
1324 if (exprNode_isDefined (e))
1326 if (!exprNode_matchType (uentry_getType (ue), e))
1329 (exprNode_getType (e), e,
1330 uentry_getType (ue), exprNode_undefined,
1331 message ("Constant %q initialized to type %t, expects %t: %s",
1332 uentry_getName (ue),
1333 exprNode_getType (e),
1334 uentry_getType (ue),
1335 exprNode_unparse (e)),
1340 if (exprNode_hasValue (e))
1342 uentry_mergeConstantValue (ue, multiVal_copy (exprNode_getValue (e)));
1346 DPRINTF (("No value: %s", exprNode_unparse (e)));
1351 DPRINTF (("Constant value: %s", uentry_unparseFull (ue)));
1352 usymtab_supGlobalEntry (ue);
1355 void processNamedDecl (idDecl t)
1357 if (qtype_isUndefined (processingType))
1359 llparseerror (message ("No type before declaration name: %q", idDecl_unparse (t)));
1361 processingType = qtype_create (ctype_unknown);
1364 t = idDecl_fixBase (t, processingType);
1366 DPRINTF (("Declare: %s", idDecl_unparse (t)));
1368 if (ProcessingGlobals)
1370 cstring id = idDecl_getName (t);
1371 uentry ue = usymtab_lookupSafe (id);
1373 if (!uentry_isValid (ue))
1375 llerror (FLG_UNRECOG,
1376 message ("Variable used in globals list is undeclared: %s", id));
1380 if (!ctype_match (uentry_getType (ue), idDecl_getCtype (t)))
1384 message ("Variable %s used in globals list declared %s, "
1386 id, ctype_unparse (uentry_getType (ue)),
1387 ctype_unparse (idDecl_getCtype (t))),
1392 sRef sr = sRef_copy (uentry_getSref (ue));
1393 reflectGlobalQualifiers (sr, idDecl_getQuals (t));
1397 else if (ProcessingVars)
1402 ct = ctype_realType (idDecl_getCtype (t));
1404 if (ProcessingParams)
1406 cstring id = idDecl_getName (t);
1407 int paramno = uentryList_lookupRealName (saveParamList, id);
1411 uentry cparam = uentryList_getN (saveParamList, paramno);
1413 DPRINTF (("Processing param: %s", uentry_unparseFull (cparam)));
1414 uentry_setType (cparam, idDecl_getCtype (t));
1415 uentry_reflectQualifiers (cparam, idDecl_getQuals (t));
1416 uentry_setDeclaredOnly (cparam, context_getSaveLocation ());
1417 DPRINTF (("Processing param: %s", uentry_unparseFull (cparam)));
1422 (message ("Old style declaration uses unlisted parameter: %s",
1430 if (context_inIterDef ())
1432 cstring pname = makeParam (idDecl_observeId (t));
1433 uentry p = usymtab_lookupSafe (pname);
1435 cstring_free (pname);
1437 if (uentry_isYield (p))
1439 e = uentry_makeParam (t, sRef_getParam (uentry_getSref (p)));
1440 uentry_checkYieldParam (p, e);
1441 usymtab_supEntrySref (e);
1446 if ((hasSpecialCode () || argsUsed)
1447 && ctype_isFunction (idDecl_getCtype (t)))
1449 e = uentry_makeIdFunction (t);
1450 reflectSpecialCode (e);
1451 reflectArgsUsed (e);
1455 e = uentry_makeIdVariable (t);
1458 loc = uentry_whereDeclared (e);
1461 if (context_inGlobalScope ())
1463 uentry_checkParams was here!
1467 if (ctype_isFunction (uentry_getType (e)))
1469 clabstract_prepareFunction (e);
1472 DPRINTF (("Superceding... %s", uentry_unparseFull (e)));
1473 e = usymtab_supEntrySrefReturn (e);
1474 DPRINTF (("After superceding... %s", uentry_unparseFull (e)));
1476 if (uentry_isExtern (e) && !context_inGlobalScope ())
1480 message ("Declaration using extern inside function scope: %q",
1481 uentry_unparse (e)),
1484 uentry_setDefined (e, fileloc_getExternal ());
1485 sRef_setDefined (uentry_getSref (e), fileloc_getExternal ());
1488 if (uentry_isFunction (e))
1490 if (!context_inXHFile ())
1492 checkParamNames (e);
1496 if (uentry_isVar (e) && uentry_isCheckedUnknown (e))
1498 sRef sr = uentry_getSref (e);
1500 if (sRef_isLocalVar (sr))
1502 if (context_getFlag (FLG_IMPCHECKMODINTERNALS))
1504 uentry_setCheckMod (e);
1508 uentry_setUnchecked (e);
1511 else if (sRef_isFileStatic (sr))
1513 if (context_getFlag (FLG_IMPCHECKEDSTRICTSTATICS))
1515 uentry_setCheckedStrict (e);
1517 else if (context_getFlag (FLG_IMPCHECKEDSTATICS))
1519 uentry_setChecked (e);
1521 else if (context_getFlag (FLG_IMPCHECKMODSTATICS))
1523 uentry_setCheckMod (e);
1530 else /* real global */
1532 llassert (sRef_isRealGlobal (sr));
1534 if (context_getFlag (FLG_IMPCHECKEDSTRICTGLOBALS))
1536 uentry_setCheckedStrict (e);
1538 else if (context_getFlag (FLG_IMPCHECKEDGLOBALS))
1540 uentry_setChecked (e);
1542 else if (context_getFlag (FLG_IMPCHECKMODGLOBALS))
1544 uentry_setCheckMod (e);
1554 else if (ProcessingTypedef)
1556 ctype ct = idDecl_getCtype (t);
1559 DPRINTF (("Processing typedef: %s", ctype_unparse (ct)));
1561 e = uentry_makeIdDatatype (t);
1563 if (cstring_equal (idDecl_getName (t), context_getBoolName ())) {
1564 ctype rt = ctype_realType (ct);
1566 if (ctype_isEnum (rt)) {
1569 if (!(ctype_isInt (rt)
1570 || ctype_isUnknown (rt)
1571 || ctype_isChar (rt))) {
1574 message ("Boolean type %s defined using non-standard type %s (integral, char or enum type expected)",
1575 context_getBoolName (),
1576 ctype_unparse (ct)),
1577 uentry_whereLast (e));
1581 uentry_setType (e, ct);
1585 reflectStorageClass (e);
1586 checkTypeDecl (e, ct);
1588 e = usymtab_supReturnTypeEntry (e);
1592 llparseerror (message ("Suspect missing struct or union keyword: %q",
1593 idDecl_unparse (t)));
1599 ** moved from grammar
1602 static idDecl fixStructDecl (/*@returned@*/ idDecl d)
1604 if (ctype_isVisiblySharable (idDecl_getCtype (d))
1605 && context_getFlag (FLG_STRUCTIMPONLY))
1607 if (!qualList_hasAliasQualifier (idDecl_getQuals (d)))
1609 if (qualList_hasExposureQualifier (idDecl_getQuals (d)))
1611 idDecl_addQual (d, qual_createDependent ());
1615 idDecl_addQual (d, qual_createImpOnly ());
1624 declareUnnamedStruct (/*@only@*/ uentryList f)
1626 DPRINTF (("Unnamed struct: %s", uentryList_unparse (f)));
1628 if (context_maybeSet (FLG_NUMSTRUCTFIELDS))
1630 int num = uentryList_size (f);
1631 int max = context_getValue (FLG_NUMSTRUCTFIELDS);
1636 (FLG_NUMSTRUCTFIELDS,
1637 message ("Structure declared with %d fields "
1638 "(limit is set to %d)",
1644 return (ctype_createUnnamedStruct (f));
1648 declareUnnamedUnion (/*@only@*/ uentryList f)
1650 if (context_maybeSet (FLG_NUMSTRUCTFIELDS))
1652 int num = uentryList_size (f);
1653 int max = context_getValue (FLG_NUMSTRUCTFIELDS);
1658 (FLG_NUMSTRUCTFIELDS,
1659 message ("Union declared with %d fields "
1660 "(limit is set to %d)",
1666 return (ctype_createUnnamedUnion (f));
1669 ctype declareStruct (cstring id, /*@only@*/ uentryList f)
1673 int num = uentryList_size (f);
1675 DPRINTF (("Declare struct: %s / %s", id, uentryList_unparse (f)));
1677 ct = ctype_createStruct (cstring_copy (id), f);
1679 DPRINTF (("Ctype: %s", ctype_unparse (ct)));
1681 ue = uentry_makeStructTagLoc (id, ct);
1683 DPRINTF (("ue: %s", uentry_unparseFull (ue)));
1685 if (context_maybeSet (FLG_NUMSTRUCTFIELDS))
1687 int max = context_getValue (FLG_NUMSTRUCTFIELDS);
1692 (FLG_NUMSTRUCTFIELDS,
1693 message ("Structure %q declared with %d fields "
1694 "(limit is set to %d)",
1695 uentry_getName (ue), num, max),
1696 uentry_whereLast (ue));
1700 return (usymtab_supTypeEntry (ue));
1703 ctype declareUnion (cstring id, uentryList f)
1707 int num = uentryList_size (f);
1709 ct = ctype_createUnion (cstring_copy (id), f);
1710 ue = uentry_makeUnionTagLoc (id, ct);
1712 if (context_maybeSet (FLG_NUMSTRUCTFIELDS))
1714 int max = context_getValue (FLG_NUMSTRUCTFIELDS);
1719 (FLG_NUMSTRUCTFIELDS,
1720 message ("Union %q declared with %d fields "
1721 "(limit is set to %d)",
1722 uentry_getName (ue), num, max),
1723 uentry_whereLast (ue));
1727 return (usymtab_supTypeEntry (ue));
1730 ctype handleStruct (/*@only@*/ cstring id)
1732 if (usymtab_existsStructTag (id))
1734 ctype ct = uentry_getAbstractType (usymtab_lookupStructTag (id));
1741 return (ctype_createForwardStruct (id));
1745 ctype handleUnion (/*@only@*/ cstring id)
1747 if (usymtab_existsUnionTag (id))
1749 ctype ret = uentry_getAbstractType (usymtab_lookupUnionTag (id));
1755 return (ctype_createForwardUnion (id));
1760 handleEnum (cstring id)
1762 if (usymtab_existsEnumTag (id))
1764 ctype ret = uentry_getAbstractType (usymtab_lookupEnumTag (id));
1770 return (declareEnum (id, enumNameList_new ()));
1774 bool processingIterVars (void)
1776 return ProcessingIterVars;
1779 uentry getCurrentIter (void)
1784 static bool flipOldStyle = FALSE;
1785 static bool flipNewStyle = TRUE;
1787 void setFlipOldStyle () { flipOldStyle = TRUE; }
1788 bool isFlipOldStyle () { return flipOldStyle; }
1789 bool isNewStyle () { return flipNewStyle; }
1790 void setNewStyle () { flipNewStyle = TRUE; }
1792 /*@dependent@*/ uentryList handleParamIdList (/*@dependent@*/ uentryList params)
1797 ** this is a really YUCKY hack to handle old style
1801 voptgenerror (FLG_OLDSTYLE,
1802 cstring_makeLiteral ("Old style function declaration"),
1805 DPRINTF (("Handle old style params: %s", uentryList_unparseFull (params)));
1807 uentryList_elements (params, current)
1809 uentry_setParam (current);
1810 uentry_setSref (current, sRef_makeParam (paramno, ctype_unknown, stateInfo_makeLoc (uentry_whereLast (current))));
1812 } end_uentryList_elements;
1814 setGenericParamList (params);
1815 g_expectingTypeName = TRUE;
1820 /*@dependent@*/ uentryList handleParamTypeList (/*@returned@*/ uentryList params)
1824 uentryList_fixMissingNames (params);
1826 voptgenerror (FLG_OLDSTYLE,
1827 cstring_makeLiteral ("Old style function declaration."),
1830 setGenericParamList (params);
1831 flipOldStyle = FALSE;
1832 g_expectingTypeName = TRUE;
1841 ctype c = ctype_unknown;
1842 cstring id = cstring_makeLiteral ("va_alist");
1845 if (ProcessingParams)
1847 int i = uentryList_lookupRealName (saveParamList, id);
1851 fileloc loc = context_getSaveLocation ();
1852 e = uentry_makeVariableSrefParam (id, c, loc, sRef_makeParam (i, c, stateInfo_makeLoc (loc)));
1856 e = uentry_undefined; /* suppress gcc message */
1857 llfatalerrorLoc (cstring_makeLiteral ("va_dcl used without va_alist"));
1862 llerror (FLG_SYNTAX, cstring_makeLiteral ("va_dcl used outside of function declaration"));
1863 e = uentry_makeVariableLoc (id, c);
1867 uentry_setUsed (e, g_currentloc);
1868 usymtab_supEntrySref (e);
1871 /*@exposed@*/ sRef modListPointer (/*@exposed@*/ sRef s)
1873 ctype ct = sRef_getType (s);
1874 ctype rt = ctype_realType (ct);
1876 if (ctype_isAP (rt))
1878 if (context_inHeader () && ctype_isAbstract (ct))
1883 ("Modifies clause in header file dereferences abstract "
1884 "type %s (interface modifies clause should not depend "
1885 "on or expose type representation): %q",
1891 return (sRef_constructPointer (s));
1895 if (ctype_isKnown (rt))
1899 message ("Implementation modifies clause dereferences non-pointer (type %s): %q",
1909 /*@exposed@*/ sRef modListFieldAccess (sRef s, cstring f)
1911 ctype ct = sRef_getType (s);
1912 ctype rt = ctype_realType (ct);
1914 if (ctype_isStructorUnion (rt))
1916 uentry tf = uentryList_lookupField (ctype_getFields (rt), f);
1918 if (uentry_isUndefined (tf))
1920 voptgenerror (FLG_TYPE,
1921 message ("Modifies list accesses non-existent "
1922 "field %s of %t: %q", f, ct,
1927 return sRef_undefined;
1931 if (ctype_isAbstract (ct) && context_inHeader ())
1936 ("Modifies clause in header file accesses abstract "
1937 "type %s (interface modifies clause should not depend "
1938 "on or expose type representation): %q",
1945 cstring_markOwned (f);
1946 return (sRef_makeField (s, f));
1952 message ("Modifies clause dereferences non-pointer (type %s): %q",
1962 /*@dependent@*/ sRef clabstract_unrecognizedGlobal (cstring s)
1964 if (cstring_equalLit (s, "nothing"))
1966 return sRef_makeNothing ();
1968 else if (cstring_equalLit (s, "internalState"))
1970 return sRef_makeInternalState ();
1972 else if (cstring_equalLit (s, "fileSystem")
1973 || cstring_equalLit (s, "systemState"))
1975 return sRef_makeSystemState ();
1981 message ("Unrecognized identifier in globals list: %s", s),
1984 return sRef_undefined;
1988 /*@exposed@*/ sRef modListArrowAccess (sRef s, cstring f)
1990 ctype ct = sRef_getType (s);
1991 ctype rt = ctype_realType (ct);
1993 if (ctype_isRealPointer (rt))
1995 ctype b = ctype_baseArrayPtr (rt);
1996 ctype rb = ctype_realType (b);
1998 if (ctype_isStructorUnion (rb))
2000 uentry tf = uentryList_lookupField (ctype_getFields (rb), f);
2002 if (uentry_isUndefined (tf))
2004 voptgenerror (FLG_TYPE,
2005 message ("Modifies list arrow accesses non-existent "
2006 "field %s of %t: %q", f, b,
2011 return sRef_undefined;
2015 if (context_inHeader ())
2017 if (ctype_isAbstract (b))
2022 ("Modifies clause in header file arrow accesses abstract "
2023 "type %s (interface modifies clause should not depend "
2024 "on or expose type representation): %q",
2032 if (ctype_isAbstract (rt))
2037 ("Modifies clause arrow accesses inaccessible abstract "
2038 "type %s (interface modifies clause should not depend "
2039 "on or expose type representation): %q",
2047 cstring_markOwned (f);
2048 return (sRef_makeArrow (s, f));
2054 message ("Modifies clause arrow accesses pointer to "
2055 "non-structure (type %s): %q",
2065 message ("Modifies clause arrow accesses non-pointer (type %s): %q",
2075 sRef checkStateClausesId (uentry ue)
2077 cstring s = uentry_rawName (ue);
2079 if (sRef_isFileOrGlobalScope (uentry_getSref (ue)))
2083 message ("Global variable %s used state clause. (Global variables "
2084 "are not recognized in state clauses. If there is "
2085 "sufficient interest in support for this, it may be "
2086 "added to a future release. Send mail to "
2087 "info@splint.org.)",
2091 return sRef_undefined;
2095 if (cstring_equalLit (s, "result"))
2099 message ("Special clause list uses %s which is a variable and has special "
2100 "meaning in a modifies list. (Special meaning assumed.)", s),
2103 uentry_showWhereDeclared (ue);
2107 return uentry_getSref (ue);
2113 don;t know what the real date is...
2119 based on checkSpecClausesId
2123 sRef checkbufferConstraintClausesId (uentry ue)
2125 cstring s = uentry_rawName (ue);
2127 if (cstring_equalLit (s, "result"))
2131 message ("Function clause list uses %s which is a variable and has special "
2132 "meaning in a modifies list. (Special meaning assumed.)", s),
2135 uentry_showWhereDeclared (ue);
2139 DPRINTF (("constrant id: %s", uentry_unparseFull (ue)));
2140 return sRef_saveCopy (uentry_getSref (ue)); /*@i523 why the saveCopy? */
2143 void checkModifiesId (uentry ue)
2145 cstring s = uentry_rawName (ue);
2147 if (cstring_equalLit (s, "nothing")
2148 || cstring_equalLit (s, "internalState")
2149 || cstring_equalLit (s, "systemState")
2150 || (cstring_equalLit (s, "fileSystem")))
2154 message ("Modifies list uses %s which is a variable and has special "
2155 "meaning in a modifies list. (Special meaning assumed.)", s),
2158 uentry_showWhereDeclared (ue);
2163 /*@exposed@*/ sRef fixModifiesId (cstring s)
2166 cstring pname = makeParam (s);
2167 uentry ue = usymtab_lookupSafe (pname);
2169 cstring_free (pname);
2171 if (cstring_equalLit (s, "nothing"))
2173 ret = sRef_makeNothing ();
2175 else if (cstring_equalLit (s, "internalState"))
2177 ret = sRef_makeInternalState ();
2179 else if (cstring_equalLit (s, "fileSystem")
2180 || cstring_equalLit (s, "systemState"))
2182 ret = sRef_makeSystemState ();
2186 ret = sRef_undefined;
2189 if (sRef_isValid (ret))
2191 if (uentry_isValid (ue))
2195 message ("Modifies list uses %s which is a parameter and has special "
2196 "meaning in a modifies list. (Special meaning assumed.)", s),
2202 if (uentry_isValid (ue))
2204 ret = uentry_getSref (ue);
2208 fileloc loc = fileloc_decColumn (g_currentloc, size_toInt (cstring_length (s)));
2209 ret = sRef_undefined;
2213 message ("Unrecognized identifier in modifies comment: %s", s),
2223 sRef fixStateClausesId (cstring s)
2226 cstring pname = makeParam (s);
2227 uentry ue = usymtab_lookupSafe (pname);
2229 cstring_free (pname);
2231 if (cstring_equalLit (s, "result"))
2233 ret = sRef_makeResult (ctype_unknown);
2237 ret = sRef_undefined;
2240 if (sRef_isValid (ret))
2242 if (uentry_isValid (ue))
2246 message ("Function clause uses %s which is a parameter and has special "
2247 "meaning in a function clause. (Special meaning assumed.)", s),
2253 if (uentry_isValid (ue))
2255 ret = uentry_getSref (ue);
2257 if (sRef_isFileOrGlobalScope (ret))
2261 message ("Global variable %s used in function clause. (Global variables "
2262 "are not recognized in function clauses. If there is "
2263 "sufficient interest in support for this, it may be "
2264 "added to a future release. Send mail to "
2265 "info@splint.org.)",
2269 ret = sRef_undefined;
2275 /*drl handle structure invariant */
2278 /*check that we're in a structure */
2280 /*@unused@*/ uentryList ueL;
2281 /*@unused@*/ uentry ue2;
2282 /*@unused@*/ ctype ct;
\r
2284 fileloc loc = fileloc_decColumn (g_currentloc, size_toInt (cstring_length (s)));
2285 ret = sRef_undefined;
2287 /*drl commenting this out for now
2288 ct = context_getLastStruct ( ct );
2290 llassert( ctype_isStruct(ct) );
2292 ueL = ctype_getFields (ct);
2294 ue2 = uentryList_lookupField (ueL, s);
2296 if (!uentry_isUndefined(ue2) )
2298 ret = uentry_getSref(ue2);
2301 message("Got field in structure in the annotation constraint: %s (or sref: %s)", s, sRef_unparse(ret) )
2311 message ("Unrecognized identifier in function clause: %s", s),
2321 sRef modListArrayFetch (/*@exposed@*/ sRef s, /*@unused@*/ sRef mexp)
2323 ctype ct = sRef_getType (s);
2324 ctype rt = ctype_realType (ct);
2326 if (ctype_isAP (rt))
2328 if (context_inHeader () && ctype_isAbstract (ct))
2333 ("Modifies clause in header file indexes abstract "
2334 "type %s (interface modifies clause should not depend "
2335 "on or expose type representation): %q",
2341 return (sRef_makeAnyArrayFetch (s));
2348 ("Implementation modifies clause uses array fetch on non-array (type %s): %q",
2349 ctype_unparse (ct), sRef_unparse (s)),
2355 static void clabstract_prepareFunction (uentry e)
2357 uentry_checkParams (e);
2358 DPRINTF (("After prepare: %s", uentry_unparseFull (e)));
2361 sRef clabstract_checkGlobal (exprNode e)
2364 llassert (exprNode_isInitializer (e));
2366 s = exprNode_getSref (e);
2367 DPRINTF (("Initializer: %s -> %s", exprNode_unparse (e), sRef_unparse (s)));
2370 return sRef_copy (s);