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