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