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