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