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