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