]> andersk Git - splint.git/blame - src/clabstract.c
Fixed stupid bug in constraintGeneration.c
[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);
a0a162cd 511 DPRINTF (("Set type: %s / %s",
512 uentry_unparse (ue), ctype_unparse (ctype_bool)));
885824d3 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 {
a0a162cd 541 DPRINTF (("Here we are!"));
885824d3 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
575static /*@dependent@*/ uentryList currentParamList;
576
577void setCurrentParams (/*@dependent@*/ uentryList ue)
578{
579 currentParamList = ue;
580}
581
582void 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
592static 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
609extern void enterParamsTemp (void)
610{
611 usymtab_enterScope ();
612 enterFunctionParams (currentParamList);
613}
614
615extern void exitParamsTemp (void)
616{
617 usymtab_quietPlainExitScope ();
618}
619
620static /*@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
675static /*@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
705static 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
720void 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
771void 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
865void
866checkTypeDecl (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
1024uentryList
1025fixUentryList (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
1087uentryList
1088fixUnnamedDecl (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
1106void setStorageClass (storageClassCode sc)
1107{
1108 storageClass = sc;
1109}
1110
1111void
1112setProcessingIterVars (uentry iter)
1113{
1114 ProcessingIterVars = TRUE;
1115 currentIter = iter;
1116 saveIterParamNo = 0;
1117}
1118
1119void
1120setProcessingGlobalsList ()
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
1139static bool ProcessingGlobMods = FALSE;
1140
1141void
1142setProcessingGlobMods ()
1143{
1144 ProcessingGlobMods = TRUE;
1145}
1146
1147void
1148clearProcessingGlobMods ()
1149{
1150 ProcessingGlobMods = FALSE;
1151}
1152
1153bool
1154isProcessingGlobMods ()
1155{
1156 return (ProcessingGlobMods);
1157}
1158
1159static 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
1168void
1169unsetProcessingGlobals ()
1170{
1171 ProcessingGlobals = FALSE;
1172}
1173
1174void
1175setProcessingVars (/*@only@*/ qtype q)
1176{
1177 ProcessingVars = TRUE;
1178 qtype_free (processingType);
1179 processingType = q;
1180}
1181
1182static void
1183setGenericParamList (/*@dependent@*/ uentryList pm)
1184{
1185 ProcessingParams = TRUE;
1186 saveParamList = pm;
1187}
1188
1189void
1190setProcessingTypedef (/*@only@*/ qtype q)
1191{
1192 ProcessingTypedef = TRUE;
1193
1194 qtype_free (processingType);
1195 processingType = q;
1196}
1197
1198void
1199unsetProcessingVars ()
1200{
1201 resetStorageClass ();
1202 ProcessingVars = FALSE;
1203}
1204
1205void
1206doneParams ()
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
1245void
1246checkDoneParams ()
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
1272void
1273unsetProcessingTypedef ()
1274{
1275 ProcessingTypedef = FALSE;
1276}
1277
1278void 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
1291void 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
1327void 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
1591static 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
1612ctype
1613declareUnnamedStruct (/*@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
1634ctype
1635declareUnnamedUnion (/*@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
1656ctype 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);
a0a162cd 1663 DPRINTF (("Declare struct: %s [%d]", ctype_unparse (ct), ct));
885824d3 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
1684ctype 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
1711ctype 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
1726ctype 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
1740ctype
1741handleEnum (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
1755bool processingIterVars (void)
1756{
1757 return ProcessingIterVars;
1758}
1759
1760uentry getCurrentIter (void)
1761{
1762 return currentIter;
1763}
1764
1765static bool flipOldStyle = FALSE;
1766static bool flipNewStyle = TRUE;
1767
1768void setFlipOldStyle () { flipOldStyle = TRUE; }
1769bool isFlipOldStyle () { return flipOldStyle; }
1770bool isNewStyle () { return flipNewStyle; }
1771void 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
1817void
1818doVaDcl ()
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
1940sRef 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
2053sRef 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
2090void 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
2170sRef 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
2236sRef 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.597186 seconds and 5 git commands to generate.