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