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