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