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