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