1 /*
2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 University of Virginia,
4 **         Massachusetts Institute of Technology
5 **
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.
10 **
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.
15 **
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.
19 **
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
23 */
24 /*
25 ** clabstract.c
26 **
27 ** ASTs for C grammar
28 **
29 */
30 
31 # include "splintMacros.nf"
32 # include "basic.h"
33 # include "cgrammar.h"
34 # include "usymtab_interface.h"
35 
36 # include "structNames.h"
37 # include "nameChecks.h"
38 
39 # include "cscannerHelp.h"
40 
41 # ifdef SANITIZER
42 # include "sgrammar_tokens.h"
43 # else
44 # include "cgrammar_tokens.h"
45 # endif
46 
47 /*
48 ** Lots of variables are needed because of interactions with the
49 ** parser.  This is easier than restructuring the grammar so the
50 ** right values are available in the right place.
51 */
52 
53 /*drl*/
54 static /*@only@*/ constraintList implicitFcnConstraints = NULL;
55 
56 static void clabstract_prepareFunction (uentry p_e) /*@modifies p_e@*/ ;
57 static bool fcnNoGlobals = FALSE;
58 static void processVariable (/*@temp@*/ idDecl p_t) /*@modifies internalState@*/ ;
59 
60 static bool s_processingVars = FALSE;
61 static bool s_processingParams = FALSE;
62 static bool s_processingGlobals = FALSE;
63 static bool s_processingTypedef = FALSE;
64 static bool s_processingIterVars = FALSE;
65 static /*@only@*/ qtype processingType = qtype_undefined;
66 static uentry currentIter = uentry_undefined;
67 static /*@dependent@*/ uentryList saveParamList;  /* for old style functions */
68 static /*@owned@*/ uentry saveFunction = uentry_undefined;
69 static int saveIterParamNo;
70 static idDecl fixStructDecl (/*@returned@*/ idDecl p_d);
71 static void checkTypeDecl (uentry p_e, ctype p_rep);
72 static /*@dependent@*/ fileloc saveStoreLoc = fileloc_undefined;
73 static storageClassCode storageClass = SCNONE;
74 static void declareEnumList (/*@temp@*/ enumNameList p_el, ctype p_c, fileloc p_loc);
75 static void resetGlobals (void);
76 static /*@null@*/ qual specialFunctionCode;
77 static bool argsUsed = FALSE;
78 
clabstract_initMod()79 extern void clabstract_initMod ()
80 {
81   specialFunctionCode = qual_createUnknown ();
82   DPRINTF (("Initialized: %s", qual_unparse (specialFunctionCode)));
83 }
84 
hasSpecialCode(void)85 static bool hasSpecialCode (void)
86 {
87   return (!qual_isUnknown (specialFunctionCode));
88 }
89 
setArgsUsed(void)90 extern void setArgsUsed (void)
91 {
92   if (argsUsed)
93     {
94       voptgenerror
95 	(FLG_SYNTAX,
96 	 cstring_makeLiteral ("Multiple ARGSUSED comments for one function"),
97 	 g_currentloc);
98     }
99 
100   argsUsed = TRUE;
101 }
102 
reflectArgsUsed(uentry ue)103 static void reflectArgsUsed (uentry ue)
104 {
105   if (argsUsed)
106     {
107       if (uentry_isFunction (ue))
108 	{
109 	  uentryList params = uentry_getParams (ue);
110 
111 	  uentryList_elements (params, el)
112 	    {
113 	      uentry_setUsed (el, fileloc_undefined);
114 	    } end_uentryList_elements ;
115 	}
116 
117       argsUsed = FALSE;
118     }
119 }
120 
setSpecialFunction(qual qu)121 extern void setSpecialFunction (qual qu)
122 {
123   if (!qual_isUnknown (specialFunctionCode))
124     {
125       voptgenerror (FLG_SYNTAX,
126 		    message ("Multiple special function codes: %s, %s "
127 			     "(first code is ignored)",
128 			     qual_unparse (specialFunctionCode),
129 			     qual_unparse (qu)),
130 		    g_currentloc);
131     }
132 
133   specialFunctionCode = qu;
134 }
135 
reflectSpecialCode(uentry ue)136 static void reflectSpecialCode (uentry ue)
137 {
138   if (qual_isUnknown (specialFunctionCode)) {
139     ;
140   } else if (qual_isPrintfLike (specialFunctionCode)) {
141     uentry_setPrintfLike (ue);
142   } else if (qual_isScanfLike (specialFunctionCode)) {
143     uentry_setScanfLike (ue);
144   } else if (qual_isMessageLike (specialFunctionCode)) {
145     uentry_setMessageLike (ue);
146   } else {
147     BADBRANCH;
148   }
149 
150   specialFunctionCode = qual_createUnknown ();
151 }
152 
resetStorageClass(void)153 static void resetStorageClass (void)
154 {
155   qtype_free (processingType);
156   processingType = qtype_undefined;
157   storageClass = SCNONE;
158 }
159 
reflectStorageClass(uentry u)160 static void reflectStorageClass (uentry u)
161 {
162   if (storageClass == SCSTATIC)
163     {
164       uentry_setStatic (u);
165     }
166   else if (storageClass == SCEXTERN)
167     {
168       uentry_setExtern (u);
169     }
170   else
171     {
172       ; /* no storage class */
173     }
174 
175   }
176 
storeLoc()177 void storeLoc ()
178 {
179   saveStoreLoc = g_currentloc;
180 }
181 
setFunctionNoGlobals(void)182 void setFunctionNoGlobals (void)
183 {
184   fcnNoGlobals = TRUE;
185 }
186 
reflectGlobalQualifiers(sRef sr,qualList quals)187 static void reflectGlobalQualifiers (sRef sr, qualList quals)
188 {
189   DPRINTF (("Reflect global qualifiers: %s / %s",
190 	    sRef_unparseFull (sr), qualList_unparse (quals)));
191 
192   qualList_elements (quals, qel)
193     {
194       if (qual_isGlobalQual (qel)) /* undef, killed */
195 	{
196 	  sstate oldstate = sRef_getDefState (sr);
197 	  sstate defstate = sstate_fromQual (qel);
198 
199 	  if ((oldstate == SS_UNDEFGLOB && defstate == SS_KILLED)
200 	      || (oldstate == SS_KILLED && defstate == SS_UNDEFGLOB))
201 	    {
202 	      defstate = SS_UNDEFKILLED;
203 	    }
204 	  else
205 	    {
206 	      ; /* any errors? */
207 	    }
208 
209 	  sRef_setDefState (sr, defstate, fileloc_undefined);
210 	  DPRINTF (("State: %s", sRef_unparseFull (sr)));
211 	}
212       else if (qual_isAllocQual (qel)) /* out, partial, reldef, etc. */
213 	{
214 	  ctype realType = sRef_getType (sr);
215 	  sstate defstate = sstate_fromQual (qel);
216 
217 	  if (qual_isRelDef (qel))
218 	    {
219 	      ; /* okay anywhere */
220 	    }
221 	  else
222 	    {
223 	      if (!ctype_isAP (realType)
224 		  && !ctype_isSU (realType)
225 		  && !ctype_isUnknown (realType)
226 		  && !ctype_isAbstract (sRef_getType (sr)))
227 		{
228 		  llerror
229 		    (FLG_SYNTAX,
230 		     message ("Qualifier %s used on non-pointer or struct: %q",
231 			      qual_unparse (qel), sRef_unparse (sr)));
232 
233 		}
234 	    }
235 
236 	  sRef_setDefState (sr, defstate, fileloc_undefined);
237 	}
238       else if (qual_isNull (qel))
239 	{
240 	  sRef_setNullState (sr, NS_POSNULL, fileloc_undefined);
241 	}
242       else if (qual_isRelNull (qel))
243 	{
244 	  sRef_setNullState (sr, NS_RELNULL, fileloc_undefined);
245 	}
246       else if (qual_isNotNull (qel))
247 	{
248 	  sRef_setNullState (sr, NS_MNOTNULL, fileloc_undefined);
249 	}
250       else
251 	{
252 	  if (qual_isCQual (qel))
253 	    {
254 	      ; /* okay */
255 	    }
256 	  else
257 	    {
258 	      llerror (FLG_SYNTAX,
259 		       message ("Qualifier %s cannot be used in a globals list",
260 				qual_unparse (qel)));
261 	    }
262 	}
263     } end_qualList_elements;
264 }
265 
clabstract_createGlobal(sRef sr,qualList quals)266 sRef clabstract_createGlobal (sRef sr, qualList quals)
267 {
268   sRef res;
269 
270   if (sRef_isValid (sr))
271     {
272       res = sRef_copy (sr);
273       DPRINTF (("Reflecting quals: %s / %s", sRef_unparse (sr), qualList_unparse (quals)));
274       reflectGlobalQualifiers (res, quals);
275       DPRINTF (("==> %s", sRef_unparseFull (res)));
276     }
277   else
278     {
279       res = sRef_undefined;
280     }
281 
282   qualList_free (quals);
283   return res;
284 }
285 
declareCIter(cstring name,uentryList params)286 extern void declareCIter (cstring name, /*@owned@*/ uentryList params)
287 {
288   uentry ue;
289 
290   ue = uentry_makeIter (name,
291 			ctype_makeFunction (ctype_void, params),
292 			fileloc_copy (g_currentloc));
293 
294   usymtab_supEntry (uentry_makeEndIter (name, fileloc_copy (g_currentloc)));
295   ue = usymtab_supGlobalEntryReturn (ue);
296 }
297 
nextIterParam(void)298 extern void nextIterParam (void)
299 {
300   llassert (s_processingIterVars);
301   saveIterParamNo++;
302 }
303 
iterParamNo(void)304 extern int iterParamNo (void)
305 {
306   llassert (s_processingIterVars);
307   return saveIterParamNo;
308 }
309 
310 /*
311 ** yucky hacks to put it in the right place
312 */
313 
314 /*@only@*/ uentry
makeCurrentParam(idDecl t)315 makeCurrentParam (idDecl t)
316 {
317   uentry ue;
318 
319   saveStoreLoc = fileloc_undefined;
320 
321   /* param number unknown */
322 
323   ue = uentry_makeParam (t, 0);
324   return ue;
325 }
326 
327 ctype
declareUnnamedEnum(enumNameList el)328 declareUnnamedEnum (enumNameList el)
329 {
330   ctype ret = usymtab_enumEnumNameListType (el);
331   ctype rt;
332   uentry e;
333 
334   if (ctype_isDefined (ret))
335     {
336       rt = ret;
337       e = uentry_makeEnumTagLoc (ctype_enumTag (rt), ret);
338 
339       reflectStorageClass (e);
340       usymtab_supGlobalEntry (e);
341 
342       declareEnumList (el, ret, g_currentloc);
343       enumNameList_free (el);
344     }
345   else
346     {
347       ctype ct = ctype_createEnum (fakeTag (), el);
348 
349       e = uentry_makeEnumTagLoc (ctype_enumTag (ctype_realType (ct)), ct);
350       reflectStorageClass (e);
351 
352       e = usymtab_supGlobalEntryReturn (e);
353       rt = uentry_getAbstractType (e);
354       declareEnumList (el, ct, g_currentloc);
355     }
356 
357   return (rt);
358 }
359 
360 ctype
declareEnum(cstring ename,enumNameList el)361 declareEnum (cstring ename, enumNameList el)
362 {
363   ctype cet;
364   uentry e;
365 
366   llassert (cstring_isDefined (ename));
367 
368   cet = ctype_createEnum (ename, el);
369   e = uentry_makeEnumTagLoc (ename, cet);
370   reflectStorageClass (e);
371   e = usymtab_supGlobalEntryReturn (e);
372   cet = uentry_getType (e);
373   declareEnumList (el, cet, uentry_whereLast (e));
374   return (uentry_getAbstractType (e));
375 }
376 
377 static void
declareEnumList(enumNameList el,ctype c,fileloc loc)378 declareEnumList (enumNameList el, ctype c, fileloc loc)
379 {
380   bool boolnames = FALSE;
381   bool othernames = FALSE;
382 
383   (void) context_getSaveLocation (); /* undefine it */
384 
385   if (context_maybeSet (FLG_NUMENUMMEMBERS))
386     {
387       int maxnum = context_getValue (FLG_NUMENUMMEMBERS);
388       int num = enumNameList_size (el);
389 
390       if (num > maxnum)
391 	{
392 	  voptgenerror
393 	    (FLG_NUMENUMMEMBERS,
394 	     message ("Enumerator %s declared with %d members (limit is set to %d)",
395 		      ctype_unparse (c), num, maxnum),
396 	     loc);
397 	}
398     }
399 
400   enumNameList_elements (el, e)
401     {
402       uentry ue = usymtab_lookupExposeGlob (e);
403       ctype ct = uentry_getType (ue);
404 
405       llassert (uentry_isEnumConstant (ue));
406 
407       if (ctype_isUnknown (ct))
408 	{
409 	  uentry_setType (ue, c);
410 	}
411       else
412 	{
413 	  if (cstring_equal (e, context_getFalseName ())
414 	      || cstring_equal (e, context_getTrueName ()))
415 	    {
416 	      if (othernames)
417 		{
418 		  if (optgenerror
419 		      (FLG_INCONDEFS,
420 		       message ("Enumerator mixes boolean name (%s) with "
421 				"non-boolean names",
422 				e),
423 		       uentry_whereLast (ue)))
424 		    {
425 		      ;
426 		    }
427 		}
428 
429 	      boolnames = TRUE;
430 	      uentry_setType (ue, ctype_bool);
431 	      DPRINTF (("Set type: %s / %s",
432 			uentry_unparse (ue), ctype_unparse (ctype_bool)));
433 	    }
434 	  else
435 	    {
436 	      if (boolnames)
437 		{
438 		  if (optgenerror
439 		      (FLG_INCONDEFS,
440 		       message ("Enumerator mixes boolean names (%s, %s) with "
441 				"non-boolean name: %s",
442 				context_getTrueName (),
443 				context_getFalseName (),
444 				e),
445 		       uentry_whereLast (ue)))
446 		    {
447 		      ;
448 		    }
449 		}
450 
451 	      othernames = TRUE;
452 	    }
453 
454 	  if (!ctype_match (c, ct))
455 	    {
456 	      if (ctype_isDirectBool (ct))
457 		{
458 		  if (cstring_equal (e, context_getFalseName ())
459 		      || cstring_equal (e, context_getTrueName ()))
460 		    {
461 		      DPRINTF (("Here we are!"));
462 		    }
463 		  else
464 		    {
465 		      if (optgenerror
466 			  (FLG_INCONDEFS,
467 			   message ("Enumerator member %s declared with "
468 				    "inconsistent type: %s",
469 				    e, ctype_unparse (c)),
470 			   uentry_whereLast (ue)))
471 			{
472 			  uentry_showWhereSpecifiedExtra
473 			    (ue, cstring_copy (ctype_unparse (ct)));
474 			}
475 		    }
476 		}
477 	      else
478 		{
479 		  if (optgenerror
480 		      (FLG_INCONDEFS,
481 		       message ("Enumerator member %s declared with "
482 				"inconsistent type: %s",
483 				e, ctype_unparse (c)),
484 		       uentry_whereLast (ue)))
485 		    {
486 		      uentry_showWhereSpecifiedExtra
487 			(ue, cstring_copy (ctype_unparse (ct)));
488 		    }
489 		}
490 	    }
491 	}
492     } end_enumNameList_elements;
493 }
494 
495 static /*@dependent@*/ uentryList currentParamList;
496 
497 /*drl added 3-28-2002*/
498 /* this function takes a list of paramentar and generates a list
499    of constraints.
500 */
501 
502 /* drl modified 10/23/2002
503 
504 The current semantics are generated constraints of the form MaxSet(p) >= 0 and MaxRead(p) >= 0 for all pointers
505 unless the @out@ annotation has been applied to a parameter, then we only want to generate maxSet(p) > = 0
506 */
507 
setImplicitfcnConstraints(void)508 void setImplicitfcnConstraints (void)
509 {
510   uentryList params;
511   sRef s;
512   constraint c;
513   params = currentParamList;
514 
515   if (constraintList_isDefined (implicitFcnConstraints))
516     {
517       constraintList_free (implicitFcnConstraints);
518     }
519 
520   implicitFcnConstraints = constraintList_makeNew();
521 
522   uentryList_elements (params, el)
523     {
524       DPRINTF (("setImplicitfcnConstraints doing: %s", uentry_unparse(el)));
525 
526       if (uentry_isVariable (el))
527 	{
528 	  s = uentry_getSref(el);
529 
530 	  if (sRef_isReference (s))
531 	    {
532 	      DPRINTF((message ("%s is a pointer", sRef_unparse(s) ) ));
533 	      /*drl 4/26/01
534 		chagned this from MaxSet(s) == 0 to MaxSet(s) >= 0 */
535 	      c = constraint_makeSRefWriteSafeInt (s, 0);
536 
537 	      implicitFcnConstraints = constraintList_add (implicitFcnConstraints , c);
538 
539 	      /*drl 10/23/2002 added support for out*/
540 
541 	      if (!uentry_isOut(el))
542 		{
543 		  c = constraint_makeSRefReadSafeInt (s, 0);
544 		  implicitFcnConstraints = constraintList_add (implicitFcnConstraints , c);
545 		}
546 	    }
547 	  else
548 	    {
549 	      DPRINTF((message ("%s is NOT a pointer", sRef_unparse(s) ) ));
550 	    }
551 	} /*end uentry_isVariable*/
552       else if (uentry_isElipsisMarker (el) )
553 	{
554 	  /* just ignore these*/
555 	  ;
556 	}
557 
558       else
559 	{
560 	  /* just ignore this
561 	     I'm not sure if this is possible though
562 	  */
563 	  ;
564 	}
565     } end_uentryList_elements;
566 }
567 
568 
getImplicitFcnConstraints(void)569 /*@observer@*/ constraintList getImplicitFcnConstraints (void)
570 {
571   return implicitFcnConstraints;
572 }
573 
setCurrentParams(uentryList ue)574 void setCurrentParams (/*@dependent@*/ uentryList ue)
575 {
576   currentParamList = ue;
577 }
578 
clearCurrentParams(void)579 void clearCurrentParams (void)
580 {
581   currentParamList = uentryList_undefined;
582 }
583 
584 /*
585 ** requires: uentry_isFunction (e)
586 **           parameter names for current function are in currentParamList
587 */
588 
enterFunctionParams(uentryList params)589 static void enterFunctionParams (uentryList params)
590 {
591   int paramno = 0;
592 
593   uentryList_elements (params, current)
594     {
595       if (uentry_hasName (current))
596 	{
597 	  uentry_setParamNo (current, paramno);
598 	  usymtab_supEntry (uentry_copy (current));
599 	}
600 
601       paramno++;
602     } end_uentryList_elements;
603 }
604 
605 
enterParamsTemp(void)606 extern void enterParamsTemp (void)
607 {
608   usymtab_enterScope ();
609   enterFunctionParams (currentParamList);
610 }
611 
exitParamsTemp(void)612 extern void exitParamsTemp (void)
613 {
614   usymtab_quietPlainExitScope ();
615 }
616 
clabstract_globalDeclareFunction(idDecl tid)617 static /*@exposed@*/ uentry clabstract_globalDeclareFunction (idDecl tid)
618 {
619   ctype deftype = idDecl_getCtype (tid);
620   ctype rettype;
621   uentry ue;
622 
623   DPRINTF (("Global function: %s", idDecl_unparse (tid)));
624 
625   if (ctype_isFunction (deftype))
626     {
627       rettype = ctype_getReturnType (deftype);
628     }
629   else
630     {
631       rettype = ctype_unknown;
632     }
633 
634   /*
635   ** check has been moved here...
636   */
637 
638   if (ctype_isFunction (idDecl_getCtype (tid)))
639     {
640       ue = uentry_makeIdFunction (tid);
641       reflectSpecialCode (ue);
642       reflectArgsUsed (ue);
643       reflectStorageClass (ue);
644       uentry_checkParams (ue);
645 
646       DPRINTF (("Supercede function: %s", uentry_unparseFull (ue)));
647 
648       ue = usymtab_supGlobalEntryReturn (ue);
649       DPRINTF (("After supercede function: %s", uentry_unparseFull (ue)));
650 
651       DPRINTF (("Enter function: %s", uentry_unparseFull (ue)));
652       context_enterFunction (ue);
653       enterFunctionParams (uentry_getParams (ue));
654 
655       resetStorageClass ();
656       DPRINTF (("Function: %s", uentry_unparseFull (ue)));
657       return (ue);
658     }
659   else
660     {
661       llparseerror (message ("Non-function declaration: %q",
662 			     idDecl_unparse (tid)));
663       return (uentry_undefined);
664     }
665 }
666 
667 /*
668 ** for now, no type checking
669 ** (must check later though!)
670 */
671 
globalDeclareOldStyleFunction(idDecl tid)672 static /*@only@*/ uentry globalDeclareOldStyleFunction (idDecl tid)
673 {
674   uentry ue;
675 
676   /*
677   ** check has been moved here...
678   */
679 
680   if (cstring_equalLit (idDecl_observeId (tid), "main"))
681     {
682       context_setFlagTemp (FLG_MAINTYPE, FALSE);
683     }
684 
685   ue = uentry_makeIdFunction (tid);
686   reflectStorageClass (ue);
687   reflectSpecialCode (ue);
688   reflectArgsUsed (ue);
689   uentry_setDefined (ue, g_currentloc);
690   uentry_checkParams (ue);
691   resetStorageClass ();
692 
693   /* context_enterOldStyleScope (); */
694 
695   return (ue);
696 }
697 
oldStyleDeclareFunction(uentry e)698 static void oldStyleDeclareFunction (/*@only@*/ uentry e)
699 {
700   uentryList params = saveParamList;
701   ctype rt = uentry_getType (e);
702 
703   llassert (ctype_isFunction (rt));
704 
705   if (uentry_hasStateClauseList (e)
706       || uentry_hasConditions (e))
707     {
708       llfatalerror (message ("%q: Old-style function declaration uses a clause (rewrite with function parameters): %q",
709 			     fileloc_unparse (g_currentloc), uentry_unparse (e)));
710     }
711 
712   e = usymtab_supGlobalEntryReturn (e);
713 
714   context_enterFunction (e);
715   enterFunctionParams (params);
716   saveParamList = uentryList_undefined;
717   resetStorageClass ();
718 }
719 
oldStyleCompleteFunction(uentry e)720 static void oldStyleCompleteFunction (/*@only@*/ uentry e)
721 {
722   uentryList params = saveParamList;
723   ctype rt = uentry_getType (e);
724 
725   llassert (ctype_isFunction (rt));
726 
727   if (uentry_hasStateClauseList (e)
728       || uentry_hasConditions (e))
729     {
730       llfatalerror (message ("%q: Old-style function declaration uses a clause (rewrite with function parameters): %q",
731 			     fileloc_unparse (g_currentloc), uentry_unparse (e)));
732     }
733 
734   e = usymtab_supGlobalEntryReturn (e);
735 
736   context_completeOldStyleFunction (e);
737   enterFunctionParams (params);
738   saveParamList = uentryList_undefined;
739   resetStorageClass ();
740 }
741 
clabstract_declareFunction(idDecl tid)742 void clabstract_declareFunction (idDecl tid) /*@globals undef saveFunction; @*/
743 {
744   uentry ue;
745 
746   DPRINTF (("Declare function: %s", idDecl_unparse (tid)));
747 
748   if (ctype_isUnknown (idDecl_getCtype (tid)))
749     {
750       /*
751       ** No type, its really a plain name (int) declaration
752       */
753 
754       voptgenerror (FLG_IMPTYPE,
755 		    message ("No type before declaration name (implicit int type): %q",
756 			     idDecl_unparse (tid)),
757 		    g_currentloc);
758       tid = idDecl_replaceCtype (tid, ctype_int);
759       processVariable (tid);
760       saveFunction = uentry_undefined;
761     }
762   else
763     {
764       if (s_processingParams)
765 	{
766 	  ue = globalDeclareOldStyleFunction (tid);
767 	  saveFunction = ue;
768 	  DPRINTF (("Set save function: %s", uentry_unparseFull (ue)));
769 	}
770       else
771 	{
772 	  saveFunction = uentry_undefined;
773 
774 	  if (context_inRealFunction ())
775 	    {
776 	      ue = uentry_makeVariableLoc (idDecl_observeId (tid), ctype_unknown);
777 
778 	      llparseerror (message ("Function declared inside function: %q",
779 				     idDecl_unparse (tid)));
780 
781 	      context_quietExitFunction ();
782 	      ue = usymtab_supEntryReturn (ue);
783 	    }
784 	  else
785 	    {
786 	      if (context_inInnerScope ())
787 		{
788 		  llparseerror (message ("Declaration in inner context: %q",
789 					 idDecl_unparse (tid)));
790 
791 		  sRef_setGlobalScope ();
792 		  ue = uentry_makeVariableLoc (idDecl_observeId (tid),
793 					       ctype_unknown);
794 		  ue = usymtab_supGlobalEntryReturn (ue);
795 		  sRef_clearGlobalScope ();
796 		}
797 	      else
798 		{
799 		  ue = clabstract_globalDeclareFunction (tid);
800 		}
801 	    }
802 
803 	  resetGlobals ();
804 	}
805 
806       resetStorageClass ();
807     }
808 
809   idDecl_free (tid);
810 }
811 
declareStaticFunction(idDecl tid)812 void declareStaticFunction (idDecl tid) /*@globals undef saveFunction; @*/
813 {
814   uentry ue;
815 
816   DPRINTF (("Declare static funciton: %s", idDecl_unparse (tid)));
817 
818   if (s_processingParams)
819     {
820       ue = globalDeclareOldStyleFunction (tid);
821       saveFunction = ue;
822     }
823   else
824     {
825       saveFunction = uentry_undefined;
826 
827       if (context_inRealFunction ())
828 	{
829 	  ue = uentry_makeVariableLoc (idDecl_observeId (tid), ctype_unknown);
830 
831 	  llparseerror (message ("Function declared inside function: %q",
832 				 idDecl_unparse (tid)));
833 
834 	  context_quietExitFunction ();
835 	  ue = usymtab_supEntryReturn (ue);
836 	}
837       else
838 	{
839 	  if (context_inInnerScope ())
840 	    {
841 	      llparseerror (message ("Declaration in inner context: %q",
842 				     idDecl_unparse (tid)));
843 
844 	      sRef_setGlobalScope ();
845 	      ue = uentry_makeVariableLoc (idDecl_observeId (tid),
846 					   ctype_unknown);
847 	      ue = usymtab_supGlobalEntryReturn (ue);
848 	      sRef_clearGlobalScope ();
849 	    }
850 	  else
851 	    {
852 	      ctype deftype = idDecl_getCtype (tid);
853 	      ctype rettype;
854 
855 	      if (ctype_isFunction (deftype))
856 		{
857 		  rettype = ctype_getReturnType (deftype);
858 		}
859 	      else
860 		{
861 		  rettype = ctype_unknown;
862 		}
863 
864 	      /*
865 	      ** check has been moved here...
866 	      */
867 
868 	      if (ctype_isFunction (idDecl_getCtype (tid)))
869 		{
870 		  ue = uentry_makeIdFunction (tid);
871 		  reflectSpecialCode (ue);
872 		  reflectArgsUsed (ue);
873 		}
874 	      else
875 		{
876 		  DPRINTF (("Here we are!"));
877 		  llparseerror (message ("Inconsistent function declaration: %q",
878 					 idDecl_unparse (tid)));
879 
880 		  tid = idDecl_replaceCtype
881 		    (tid, ctype_makeFunction (ctype_unknown, uentryList_undefined));
882 		  ue = uentry_makeIdFunction (tid);
883 		}
884 
885 	      reflectStorageClass (ue);
886 	      uentry_setStatic (ue);
887 
888 	      uentry_checkParams (ue);
889 
890 	      DPRINTF (("Sub global entry: %s", uentry_unparse (ue)));
891 	      ue = usymtab_supGlobalEntryReturn (ue);
892 
893 	      context_enterFunction (ue);
894 	      enterFunctionParams (uentry_getParams (ue));
895 	      resetStorageClass ();
896 	    }
897 	}
898 
899       resetGlobals ();
900     }
901 
902   resetStorageClass ();
903   idDecl_free (tid);
904 }
905 
906 void
checkTypeDecl(uentry e,ctype rep)907 checkTypeDecl (uentry e, ctype rep)
908 {
909   cstring n = uentry_getName (e);
910 
911   DPRINTF (("Check type decl: %s", uentry_unparseFull (e)));
912 
913   if (cstring_equal (context_getBoolName (), n))
914     {
915       ctype rrep = ctype_realType (rep);
916 
917       /*
918       ** for abstract enum types, we need to fix the enum members:
919       ** they should have the abstract type, not the rep type.
920       */
921 
922       if (ctype_isEnum (ctype_realType (rrep)))
923 	{
924 	  enumNameList el = ctype_elist (rrep);
925 
926 	  enumNameList_elements (el, ye)
927 	    {
928 	      if (usymtab_existsGlob (ye))
929 		{
930 		  uentry ue = usymtab_lookupSafe (ye);
931 		  uentry_setType (ue, ctype_bool);
932 		}
933 
934 	      if (cstring_equal (context_getTrueName (), ye)
935 		  || cstring_equal (context_getFalseName (), ye))
936 		{
937 		  ;
938 		}
939 	      else
940 		{
941 		  vgenhinterror
942 		    (FLG_SYNTAX,
943 		     message ("Member of boolean enumerated type definition "
944 			      "does not match name set to represent true "
945 			      "or false: %s",
946 			      ye),
947 		     message ("Use -boolfalse and -booltrue to set the "
948 			      "name of false and true boolean values."),
949 		     uentry_whereDefined (e));
950 		}
951 	    } end_enumNameList_elements;
952 	}
953     }
954 
955   if (usymtab_exists (n))
956     {
957       usymId llm = usymtab_getId (n);
958       uentry le  = usymtab_getTypeEntry (typeId_fromUsymId (llm));
959 
960       uentry_setDeclared (e, g_currentloc);
961       uentry_setSref (e, sRef_makeGlobal (llm, uentry_getType (le), stateInfo_currentLoc ()));
962 
963       DPRINTF (("Here we are: %s / %s",
964 		n, context_getBoolName ()));
965 
966       if (uentry_isAbstractDatatype (le))
967 	{
968 	  ctype rrep = ctype_realType (rep);
969 
970 	  DPRINTF (("Abstract type: %s", uentry_unparseFull (le)));
971 
972 	  /*
973 	  ** for abstract enum types, we need to fix the enum members:
974 	  ** they should have the abstract type, not the rep type.
975 	  */
976 
977 	  if (ctype_isEnum (ctype_realType (rrep)))
978 	    {
979 	      ctype at = uentry_getAbstractType (le);
980 	      enumNameList el = ctype_elist (rrep);
981 
982 	      enumNameList_elements (el, ye)
983 		{
984 		  if (usymtab_existsGlob (ye))
985 		    {
986 		      uentry ue = usymtab_lookupSafe (ye);
987 
988 		      llassert (uentry_isEitherConstant (ue));
989 
990 		      /* evans 2002-04-22 */
991 		      if (ctype_isBool (uentry_getType (ue)))
992 			{
993 			  /*
994 			  ** If set using -booltrue or -boolfalse, don't change the type.
995 			  */
996 			}
997 		      else
998 			{
999 			  llassertprint (ctype_match (uentry_getType (ue), rrep),
1000 					 ("Bad enum: %s / %s",
1001 					  uentry_unparse (ue),
1002 					  ctype_unparse (rrep)));
1003 
1004 			  uentry_setType (ue, at);
1005 			}
1006 		    }
1007 		} end_enumNameList_elements;
1008 	    }
1009 
1010 	  if (uentry_isMutableDatatype (le))
1011 	    {
1012 	      /* maybe more complicated if abstract and immutable ? */
1013 
1014 	      if (!ctype_isRealPointer (rep) && !ctype_isRealAbstract (rep))
1015 		{
1016 		  voptgenerror
1017 		    (FLG_MUTREP,
1018 		     message ("Mutable abstract type %s declared without pointer "
1019 			      "indirection: %s (violates assignment semantics)",
1020 			      n, ctype_unparse (rep)),
1021 		     uentry_whereDefined (e));
1022 
1023 		  uentry_setMutable (e);
1024 		}
1025 	    }
1026 	}
1027     }
1028   else
1029     {
1030       fileloc fl = uentry_whereDeclared (e);
1031 
1032       if (context_getFlag (FLG_LIKELYBOOL)
1033 	  && !context_getFlag (FLG_BOOLINT))
1034 	{
1035 	  if ((cstring_equalLit (n, "BOOL")
1036 	       || cstring_equalLit (n, "Bool")
1037 	       || cstring_equalLit (n, "bool")
1038 	       || cstring_equalLit (n, "boolean")
1039 	       || cstring_equalLit (n, "Boolean")
1040 	       || cstring_equalLit (n, "BOOLEAN"))
1041 	      && !(cstring_equal (n, context_getBoolName ())))
1042 	    {
1043 	      if (context_setBoolName ()) {
1044 		voptgenerror
1045 		  (FLG_LIKELYBOOL,
1046 		   message ("Type %s is probably meant as a boolean type, but does "
1047 			    "not match the boolean type name \"%s\".",
1048 			    n,
1049 			    context_getBoolName ()),
1050 		   fl);
1051 	      } else
1052 		voptgenerror
1053 		  (FLG_LIKELYBOOL,
1054 		   message ("Type %s is probably meant as a boolean type, "
1055 			    "but the boolean type name is not set. "
1056 			    "Use -booltype %s to set it.",
1057 			    n,
1058 			    n),
1059 		   fl);
1060 		}
1061 	}
1062 
1063       if (!uentry_isStatic (e)
1064 	  && !ctype_isFunction (uentry_getType (e))
1065 	  && !fileloc_isLib (fl)
1066 	  && !fileloc_isImport (fl)
1067 	  && fileloc_isHeader (fl))
1068 	{
1069 	  voptgenerror (FLG_EXPORTTYPE,
1070 			message ("Type exported, but not specified: %s\n", n),
1071 			fl);
1072 	}
1073     }
1074 
1075   cstring_free (n);
1076 }
1077 
1078 uentryList
fixUentryList(idDeclList tl,qtype q)1079 fixUentryList (idDeclList tl, qtype q)
1080 {
1081   uentryList f = uentryList_new ();
1082 
1083   idDeclList_elements (tl, i)
1084   {
1085     if (idDecl_isDefined (i))
1086       {
1087 	uentry ue;
1088 	uentry old;
1089 	ctype rt;
1090 
1091 	(void) idDecl_fixBase (i, q);
1092 
1093 	/*
1094 	** implicit annotations
1095 	*/
1096 
1097 	(void) fixStructDecl (i);
1098 
1099 	ue = uentry_makeIdVariable (i);
1100 	rt = ctype_realType (uentry_getType (ue));
1101 
1102 	/*
1103 	** where is this here???
1104 
1105 	if (ctype_isArray (rt) || ctype_isSU (rt))
1106 	  {
1107 	    sRef_setAllocated (uentry_getSref (ue), uentry_whereDefined (ue));
1108 	  }
1109 
1110         **
1111 	*/
1112 
1113 	if (uentry_isValid (old = uentryList_lookupField (f, uentry_rawName (ue))))
1114 	  {
1115 	    if (optgenerror (FLG_SYNTAX,
1116 			     message ("Field name reused: %s", uentry_rawName (ue)),
1117 			     uentry_whereDefined (ue)))
1118 	      {
1119 		llgenmsg (message ("Previous use of %s", uentry_rawName (ue)),
1120 			  uentry_whereDefined (old));
1121 	      }
1122 	  }
1123 
1124 	f = uentryList_add (f, ue);
1125       }
1126   } end_idDeclList_elements;
1127 
1128   idDeclList_free (tl);
1129   return (f);
1130 }
1131 
1132 /*
1133 ** This is a hack to support unnamed struct/union fields as done by
1134 ** Microsoft VC++.  It is not supported by the ANSI standard.
1135 **
1136 ** The inner fields are added to the outer structure.  This is meaningful
1137 ** for nesting structs inside unions, but Splint does no related
1138 ** checking.
1139 */
1140 
1141 uentryList
fixUnnamedDecl(qtype q)1142 fixUnnamedDecl (qtype q)
1143 {
1144   ctype ct = ctype_realType (qtype_getType (q));
1145 
1146   if (ctype_isStruct (ct) || ctype_isUnion (ct))
1147     {
1148       return uentryList_single (uentry_makeUnnamedVariable (ct));
1149     }
1150   else if (ctype_isEnum (ct))
1151     {
1152       /* evans 2002-02-05: nothing to do for unnamed enum lists */
1153       return uentryList_undefined;
1154     }
1155   else
1156     {
1157       voptgenerror
1158 	(FLG_SYNTAX,
1159 	 message ("Type name in field declarations: %s", qtype_unparse (q)),
1160 	 g_currentloc);
1161     }
1162 
1163   return uentryList_undefined;
1164 }
1165 
setStorageClass(storageClassCode sc)1166 void setStorageClass (storageClassCode sc)
1167 {
1168   storageClass = sc;
1169 }
1170 
1171 void
setProcessingIterVars(uentry iter)1172 setProcessingIterVars (uentry iter)
1173 {
1174   s_processingIterVars = TRUE;
1175   currentIter = iter;
1176   saveIterParamNo = 0;
1177 }
1178 
1179 void
setProcessingGlobalsList()1180 setProcessingGlobalsList ()
1181 {
1182   s_processingGlobals = TRUE;
1183   fcnNoGlobals = FALSE;
1184 }
1185 
1186 static bool ProcessingGlobMods = FALSE;
1187 
1188 void
setProcessingGlobMods()1189 setProcessingGlobMods ()
1190 {
1191   ProcessingGlobMods = TRUE;
1192 }
1193 
1194 void
clearProcessingGlobMods()1195 clearProcessingGlobMods ()
1196 {
1197   ProcessingGlobMods = FALSE;
1198 }
1199 
1200 bool
isProcessingGlobMods()1201 isProcessingGlobMods ()
1202 {
1203   return (ProcessingGlobMods);
1204 }
1205 
resetGlobals(void)1206 static void resetGlobals (void)
1207 {
1208   s_processingGlobals = FALSE;
1209   fcnNoGlobals = FALSE;
1210 }
1211 
1212 void
unsetProcessingGlobals()1213 unsetProcessingGlobals ()
1214 {
1215   s_processingGlobals = FALSE;
1216 }
1217 
1218 void
setProcessingVars(qtype q)1219 setProcessingVars (/*@only@*/ qtype q)
1220 {
1221   s_processingVars = TRUE;
1222   qtype_free (processingType);
1223   processingType = q;
1224 }
1225 
1226 static void
setGenericParamList(uentryList pm)1227 setGenericParamList (/*@dependent@*/ uentryList pm)
1228 {
1229   s_processingParams = TRUE;
1230   saveParamList = pm;
1231 }
1232 
1233 void
setProcessingTypedef(qtype q)1234 setProcessingTypedef (qtype q)
1235 {
1236   s_processingTypedef = TRUE;
1237 
1238   qtype_free (processingType);
1239   processingType = q;
1240 }
1241 
1242 void
unsetProcessingVars()1243 unsetProcessingVars ()
1244 {
1245   resetStorageClass ();
1246   s_processingVars = FALSE;
1247 }
1248 
1249 void
oldStyleDoneParams()1250 oldStyleDoneParams ()
1251 {
1252   if (s_processingParams)
1253     {
1254       if (uentry_isInvalid (saveFunction))
1255 	{
1256 	  llbuglit ("unsetProcessingVars: no saved function\n");
1257 	}
1258       else
1259 	{
1260 	  ctype ct = ctype_getReturnType (uentry_getType (saveFunction));
1261 	  uentryList params = uentryList_copy (saveParamList);
1262 	  ctype ct2 = ctype_makeFunction (ct, params);
1263 
1264 	  uentry_setType (saveFunction, ct2);
1265 	  s_processingParams = FALSE;
1266 
1267 	  oldStyleCompleteFunction (saveFunction);
1268 	  saveFunction = uentry_undefined;
1269 	  resetGlobals ();
1270 	}
1271     }
1272   else
1273     {
1274       /*
1275       ** If the paramlist used a type name, we could be here.
1276       */
1277 
1278       llfatalerror (message ("%q: Old-style function parameter list uses a "
1279 			     "type name.", fileloc_unparse (g_currentloc)));
1280     }
1281 }
1282 
1283 void
checkDoneParams()1284 checkDoneParams ()
1285 {
1286   if (uentry_isValid (saveFunction))
1287     {
1288       /*
1289       ** old style declaration
1290       */
1291 
1292       ctype ct = ctype_getReturnType (uentry_getType (saveFunction));
1293       ctype ct2;
1294 
1295       DPRINTF (("save function: %s", uentry_unparseFull (saveFunction)));
1296 
1297       uentryList_elements (saveParamList, current)
1298 	{
1299 	  uentry_setType (current, ctype_int); /* all params are ints */
1300 	} end_uentryList_elements;
1301 
1302       ct2 = ctype_makeParamsFunction (ct, uentryList_copy (saveParamList));
1303 
1304       uentry_setType (saveFunction, ct2);
1305       s_processingParams = FALSE;
1306 
1307       oldStyleDeclareFunction (saveFunction);
1308       saveFunction = uentry_undefined;
1309     }
1310 }
1311 
clabstract_declareType(exprNodeList decls,warnClause warn)1312 void clabstract_declareType (/*@only@*/ exprNodeList decls, /*@only@*/ warnClause warn)
1313 {
1314   llassert (s_processingTypedef);
1315 
1316   DPRINTF (("Declare type: %s", exprNodeList_unparse (decls)));
1317 
1318   if (warnClause_isDefined (warn))
1319     {
1320       DPRINTF (("Has a warn clause!"));
1321       DPRINTF (("Warn: %s", warnClause_unparse (warn)));
1322 
1323       exprNodeList_elements (decls, el)
1324 	{
1325 	  uentry ue = exprNode_getUentry (el);
1326 	  cstring uname = uentry_getName (ue);
1327 
1328 	  DPRINTF (("Entry: %s", exprNode_unparse (el)));
1329 
1330 	  /*
1331 	  ** Need to lookup again to make sure we have the right one...
1332 	  */
1333 
1334 	  ue = usymtab_lookupExposeGlob (uname);
1335 
1336 	  llassert (uentry_isValid (ue));
1337 	  llassert (uentry_isDatatype (ue));
1338 
1339 	  DPRINTF (("Warning for %s: %s",
1340 		    uentry_unparse (ue), warnClause_unparse (warn)));
1341 
1342 	  uentry_addWarning (ue, warnClause_copy (warn));
1343 	  DPRINTF (("After add warning: %s", uentry_unparseFull (ue)));
1344 	  cstring_free (uname);
1345 	} end_exprNodeList_elements;
1346     }
1347 
1348   warnClause_free (warn);
1349   exprNodeList_free (decls);
1350   unsetProcessingTypedef ();
1351 }
1352 
1353 void
unsetProcessingTypedef()1354 unsetProcessingTypedef ()
1355 {
1356   s_processingTypedef = FALSE;
1357 }
1358 
checkConstant(qtype t,idDecl id)1359 void checkConstant (qtype t, idDecl id)
1360 {
1361   uentry e;
1362 
1363   id = idDecl_fixBase (id, t);
1364   e = uentry_makeIdConstant (id);
1365 
1366   reflectStorageClass (e);
1367   resetStorageClass ();
1368 
1369   DPRINTF (("Constant: %s", uentry_unparseFull (e)));
1370   usymtab_supGlobalEntry (e);
1371 }
1372 
checkValueConstant(qtype t,idDecl id,exprNode e)1373 void checkValueConstant (qtype t, idDecl id, exprNode e)
1374 {
1375   uentry ue;
1376 
1377   id = idDecl_fixBase (id, t);
1378   ue = uentry_makeIdConstant (id);
1379   reflectStorageClass (ue);
1380   resetStorageClass ();
1381 
1382   if (exprNode_isDefined (e))
1383     {
1384       if (!exprNode_matchType (uentry_getType (ue), e))
1385 	{
1386 	  (void) gentypeerror
1387 	    (exprNode_getType (e), e,
1388 	     uentry_getType (ue), exprNode_undefined,
1389 	     message ("Constant %q initialized to type %t, expects %t: %s",
1390 		      uentry_getName (ue),
1391 		      exprNode_getType (e),
1392 		      uentry_getType (ue),
1393 		      exprNode_unparse (e)),
1394 	     exprNode_loc (e));
1395 	}
1396       else
1397 	{
1398 	  if (exprNode_hasValue (e))
1399 	    {
1400 	      uentry_mergeConstantValue (ue, multiVal_copy (exprNode_getValue (e)));
1401 	    }
1402 	  else
1403 	    {
1404 	      DPRINTF (("No value: %s", exprNode_unparse (e)));
1405 	    }
1406 	}
1407     }
1408 
1409   DPRINTF (("Constant value: %s", uentry_unparseFull (ue)));
1410   usymtab_supGlobalEntry (ue);
1411 }
1412 
processVariable(idDecl t)1413 static void processVariable (idDecl t)
1414 {
1415   uentry e;
1416   ctype ct;
1417 
1418   ct = ctype_realType (idDecl_getCtype (t));
1419 
1420   if (s_processingParams)
1421     {
1422       cstring id = idDecl_getName (t);
1423       int paramno = uentryList_lookupRealName (saveParamList, id);
1424 
1425       if (paramno >= 0)
1426 	{
1427 	  uentry cparam = uentryList_getN (saveParamList, paramno);
1428 
1429 	  DPRINTF (("Processing param: %s", uentry_unparseFull (cparam)));
1430 	  uentry_setType (cparam, idDecl_getCtype (t));
1431 	  uentry_reflectQualifiers (cparam, idDecl_getQuals (t));
1432 	  uentry_setDeclaredOnly (cparam, context_getSaveLocation ());
1433 	  DPRINTF (("Processing param: %s", uentry_unparseFull (cparam)));
1434 	}
1435       else
1436 	{
1437 	  llfatalerrorLoc
1438 	    (message ("Old style declaration uses unlisted parameter: %s",
1439 		      id));
1440 	}
1441     }
1442   else
1443     {
1444       fileloc loc;
1445 
1446       if (context_inIterDef ())
1447 	{
1448 	  cstring pname = makeParam (idDecl_observeId (t));
1449 	  uentry p = usymtab_lookupSafe (pname);
1450 
1451 	  cstring_free (pname);
1452 
1453 	  if (uentry_isYield (p))
1454 	    {
1455 	      e = uentry_makeParam (t, sRef_getParam (uentry_getSref (p)));
1456 	      uentry_checkYieldParam (p, e);
1457 	      usymtab_supEntrySref (e);
1458 	      return;
1459 	    }
1460 	}
1461 
1462       if ((hasSpecialCode () || argsUsed)
1463 	  && ctype_isFunction (idDecl_getCtype (t)))
1464 	{
1465 	  e = uentry_makeIdFunction (t);
1466 	  reflectSpecialCode (e);
1467 	  reflectArgsUsed (e);
1468 	}
1469       else
1470 	{
1471 	  e = uentry_makeIdVariable (t);
1472 	}
1473 
1474       loc = uentry_whereDeclared (e);
1475 
1476       /*
1477 	if (context_inGlobalScope ())
1478 	{
1479 	uentry_checkParams was here!
1480 	}
1481       */
1482 
1483       if (ctype_isFunction (uentry_getType (e)))
1484 	{
1485 	  clabstract_prepareFunction (e);
1486 	}
1487 
1488       DPRINTF (("Superceding... %s", uentry_unparseFull (e)));
1489       e = usymtab_supEntrySrefReturn (e);
1490       DPRINTF (("After superceding... %s", uentry_unparseFull (e)));
1491 
1492       if (uentry_isExtern (e) && !context_inGlobalScope ())
1493 	{
1494 	  voptgenerror
1495 	    (FLG_NESTEDEXTERN,
1496 	     message ("Declaration using extern inside function scope: %q",
1497 		      uentry_unparse (e)),
1498 	     g_currentloc);
1499 
1500 	  uentry_setDefined (e, fileloc_getExternal ());
1501 	  sRef_setDefined (uentry_getSref (e), fileloc_getExternal ());
1502 	}
1503 
1504       if (uentry_isFunction (e))
1505 	{
1506 	  if (!context_inXHFile ())
1507 	    {
1508 	      checkParamNames (e);
1509 	    }
1510 	}
1511 
1512       if (uentry_isVar (e) && uentry_isCheckedUnknown (e))
1513 	{
1514 	  sRef sr = uentry_getSref (e);
1515 
1516 	  if (sRef_isLocalVar (sr))
1517 	    {
1518 	      if (context_getFlag (FLG_IMPCHECKMODINTERNALS))
1519 		{
1520 		  uentry_setCheckMod (e);
1521 		}
1522 	      else
1523 		{
1524 		  uentry_setUnchecked (e);
1525 		}
1526 	    }
1527 	  else if (sRef_isFileStatic (sr))
1528 	    {
1529 	      if (context_getFlag (FLG_IMPCHECKEDSTRICTSTATICS))
1530 		{
1531 		  uentry_setCheckedStrict (e);
1532 		}
1533 	      else if (context_getFlag (FLG_IMPCHECKEDSTATICS))
1534 		{
1535 		  uentry_setChecked (e);
1536 		}
1537 	      else if (context_getFlag (FLG_IMPCHECKMODSTATICS))
1538 		{
1539 		  uentry_setCheckMod (e);
1540 		}
1541 	      else
1542 		{
1543 		  ;
1544 		}
1545 	    }
1546 	  else /* real global */
1547 	    {
1548 	      llassert (sRef_isRealGlobal (sr));
1549 
1550 	      if (context_getFlag (FLG_IMPCHECKEDSTRICTGLOBALS))
1551 		{
1552 		  uentry_setCheckedStrict (e);
1553 		}
1554 	      else if (context_getFlag (FLG_IMPCHECKEDGLOBALS))
1555 		{
1556 		  uentry_setChecked (e);
1557 		}
1558 	      else if (context_getFlag (FLG_IMPCHECKMODGLOBALS))
1559 		{
1560 		  uentry_setCheckMod (e);
1561 		}
1562 	      else
1563 		{
1564 		  ;
1565 		}
1566 	    }
1567 	}
1568     }
1569 }
1570 
processNamedDecl(idDecl t)1571 void processNamedDecl (idDecl t)
1572 {
1573   if (qtype_isUndefined (processingType))
1574     {
1575       processingType = qtype_create (ctype_int);
1576       t = idDecl_fixBase (t, processingType);
1577 
1578       voptgenerror (FLG_IMPTYPE,
1579 		    message ("No type before declaration name (implicit int type): %q",
1580 			     idDecl_unparse (t)),
1581 		    g_currentloc);
1582     }
1583   else
1584     {
1585       t = idDecl_fixBase (t, processingType);
1586     }
1587 
1588   DPRINTF (("Declare: %s", idDecl_unparse (t)));
1589 
1590   if (s_processingGlobals)
1591     {
1592       cstring id = idDecl_getName (t);
1593       uentry ue = usymtab_lookupSafe (id);
1594 
1595       if (!uentry_isValid (ue))
1596 	{
1597 	  llerror (FLG_UNRECOG,
1598 		   message ("Variable used in globals list is undeclared: %s", id));
1599 	}
1600       else
1601 	{
1602 	  if (!ctype_match (uentry_getType (ue), idDecl_getCtype (t)))
1603 	    {
1604 	      voptgenerror
1605 		(FLG_INCONDEFS,
1606 		 message ("Variable %s used in globals list declared %s, "
1607 			  "but listed as %s",
1608 			  id, ctype_unparse (uentry_getType (ue)),
1609 			  ctype_unparse (idDecl_getCtype (t))),
1610 		 g_currentloc);
1611 	    }
1612 	  else
1613 	    {
1614 	      sRef sr = sRef_copy (uentry_getSref (ue));
1615 	      reflectGlobalQualifiers (sr, idDecl_getQuals (t));
1616 	    }
1617 	}
1618     }
1619   else if (s_processingVars)
1620     {
1621       processVariable (t);
1622     }
1623   else if (s_processingTypedef)
1624     {
1625       ctype ct = idDecl_getCtype (t);
1626       uentry e;
1627 
1628       DPRINTF (("Processing typedef: %s", ctype_unparse (ct)));
1629 
1630       e = uentry_makeIdDatatype (t);
1631 
1632       if (cstring_equal (idDecl_getName (t), context_getBoolName ())) {
1633 	ctype rt = ctype_realType (ct);
1634 
1635 	if (ctype_isEnum (rt)) {
1636 	  ;
1637 	} else {
1638 	  if (!(ctype_isInt (rt)
1639 		|| ctype_isUnknown (rt)
1640 		|| ctype_isChar (rt))) {
1641 	    (void) llgenerror
1642 	      (FLG_BOOLTYPE,
1643 	       message ("Boolean type %s defined using non-standard type %s (integral, char or enum type expected)",
1644 			context_getBoolName (),
1645 			ctype_unparse (ct)),
1646 	       uentry_whereLast (e));
1647 	  }
1648 
1649 	  ct = ctype_bool;
1650 	  uentry_setType (e, ct);
1651 	}
1652       }
1653 
1654       reflectStorageClass (e);
1655       checkTypeDecl (e, ct);
1656 
1657       e = usymtab_supReturnTypeEntry (e);
1658     }
1659   else
1660     {
1661       llparseerror (message ("Suspect missing struct or union keyword: %q",
1662 			     idDecl_unparse (t)));
1663     }
1664 
1665   }
1666 
1667 /*
1668 ** moved from grammar
1669 */
1670 
fixStructDecl(idDecl d)1671 static idDecl fixStructDecl (/*@returned@*/ idDecl d)
1672 {
1673   if (ctype_isVisiblySharable (idDecl_getCtype (d))
1674       && context_getFlag (FLG_STRUCTIMPONLY))
1675     {
1676       if (!qualList_hasAliasQualifier (idDecl_getQuals (d)))
1677 	{
1678 	  if (qualList_hasExposureQualifier (idDecl_getQuals (d)))
1679 	    {
1680 	      idDecl_addQual (d, qual_createDependent ());
1681 	    }
1682 	  else
1683 	    {
1684 	      idDecl_addQual (d, qual_createImpOnly ());
1685 	    }
1686 	}
1687     }
1688 
1689   return d;
1690 }
1691 
1692 ctype
declareUnnamedStruct(uentryList f)1693 declareUnnamedStruct (/*@only@*/ uentryList f)
1694 {
1695   DPRINTF (("Unnamed struct: %s", uentryList_unparse (f)));
1696 
1697   if (context_maybeSet (FLG_NUMSTRUCTFIELDS))
1698     {
1699       int num = uentryList_size (f);
1700       int max = context_getValue (FLG_NUMSTRUCTFIELDS);
1701 
1702       if (num > max)
1703 	{
1704 	  voptgenerror
1705 	    (FLG_NUMSTRUCTFIELDS,
1706 	     message ("Structure declared with %d fields "
1707 		      "(limit is set to %d)",
1708 		      num, max),
1709 	     g_currentloc);
1710 	}
1711     }
1712 
1713   return (ctype_createUnnamedStruct (f));
1714 }
1715 
1716 ctype
declareUnnamedUnion(uentryList f)1717 declareUnnamedUnion (/*@only@*/ uentryList f)
1718 {
1719   DPRINTF (("Unnamed union: %s", uentryList_unparse (f)));
1720 
1721   if (context_maybeSet (FLG_NUMSTRUCTFIELDS))
1722     {
1723       int num = uentryList_size (f);
1724       int max = context_getValue (FLG_NUMSTRUCTFIELDS);
1725 
1726       if (num > max)
1727 	{
1728 	  voptgenerror
1729 	    (FLG_NUMSTRUCTFIELDS,
1730 	     message ("Union declared with %d fields "
1731 		      "(limit is set to %d)",
1732 		      num, max),
1733 	     g_currentloc);
1734 	}
1735     }
1736 
1737   return (ctype_createUnnamedUnion (f));
1738 }
1739 
declareStruct(cstring id,uentryList f)1740 ctype declareStruct (cstring id, /*@only@*/ uentryList f)
1741 {
1742   ctype ct;
1743   uentry ue;
1744   int num = uentryList_size (f);
1745 
1746   DPRINTF (("Declare struct: %s / %s [%d]", id, uentryList_unparse (f),
1747 	    uentryList_size (f)));
1748 
1749   ct = ctype_createStruct (cstring_copy (id), f);
1750 
1751   DPRINTF (("Ctype: %s", ctype_unparse (ct)));
1752 
1753   ue = uentry_makeStructTagLoc (id, ct);
1754 
1755   DPRINTF (("ue: %s", uentry_unparseFull (ue)));
1756 
1757   if (context_maybeSet (FLG_NUMSTRUCTFIELDS))
1758     {
1759       int max = context_getValue (FLG_NUMSTRUCTFIELDS);
1760 
1761       if (num > max)
1762 	{
1763 	  voptgenerror
1764 	    (FLG_NUMSTRUCTFIELDS,
1765 	     message ("Structure %q declared with %d fields "
1766 		      "(limit is set to %d)",
1767 		      uentry_getName (ue), num, max),
1768 	     uentry_whereLast (ue));
1769 	}
1770     }
1771 
1772   return (usymtab_supTypeEntry (ue));
1773 }
1774 
declareUnion(cstring id,uentryList f)1775 ctype declareUnion (cstring id, uentryList f)
1776 {
1777   ctype ct;
1778   uentry ue;
1779   int num = uentryList_size (f);
1780 
1781   ct = ctype_createUnion (cstring_copy (id), f);
1782   ue = uentry_makeUnionTagLoc (id, ct);
1783 
1784   if (context_maybeSet (FLG_NUMSTRUCTFIELDS))
1785     {
1786       int max = context_getValue (FLG_NUMSTRUCTFIELDS);
1787 
1788       if (num > max)
1789 	{
1790 	  voptgenerror
1791 	    (FLG_NUMSTRUCTFIELDS,
1792 	     message ("Union %q declared with %d fields "
1793 		      "(limit is set to %d)",
1794 		      uentry_getName (ue), num, max),
1795 	     uentry_whereLast (ue));
1796 	}
1797     }
1798 
1799   return (usymtab_supTypeEntry (ue));
1800 }
1801 
handleStruct(cstring id)1802 ctype handleStruct (/*@only@*/ cstring id)
1803 {
1804   if (usymtab_existsStructTag (id))
1805     {
1806       ctype ct = uentry_getAbstractType (usymtab_lookupStructTag (id));
1807 
1808       cstring_free (id);
1809       return ct;
1810     }
1811   else
1812     {
1813       return (ctype_createForwardStruct (id));
1814     }
1815 }
1816 
handleUnion(cstring id)1817 ctype handleUnion (/*@only@*/ cstring id)
1818 {
1819   if (usymtab_existsUnionTag (id))
1820     {
1821       ctype ret = uentry_getAbstractType (usymtab_lookupUnionTag (id));
1822       cstring_free (id);
1823       return (ret);
1824     }
1825   else
1826     {
1827       return (ctype_createForwardUnion (id));
1828     }
1829 }
1830 
1831 ctype
handleEnum(cstring id)1832 handleEnum (cstring id)
1833 {
1834   if (usymtab_existsEnumTag (id))
1835     {
1836       ctype ret = uentry_getAbstractType (usymtab_lookupEnumTag (id));
1837       cstring_free (id);
1838       return ret;
1839     }
1840   else
1841     {
1842       return (ctype_createForwardEnum (id));
1843     }
1844 }
1845 
processingIterVars(void)1846 bool processingIterVars (void)
1847 {
1848   return s_processingIterVars;
1849 }
1850 
getCurrentIter(void)1851 uentry getCurrentIter (void)
1852 {
1853   return currentIter;
1854 }
1855 
1856 static bool flipOldStyle = FALSE;
1857 static bool flipNewStyle = TRUE;
1858 
setFlipOldStyle()1859 void setFlipOldStyle ()          { flipOldStyle = TRUE; }
isFlipOldStyle()1860 bool isFlipOldStyle ()           { return flipOldStyle; }
isNewStyle()1861 bool isNewStyle ()               { return flipNewStyle; }
setNewStyle()1862 void setNewStyle ()              { flipNewStyle = TRUE; }
1863 
handleParamIdList(uentryList params)1864 /*@dependent@*/ uentryList handleParamIdList (/*@dependent@*/ uentryList params)
1865 {
1866   int paramno = 0;
1867 
1868   /*
1869   ** this is a really YUCKY hack to handle old style
1870   ** declarations.
1871   */
1872 
1873   voptgenerror (FLG_OLDSTYLE,
1874 		cstring_makeLiteral ("Old style function declaration"),
1875 		g_currentloc);
1876 
1877   DPRINTF (("Handle old style params: %s", uentryList_unparseFull (params)));
1878 
1879   uentryList_elements (params, current)
1880     {
1881       uentry_setParam (current);
1882       uentry_setSref (current, sRef_makeParam
1883 		      (paramno, ctype_unknown,
1884 		       stateInfo_makeLoc (uentry_whereLast (current), SA_DECLARED)));
1885       paramno++;
1886     } end_uentryList_elements;
1887 
1888   setGenericParamList (params);
1889   cscannerHelp_setExpectingTypeName ();
1890 
1891   return params;
1892 }
1893 
handleParamTypeList(uentryList params)1894 /*@dependent@*/ uentryList handleParamTypeList (/*@returned@*/ uentryList params)
1895 {
1896   if (flipOldStyle)
1897     {
1898       uentryList_fixMissingNames (params);
1899 
1900       voptgenerror (FLG_OLDSTYLE,
1901 		    cstring_makeLiteral ("Old style function declaration."),
1902 		    g_currentloc);
1903 
1904       setGenericParamList (params);
1905       flipOldStyle = FALSE;
1906       cscannerHelp_setExpectingTypeName ();
1907     }
1908 
1909   return (params);
1910 }
1911 
1912 void
doVaDcl()1913 doVaDcl ()
1914 {
1915   ctype c = ctype_unknown;
1916   cstring id = cstring_makeLiteral ("va_alist");
1917   uentry e;
1918 
1919   if (s_processingParams)
1920     {
1921       int i = uentryList_lookupRealName (saveParamList, id);
1922 
1923       if (i >= 0)
1924 	{
1925 	  fileloc loc = context_getSaveLocation ();
1926 	  e = uentry_makeVariableSrefParam
1927 	    (id, c, loc,
1928 	     sRef_makeParam (i, c, stateInfo_makeLoc (loc, SA_DECLARED)));
1929 	}
1930       else
1931 	{
1932 	  e = uentry_undefined; /* suppress gcc message */
1933 	  llfatalerrorLoc (cstring_makeLiteral ("va_dcl used without va_alist"));
1934 	}
1935     }
1936   else
1937     {
1938       llerror (FLG_SYNTAX, cstring_makeLiteral ("va_dcl used outside of function declaration"));
1939       e = uentry_makeVariableLoc (id, c);
1940     }
1941 
1942   cstring_free (id);
1943   uentry_setUsed (e, g_currentloc);
1944   usymtab_supEntrySref (e);
1945 }
1946 
modListPointer(sRef s)1947 /*@exposed@*/ sRef modListPointer (/*@exposed@*/ sRef s)
1948 {
1949   ctype ct = sRef_getType (s);
1950   ctype rt = ctype_realType (ct);
1951 
1952   if (ctype_isAP (rt))
1953     {
1954       if (context_inHeader () && ctype_isAbstract (ct))
1955 	{
1956 	  voptgenerror
1957 	    (FLG_ABSTRACT,
1958 	     message
1959 	     ("Modifies clause in header file dereferences abstract "
1960 	      "type %s (interface modifies clause should not depend "
1961 	      "on or expose type representation): %q",
1962 	      ctype_unparse (ct),
1963 	      sRef_unparse (s)),
1964 	     g_currentloc);
1965 	}
1966 
1967       return (sRef_constructPointer (s));
1968     }
1969   else
1970     {
1971       if (ctype_isKnown (rt))
1972 	{
1973 	  voptgenerror
1974 	    (FLG_TYPE,
1975 	     message ("Implementation modifies clause dereferences non-pointer (type %s): %q",
1976 		      ctype_unparse (rt),
1977 		      sRef_unparse (s)),
1978 	     g_currentloc);
1979 	}
1980 
1981       return s;
1982     }
1983 }
1984 
modListFieldAccess(sRef s,cstring f)1985 /*@exposed@*/ sRef modListFieldAccess (sRef s, cstring f)
1986 {
1987   ctype ct = sRef_getType (s);
1988   ctype rt = ctype_realType (ct);
1989 
1990   if (ctype_isStructorUnion (rt))
1991     {
1992       uentry tf = uentryList_lookupField (ctype_getFields (rt), f);
1993 
1994       if (uentry_isUndefined (tf))
1995 	{
1996 	  voptgenerror (FLG_TYPE,
1997 			message ("Modifies list accesses non-existent "
1998 				 "field %s of %t: %q", f, ct,
1999 				 sRef_unparse (s)),
2000 			g_currentloc);
2001 
2002 	  cstring_free (f);
2003 	  return sRef_undefined;
2004 	}
2005       else
2006 	{
2007 	  if (ctype_isAbstract (ct) && context_inHeader ())
2008 	    {
2009 	      voptgenerror
2010 		(FLG_ABSTRACT,
2011 		 message
2012 		 ("Modifies clause in header file accesses abstract "
2013 		  "type %s (interface modifies clause should not depend "
2014 		  "on or expose type representation): %q",
2015 		  ctype_unparse (ct),
2016 		  sRef_unparse (s)),
2017 		 g_currentloc);
2018 	    }
2019 	}
2020 
2021       cstring_markOwned (f);
2022       return (sRef_makeField (s, f));
2023     }
2024   else
2025     {
2026       voptgenerror
2027 	(FLG_TYPE,
2028 	 message ("Modifies clause dereferences non-pointer (type %s): %q",
2029 		  ctype_unparse (rt),
2030 		  sRef_unparse (s)),
2031 	 g_currentloc);
2032 
2033       cstring_free (f);
2034       return s;
2035     }
2036 }
2037 
clabstract_unrecognizedGlobal(cstring s)2038 /*@dependent@*/ sRef clabstract_unrecognizedGlobal (cstring s)
2039 {
2040   if (cstring_equalLit (s, "nothing"))
2041     {
2042       return sRef_makeNothing ();
2043     }
2044   else if (cstring_equalLit (s, "internalState"))
2045     {
2046       return sRef_makeInternalState ();
2047     }
2048   else if (cstring_equalLit (s, "fileSystem")
2049 	   || cstring_equalLit (s, "systemState"))
2050     {
2051       return sRef_makeSystemState ();
2052     }
2053   else
2054     {
2055       voptgenerror
2056 	(FLG_UNRECOG,
2057 	 message ("Unrecognized identifier in globals list: %s", s),
2058 	 g_currentloc);
2059 
2060       return sRef_undefined;
2061     }
2062 }
2063 
modListArrowAccess(sRef s,cstring f)2064 /*@exposed@*/ sRef modListArrowAccess (sRef s, cstring f)
2065 {
2066   ctype ct = sRef_getType (s);
2067   ctype rt = ctype_realType (ct);
2068 
2069   if (ctype_isRealPointer (rt))
2070     {
2071       ctype b = ctype_baseArrayPtr (rt);
2072       ctype rb = ctype_realType (b);
2073 
2074       if (ctype_isStructorUnion (rb))
2075 	{
2076 	  uentry tf = uentryList_lookupField (ctype_getFields (rb), f);
2077 
2078 	  if (uentry_isUndefined (tf))
2079 	    {
2080 	      voptgenerror (FLG_TYPE,
2081 			    message ("Modifies list arrow accesses non-existent "
2082 				     "field %s of %t: %q", f, b,
2083 				     sRef_unparse (s)),
2084 			    g_currentloc);
2085 
2086 	      cstring_free (f);
2087 	      return sRef_undefined;
2088 	    }
2089 	  else
2090 	    {
2091 	      if (context_inHeader ())
2092 		{
2093 		  if (ctype_isAbstract (b))
2094 		    {
2095 		      voptgenerror
2096 			(FLG_ABSTRACT,
2097 			 message
2098 			 ("Modifies clause in header file arrow accesses abstract "
2099 			  "type %s (interface modifies clause should not depend "
2100 			  "on or expose type representation): %q",
2101 			  ctype_unparse (b),
2102 			  sRef_unparse (s)),
2103 			 g_currentloc);
2104 		    }
2105 		}
2106 	      else
2107 		{
2108 		  if (ctype_isAbstract (rt))
2109 		    {
2110 		      voptgenerror
2111 			(FLG_ABSTRACT,
2112 			 message
2113 			 ("Modifies clause arrow accesses inaccessible abstract "
2114 			  "type %s (interface modifies clause should not depend "
2115 			  "on or expose type representation): %q",
2116 			  ctype_unparse (rt),
2117 			  sRef_unparse (s)),
2118 			 g_currentloc);
2119 		    }
2120 		}
2121 	    }
2122 
2123 	  cstring_markOwned (f);
2124 	  return (sRef_makeArrow (s, f));
2125 	}
2126       else
2127 	{
2128 	  voptgenerror
2129 	    (FLG_TYPE,
2130 	     message ("Modifies clause arrow accesses pointer to "
2131 		      "non-structure (type %s): %q",
2132 		      ctype_unparse (rt),
2133 		      sRef_unparse (s)),
2134 	     g_currentloc);
2135 	}
2136     }
2137   else
2138     {
2139       voptgenerror
2140 	(FLG_TYPE,
2141 	 message ("Modifies clause arrow accesses non-pointer (type %s): %q",
2142 		  ctype_unparse (rt),
2143 		  sRef_unparse (s)),
2144 	 g_currentloc);
2145     }
2146 
2147   cstring_free (f);
2148   return s;
2149 }
2150 
checkStateClausesId(uentry ue)2151 sRef checkStateClausesId (uentry ue)
2152 {
2153   cstring s = uentry_rawName (ue);
2154 
2155   if (sRef_isFileOrGlobalScope (uentry_getSref (ue)))
2156     {
2157       voptgenerror
2158 	(FLG_COMMENTERROR,
2159 	 message ("Global variable %s used state clause.  (Global variables "
2160 		  "are not recognized in state clauses.  If they are present "
2161 		  "they are ignored. "
2162 		  " If there is "
2163 		  "sufficient interest in support for this, it may be "
2164 		  "added to a future release.  Send mail to "
2165 		  "info@splint.org.)",
2166 		  s),
2167 	 g_currentloc);
2168 
2169       return sRef_undefined;
2170     }
2171   else
2172     {
2173       if (cstring_equalLit (s, "result"))
2174 	{
2175 	  if (optgenerror
2176 	      (FLG_SYNTAX,
2177 	       message ("Special clause list uses %s which is a variable and has special "
2178 			"meaning in a modifies list.  (Special meaning assumed.)", s),
2179 	       g_currentloc))
2180 	    {
2181 	      uentry_showWhereDeclared (ue);
2182 	    }
2183 	}
2184 
2185       return uentry_getSref (ue);
2186     }
2187 }
2188 /*drl:1/19/2001
2189   oops to 1/8/2000
2190   date is wronge ..
2191   don;t know what the real date is...
2192 
2193 */
2194 
2195 /*drl
2196   added 1/8/2000
2197   based on checkSpecClausesId
2198   called by grammar
2199 */
2200 
checkbufferConstraintClausesId(uentry ue)2201 sRef checkbufferConstraintClausesId (uentry ue)
2202 {
2203   sRef sr;
2204   cstring s = uentry_rawName (ue);
2205 
2206   if (cstring_equalLit (s, "result"))
2207     {
2208       if (optgenerror
2209 	  (FLG_SYNTAX,
2210 	   message ("Function clause list uses %s which is a variable and has special "
2211 		    "meaning in a modifies list.  (Special meaning assumed.)", s),
2212 	   g_currentloc))
2213 	{
2214 	  uentry_showWhereDeclared (ue);
2215 	}
2216     }
2217 
2218   sr = uentry_getSref (ue);
2219 
2220   if (sRef_isInvalid (sr))
2221     {
2222       llfatalerrorLoc (cstring_makeLiteral ("Macro defined constants can not be used in function "
2223 					    "constraints unless they are specifed with the constant "
2224 					    "annotation. To use a macro defined constant include an "
2225 					    "annotation of the form /*@constant <type> <name>=<value>@*/ "
2226 					    "somewhere before the function constraint. This restriction "
2227 					    "may be removed in future releases."));
2228     }
2229 
2230   /* saveCopy to used to mitigate danger of accessing freed memory*/
2231   return sRef_saveCopy (sr);
2232 }
2233 
checkModifiesId(uentry ue)2234 void checkModifiesId (uentry ue)
2235 {
2236   cstring s = uentry_rawName (ue);
2237 
2238   if (cstring_equalLit (s, "nothing")
2239       || cstring_equalLit (s, "internalState")
2240       || cstring_equalLit (s, "systemState")
2241       || (cstring_equalLit (s, "fileSystem")))
2242     {
2243       if (optgenerror
2244 	  (FLG_SYNTAX,
2245 	   message ("Modifies list uses %s which is a variable and has special "
2246 		    "meaning in a modifies list.  (Special meaning assumed.)", s),
2247 	   g_currentloc))
2248 	{
2249 	  uentry_showWhereDeclared (ue);
2250 	}
2251     }
2252 }
2253 
fixModifiesId(cstring s)2254 /*@exposed@*/ sRef fixModifiesId (cstring s)
2255 {
2256   sRef ret;
2257   cstring pname = makeParam (s);
2258   uentry ue = usymtab_lookupSafe (pname);
2259 
2260   cstring_free (pname);
2261 
2262   if (cstring_equalLit (s, "nothing"))
2263     {
2264       ret = sRef_makeNothing ();
2265     }
2266   else if (cstring_equalLit (s, "internalState"))
2267     {
2268       ret = sRef_makeInternalState ();
2269     }
2270   else if (cstring_equalLit (s, "fileSystem")
2271 	   || cstring_equalLit (s, "systemState"))
2272     {
2273       ret = sRef_makeSystemState ();
2274     }
2275   else
2276     {
2277       ret = sRef_undefined;
2278     }
2279 
2280   if (sRef_isValid (ret))
2281     {
2282       if (uentry_isValid (ue))
2283 	{
2284 	  voptgenerror
2285 	    (FLG_SYNTAX,
2286 	     message ("Modifies list uses %s which is a parameter and has special "
2287 		      "meaning in a modifies list.  (Special meaning assumed.)", s),
2288 	     g_currentloc);
2289 	}
2290     }
2291   else
2292     {
2293       if (uentry_isValid (ue))
2294 	{
2295 	  ret = uentry_getSref (ue);
2296 	}
2297       else
2298 	{
2299 	  fileloc loc = fileloc_decColumn (g_currentloc, size_toInt (cstring_length (s)));
2300 	  ret = sRef_undefined;
2301 
2302 	  voptgenerror
2303 	    (FLG_UNRECOG,
2304 	     message ("Unrecognized identifier in modifies comment: %s", s),
2305 	     loc);
2306 
2307 	  fileloc_free (loc);
2308 	}
2309     }
2310 
2311   return ret;
2312 }
2313 
fixStateClausesId(cstring s)2314 sRef fixStateClausesId (cstring s)
2315 {
2316   sRef ret;
2317   cstring pname = makeParam (s);
2318   uentry ue = usymtab_lookupSafe (pname);
2319 
2320   cstring_free (pname);
2321 
2322   if (cstring_equalLit (s, "result"))
2323     {
2324       ret = sRef_makeResult (ctype_unknown);
2325     }
2326   else
2327     {
2328       ret = sRef_undefined;
2329     }
2330 
2331   if (sRef_isValid (ret))
2332     {
2333       if (uentry_isValid (ue))
2334 	{
2335 	  voptgenerror
2336 	    (FLG_SYNTAX,
2337 	     message ("Function clause uses %s which is a parameter and has special "
2338 		      "meaning in a function clause.  (Special meaning assumed.)", s),
2339 	     g_currentloc);
2340 	}
2341     }
2342   else
2343     {
2344       if (uentry_isValid (ue))
2345 	{
2346 	  ret = uentry_getSref (ue);
2347 
2348 	  if (sRef_isFileOrGlobalScope (ret))
2349 	    {
2350 	      voptgenerror
2351 		(FLG_SYNTAX,
2352 		 message ("Global variable %s used in function clause.  (Global variables "
2353 			  "are not recognized in function clauses.  If there is "
2354 			  "sufficient interest in support for this, it may be "
2355 			  "added to a future release.  Send mail to "
2356 			  "info@splint.org.)",
2357 			  s),
2358 		 g_currentloc);
2359 
2360 	      ret = sRef_undefined;
2361 	    }
2362 	}
2363       else
2364 	{
2365 
2366 	  /* drl This is the code for structure invariants
2367 
2368 	  It is no yet stable enough to be included in a Splint release.
2369 	  */
2370 
2371 	  /*check that we're in a structure */
2372 #if 0
2373 		  /*@unused@*/	  uentryList ueL;
2374 	  /*@unused@*/ uentry ue2;
2375 	  /*@unused@*/ ctype ct;
2376 #endif
2377 	  fileloc loc = fileloc_decColumn (g_currentloc, size_toInt (cstring_length (s)));
2378 	  ret = sRef_undefined;
2379 # if 0
2380 
2381 	  ct = context_getLastStruct ( ct );
2382 
2383 	  llassert( ctype_isStruct(ct) );
2384 
2385 	  ueL =  ctype_getFields (ct);
2386 
2387 	  ue2 = uentryList_lookupField (ueL, s);
2388 
2389 	  if (!uentry_isUndefined(ue2) )
2390 	    {
2391 	      ret = uentry_getSref(ue2);
2392 
2393 	      DPRINTF((
2394 		       message("Got field in structure in the annotation constraint: %s (or sref: %s)", s, sRef_unparse(ret) )
2395 		       ));
2396 
2397 	      return ret;
2398 	    }
2399 
2400 #endif
2401 
2402 	  voptgenerror
2403 	    (FLG_UNRECOG,
2404 	     message ("Unrecognized identifier in function clause: %s", s),
2405 	     loc);
2406 
2407 	  fileloc_free (loc);
2408 	}
2409     }
2410 
2411   return ret;
2412 }
2413 
modListArrayFetch(sRef s,sRef mexp)2414 sRef modListArrayFetch (/*@exposed@*/ sRef s, /*@unused@*/ sRef mexp)
2415 {
2416   ctype ct = sRef_getType (s);
2417   ctype rt = ctype_realType (ct);
2418 
2419   if (ctype_isAP (rt))
2420     {
2421       if (context_inHeader () && ctype_isAbstract (ct))
2422 	{
2423 	  voptgenerror
2424 	    (FLG_ABSTRACT,
2425 	     message
2426 	     ("Modifies clause in header file indexes abstract "
2427 	      "type %s (interface modifies clause should not depend "
2428 	      "on or expose type representation): %q",
2429 	      ctype_unparse (ct),
2430 	      sRef_unparse (s)),
2431 	     g_currentloc);
2432 	}
2433 
2434       return (sRef_makeAnyArrayFetch (s));
2435     }
2436   else
2437     {
2438       voptgenerror
2439 	(FLG_TYPE,
2440 	 message
2441 	 ("Implementation modifies clause uses array fetch on non-array (type %s): %q",
2442 	  ctype_unparse (ct), sRef_unparse (s)),
2443 	 g_currentloc);
2444       return s;
2445     }
2446 }
2447 
clabstract_prepareFunction(uentry e)2448 static void clabstract_prepareFunction (uentry e)
2449 {
2450   uentry_checkParams (e);
2451   DPRINTF (("After prepare: %s", uentry_unparseFull (e)));
2452 }
2453 
clabstract_checkGlobal(exprNode e)2454 sRef clabstract_checkGlobal (exprNode e)
2455 {
2456   sRef s;
2457   llassert (exprNode_isInitializer (e));
2458 
2459   s = exprNode_getSref (e);
2460   DPRINTF (("Initializer: %s -> %s", exprNode_unparse (e), sRef_unparse (s)));
2461 
2462   exprNode_free (e);
2463   return sRef_copy (s);
2464 }
2465