]> 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
677 e = usymtab_supGlobalEntryReturn (e);
678
679 context_enterFunction (e);
680 enterFunctionParams (params);
681 saveParamList = uentryList_undefined;
682 resetStorageClass ();
683}
684
28bf4b0b 685void clabstract_declareFunction (idDecl tid) /*@globals undef saveFunction; @*/
616915dd 686{
687 uentry ue;
688
689 DPRINTF (("Declare function: %s", idDecl_unparse (tid)));
690
691 if (ProcessingParams)
692 {
693 ue = globalDeclareOldStyleFunction (tid);
694 saveFunction = ue;
695 }
696 else
697 {
698 saveFunction = uentry_undefined;
699
700 if (context_inRealFunction ())
701 {
702 ue = uentry_makeVariableLoc (idDecl_observeId (tid), ctype_unknown);
703
704 llparseerror (message ("Function declared inside function: %q",
705 idDecl_unparse (tid)));
706
707 context_quietExitFunction ();
708 ue = usymtab_supEntryReturn (ue);
709 }
710 else
711 {
712 if (context_inInnerScope ())
713 {
714 llparseerror (message ("Declaration in inner context: %q",
715 idDecl_unparse (tid)));
716
717 sRef_setGlobalScope ();
718 ue = uentry_makeVariableLoc (idDecl_observeId (tid),
719 ctype_unknown);
720 ue = usymtab_supGlobalEntryReturn (ue);
721 sRef_clearGlobalScope ();
722 }
723 else
724 {
28bf4b0b 725 ue = clabstract_globalDeclareFunction (tid);
616915dd 726 }
727 }
728
729 resetGlobals ();
730 }
731
732 resetStorageClass ();
733 idDecl_free (tid);
734}
735
736void declareStaticFunction (idDecl tid) /*@globals undef saveFunction; @*/
737{
738 uentry ue;
739
740 DPRINTF (("Declare static funciton: %s", idDecl_unparse (tid)));
741
742 if (ProcessingParams)
743 {
744 ue = globalDeclareOldStyleFunction (tid);
745 saveFunction = ue;
746 }
747 else
748 {
749 saveFunction = uentry_undefined;
750
751 if (context_inRealFunction ())
752 {
753 ue = uentry_makeVariableLoc (idDecl_observeId (tid), ctype_unknown);
754
755 llparseerror (message ("Function declared inside function: %q",
756 idDecl_unparse (tid)));
757
758 context_quietExitFunction ();
759 ue = usymtab_supEntryReturn (ue);
760 }
761 else
762 {
763 if (context_inInnerScope ())
764 {
765 llparseerror (message ("Declaration in inner context: %q",
766 idDecl_unparse (tid)));
767
768 sRef_setGlobalScope ();
769 ue = uentry_makeVariableLoc (idDecl_observeId (tid),
770 ctype_unknown);
771 ue = usymtab_supGlobalEntryReturn (ue);
772 sRef_clearGlobalScope ();
773 }
774 else
775 {
776 ctype deftype = idDecl_getCtype (tid);
777 ctype rettype;
778
779 if (ctype_isFunction (deftype))
780 {
28bf4b0b 781 rettype = ctype_getReturnType (deftype);
616915dd 782 }
783 else
784 {
785 rettype = ctype_unknown;
786 }
787
788 /*
789 ** check has been moved here...
790 */
791
792 if (ctype_isFunction (idDecl_getCtype (tid)))
793 {
794 ue = uentry_makeIdFunction (tid);
795 reflectSpecialCode (ue);
796 reflectArgsUsed (ue);
797 }
798 else
799 {
800 llparseerror (message ("Inconsistent function declaration: %q",
801 idDecl_unparse (tid)));
802
803 tid = idDecl_replaceCtype
804 (tid, ctype_makeFunction (ctype_unknown, uentryList_undefined));
805 ue = uentry_makeIdFunction (tid);
806 }
807
808 reflectStorageClass (ue);
809 uentry_setStatic (ue);
810
811 uentry_checkParams (ue);
616915dd 812
813 DPRINTF (("Sub global entry: %s", uentry_unparse (ue)));
814 ue = usymtab_supGlobalEntryReturn (ue);
815
816 context_enterFunction (ue);
817 enterFunctionParams (uentry_getParams (ue));
818 resetStorageClass ();
819 }
820 }
821
822 resetGlobals ();
823 }
824
825 resetStorageClass ();
826 idDecl_free (tid);
827}
828
829void
830checkTypeDecl (uentry e, ctype rep)
831{
832 cstring n = uentry_getName (e);
833
28bf4b0b 834 DPRINTF (("Check type decl: %s", uentry_unparseFull (e)));
616915dd 835
836 if (cstring_equal (context_getBoolName (), n))
837 {
838 ctype rrep = ctype_realType (rep);
839
840 /*
841 ** for abstract enum types, we need to fix the enum members:
842 ** they should have the abstract type, not the rep type.
843 */
844
845 if (ctype_isEnum (ctype_realType (rrep)))
846 {
847 enumNameList el = ctype_elist (rrep);
848
849 enumNameList_elements (el, ye)
850 {
851 if (usymtab_existsGlob (ye))
852 {
853 uentry ue = usymtab_lookupSafe (ye);
854 uentry_setType (ue, ctype_bool);
855 }
856
857 if (cstring_equal (context_getTrueName (), ye)
858 || cstring_equal (context_getFalseName (), ye))
859 {
860 ;
861 }
862 else
863 {
864 vgenhinterror
865 (FLG_SYNTAX,
866 message ("Member of boolean enumerated type definition "
867 "does not match name set to represent TRUE "
868 "or FALSE: %s",
869 ye),
870 message ("Use -boolfalse and -booltrue to set the "
871 "name of false and true boolean values."),
872 uentry_whereDefined (e));
873 }
874 } end_enumNameList_elements;
875 }
876 }
877
878 if (usymtab_exists (n))
879 {
880 usymId llm = usymtab_getId (n);
881 uentry le = usymtab_getTypeEntry (llm);
882
883 uentry_setDeclared (e, g_currentloc);
884 uentry_setSref (e, sRef_makeGlobal (llm, uentry_getType (le)));
885
886 DPRINTF (("Here we are: %s / %s",
887 n, context_getBoolName ()));
888
889 if (uentry_isAbstractDatatype (le))
890 {
891 ctype rrep = ctype_realType (rep);
892
28bf4b0b 893 DPRINTF (("Abstract type: %s", uentry_unparseFull (le)));
894
616915dd 895 /*
896 ** for abstract enum types, we need to fix the enum members:
897 ** they should have the abstract type, not the rep type.
898 */
899
900 if (ctype_isEnum (ctype_realType (rrep)))
901 {
902 ctype at = uentry_getAbstractType (le);
903 enumNameList el = ctype_elist (rrep);
904
905 enumNameList_elements (el, ye)
906 {
907 if (usymtab_existsGlob (ye))
908 {
909 uentry ue = usymtab_lookupSafe (ye);
910
911 llassert (uentry_isEitherConstant (ue));
912 llassertprint (ctype_match (uentry_getType (ue), rrep),
913 ("Bad enum: %s / %s",
914 uentry_unparse (ue),
915 ctype_unparse (rrep)));
916
917 uentry_setType (ue, at);
918 }
919 } end_enumNameList_elements;
920 }
921
922 if (uentry_isMutableDatatype (le))
923 {
924 /* maybe more complicated if abstract and immutable ? */
925
926 if (!ctype_isRealPointer (rep) && !ctype_isRealAbstract (rep))
927 {
928 voptgenerror
929 (FLG_MUTREP,
930 message ("Mutable abstract type %s declared without pointer "
931 "indirection: %s (violates assignment semantics)",
932 n, ctype_unparse (rep)),
933 uentry_whereDefined (e));
934
935 uentry_setMutable (e);
936 }
937 }
938 }
939 }
940 else
941 {
942 fileloc fl = uentry_whereDeclared (e);
943
944 if (context_getFlag (FLG_LIKELYBOOL)
945 && !context_getFlag (FLG_BOOLINT))
946 {
947 if ((cstring_equalLit (n, "BOOL")
948 || cstring_equalLit (n, "Bool")
949 || cstring_equalLit (n, "bool")
950 || cstring_equalLit (n, "boolean")
951 || cstring_equalLit (n, "Boolean")
952 || cstring_equalLit (n, "BOOLEAN"))
953 && !(cstring_equal (n, context_getBoolName ())))
954 {
955 if (context_setBoolName ()) {
956 voptgenerror
957 (FLG_LIKELYBOOL,
958 message ("Type %s is probably meant as a boolean type, but does "
959 "not match the boolean type name \"%s\".",
960 n,
961 context_getBoolName ()),
962 fl);
963 } else
964 voptgenerror
965 (FLG_LIKELYBOOL,
966 message ("Type %s is probably meant as a boolean type, "
967 "but the boolean type name is not set. "
968 "Use -booltype %s to set it.",
969 n,
970 n),
971 fl);
972 }
973 }
974
975 if (!uentry_isStatic (e)
976 && !ctype_isFunction (uentry_getType (e))
977 && !fileloc_isLib (fl)
978 && !fileloc_isImport (fl)
979 && fileloc_isHeader (fl))
980 {
981 voptgenerror (FLG_EXPORTTYPE,
982 message ("Type exported, but not specified: %s\n", n),
983 fl);
984 }
985 }
986
987 cstring_free (n);
988}
989
990uentryList
991fixUentryList (idDeclList tl, qtype q)
992{
993 uentryList f = uentryList_new ();
994
995 idDeclList_elements (tl, i)
996 {
997 if (idDecl_isDefined (i))
998 {
999 uentry ue;
1000 uentry old;
1001 ctype rt;
1002
1003 (void) idDecl_fixBase (i, q);
1004
1005 /*
1006 ** implicit annotations
1007 */
1008
1009 (void) fixStructDecl (i);
1010
1011 ue = uentry_makeIdVariable (i);
1012 rt = ctype_realType (uentry_getType (ue));
1013
1014 /*
1015 ** where is this here???
1016
1017 if (ctype_isArray (rt) || ctype_isSU (rt))
1018 {
1019 sRef_setAllocated (uentry_getSref (ue), uentry_whereDefined (ue));
1020 }
1021
1022 **
1023 */
1024
1025 if (uentry_isValid (old = uentryList_lookupField (f, uentry_rawName (ue))))
1026 {
1027 if (optgenerror (FLG_SYNTAX,
1028 message ("Field name reused: %s", uentry_rawName (ue)),
1029 uentry_whereDefined (ue)))
1030 {
1031 llgenmsg (message ("Previous use of %s", uentry_rawName (ue)),
1032 uentry_whereDefined (old));
1033 }
1034 }
1035
1036 f = uentryList_add (f, ue);
1037 }
1038 } end_idDeclList_elements;
1039
1040 idDeclList_free (tl);
1041 return (f);
1042}
1043
1044/*
1045** This is a hack to support unnamed struct/union fields as done by
1046** Microsoft VC++. It is not supported by the ANSI standard.
1047**
1048** The inner fields are added to the outer structure. This is meaningful
1049** for nesting structs inside unions, but lclint does no related
1050** checking.
1051*/
1052
1053uentryList
1054fixUnnamedDecl (qtype q)
1055{
1056 ctype ct = ctype_realType (qtype_getType (q));
1057
1058 if (ctype_isStruct (ct) || ctype_isUnion (ct))
1059 {
1060 uentryList res = ctype_getFields (ct);
1061
1062 return (uentryList_copy (res));
1063 }
1064 else
1065 {
1066 BADBRANCHCONT;
1067 }
1068
1069 return uentryList_undefined;
1070}
1071
1072void setStorageClass (storageClassCode sc)
1073{
1074 storageClass = sc;
1075}
1076
1077void
1078setProcessingIterVars (uentry iter)
1079{
1080 ProcessingIterVars = TRUE;
1081 currentIter = iter;
1082 saveIterParamNo = 0;
1083}
1084
1085void
1086setProcessingGlobalsList ()
1087{
1088 ProcessingGlobals = TRUE;
616915dd 1089 fcnNoGlobals = FALSE;
1090}
1091
1092static bool ProcessingGlobMods = FALSE;
1093
1094void
1095setProcessingGlobMods ()
1096{
1097 ProcessingGlobMods = TRUE;
1098}
1099
1100void
1101clearProcessingGlobMods ()
1102{
1103 ProcessingGlobMods = FALSE;
1104}
1105
1106bool
1107isProcessingGlobMods ()
1108{
1109 return (ProcessingGlobMods);
1110}
1111
1112static void resetGlobals (void)
1113{
1114 ProcessingGlobals = FALSE;
616915dd 1115 fcnNoGlobals = FALSE;
1116}
1117
1118void
1119unsetProcessingGlobals ()
1120{
1121 ProcessingGlobals = FALSE;
1122}
1123
1124void
1125setProcessingVars (/*@only@*/ qtype q)
1126{
1127 ProcessingVars = TRUE;
1128 qtype_free (processingType);
1129 processingType = q;
1130}
1131
1132static void
1133setGenericParamList (/*@dependent@*/ uentryList pm)
1134{
1135 ProcessingParams = TRUE;
1136 saveParamList = pm;
1137}
1138
1139void
1140setProcessingTypedef (/*@only@*/ qtype q)
1141{
1142 ProcessingTypedef = TRUE;
1143
1144 qtype_free (processingType);
1145 processingType = q;
1146}
1147
1148void
1149unsetProcessingVars ()
1150{
1151 resetStorageClass ();
1152 ProcessingVars = FALSE;
1153}
1154
1155void
1156doneParams ()
1157{
1158 if (ProcessingParams)
1159 {
1160 if (uentry_isInvalid (saveFunction))
1161 {
1162 llbuglit ("unsetProcessingVars: no saved function\n");
616915dd 1163 }
1164 else
1165 {
28bf4b0b 1166 ctype ct = ctype_getReturnType (uentry_getType (saveFunction));
616915dd 1167 uentryList params = uentryList_copy (saveParamList);
1168 ctype ct2 = ctype_makeFunction (ct, params);
1169
1170 uentry_setType (saveFunction, ct2);
1171 ProcessingParams = FALSE;
1172
616915dd 1173 oldStyleDeclareFunction (saveFunction);
1174 saveFunction = uentry_undefined;
1175 resetGlobals ();
1176 }
1177 }
1178 else
1179 {
1180 /*
1181 ** If the paramlist used a type name, we could be here.
1182 */
1183
1184 llfatalerror (message ("%q: Old-style function parameter list uses a "
1185 "type name.", fileloc_unparse (g_currentloc)));
1186 }
1187}
1188
1189void
1190checkDoneParams ()
1191{
1192 if (uentry_isValid (saveFunction))
1193 {
1194 /*
1195 ** old style declaration
1196 */
1197
28bf4b0b 1198 ctype ct = ctype_getReturnType (uentry_getType (saveFunction));
616915dd 1199 ctype ct2;
1200
1201 uentryList_elements (saveParamList, current)
1202 {
1203 uentry_setType (current, ctype_int); /* all params are ints */
1204 } end_uentryList_elements;
1205
1206 ct2 = ctype_makeParamsFunction (ct, uentryList_copy (saveParamList));
1207
1208 uentry_setType (saveFunction, ct2);
1209 ProcessingParams = FALSE;
1210
1211 oldStyleDeclareFunction (saveFunction);
1212 saveFunction = uentry_undefined;
1213 }
1214}
1215
1216void
1217unsetProcessingTypedef ()
1218{
1219 ProcessingTypedef = FALSE;
1220}
1221
1222void checkConstant (qtype t, idDecl id)
1223{
1224 uentry e;
1225
1226 id = idDecl_fixBase (id, t);
1227 e = uentry_makeIdConstant (id);
1228
1229 reflectStorageClass (e);
1230 resetStorageClass ();
1231
1232 usymtab_supGlobalEntry (e);
1233}
1234
1235void checkValueConstant (qtype t, idDecl id, exprNode e)
1236{
1237 uentry ue;
1238
1239 id = idDecl_fixBase (id, t);
1240 ue = uentry_makeIdConstant (id);
1241 reflectStorageClass (ue);
1242 resetStorageClass ();
1243
1244 if (exprNode_isDefined (e))
1245 {
1246 if (!exprNode_matchType (uentry_getType (ue), e))
1247 {
1248 (void) gentypeerror
1249 (exprNode_getType (e), e,
1250 uentry_getType (ue), exprNode_undefined,
1251 message ("Constant %q initialized to type %t, expects %t: %s",
1252 uentry_getName (ue),
1253 exprNode_getType (e),
1254 uentry_getType (ue),
1255 exprNode_unparse (e)),
1256 exprNode_loc (e));
1257 }
1258 else
1259 {
1260 if (exprNode_hasValue (e))
1261 {
1262 uentry_mergeConstantValue (ue, multiVal_copy (exprNode_getValue (e)));
1263 }
1264 }
1265 }
1266
1267 usymtab_supGlobalEntry (ue);
1268}
1269
616915dd 1270void processNamedDecl (idDecl t)
1271{
1272 if (qtype_isUndefined (processingType))
1273 {
1274 llparseerror (message ("No type before declaration name: %q", idDecl_unparse (t)));
1275
1276 processingType = qtype_create (ctype_unknown);
1277 }
1278
1279 t = idDecl_fixBase (t, processingType);
1280
1281 DPRINTF (("Declare: %s", idDecl_unparse (t)));
1282
1283 if (ProcessingGlobals)
1284 {
1285 cstring id = idDecl_getName (t);
1286 uentry ue = usymtab_lookupSafe (id);
28bf4b0b 1287
616915dd 1288 if (!uentry_isValid (ue))
1289 {
1290 llerror (FLG_UNRECOG,
1291 message ("Variable used in globals list is undeclared: %s", id));
1292 }
1293 else
1294 {
1295 if (!ctype_match (uentry_getType (ue), idDecl_getCtype (t)))
1296 {
1297 voptgenerror
1298 (FLG_INCONDEFS,
1299 message ("Variable %s used in globals list declared %s, "
1300 "but listed as %s",
1301 id, ctype_unparse (uentry_getType (ue)),
1302 ctype_unparse (idDecl_getCtype (t))),
1303 g_currentloc);
1304 }
1305 else
1306 {
1307 sRef sr = sRef_copy (uentry_getSref (ue));
616915dd 1308 reflectGlobalQualifiers (sr, idDecl_getQuals (t));
616915dd 1309 }
1310 }
1311 }
1312 else if (ProcessingVars)
1313 {
1314 uentry e;
1315 ctype ct;
1316
1317 ct = ctype_realType (idDecl_getCtype (t));
1318
1319 if (ProcessingParams)
1320 {
1321 cstring id = idDecl_getName (t);
1322 int paramno = uentryList_lookupRealName (saveParamList, id);
1323
1324 if (paramno >= 0)
1325 {
1326 uentry cparam = uentryList_getN (saveParamList, paramno);
1327
1328 uentry_setType (cparam, idDecl_getCtype (t));
1329 uentry_reflectQualifiers (cparam, idDecl_getQuals (t));
1330 uentry_setDeclaredOnly (cparam, context_getSaveLocation ());
1331 }
1332 else
1333 {
1334 llfatalerrorLoc
1335 (message ("Old style declaration uses unlisted parameter: %s",
1336 id));
1337 }
1338 }
1339 else
1340 {
1341 fileloc loc;
1342
1343 if (context_inIterDef ())
1344 {
1345 cstring pname = makeParam (idDecl_observeId (t));
1346 uentry p = usymtab_lookupSafe (pname);
1347
1348 cstring_free (pname);
1349
1350 if (uentry_isYield (p))
28bf4b0b 1351 {
1352 e = uentry_makeParam (t, sRef_getParam (uentry_getSref (p)));
1353 uentry_checkYieldParam (p, e);
1354 usymtab_supEntrySref (e);
1355 return;
1356 }
616915dd 1357 }
28bf4b0b 1358
616915dd 1359 if ((hasSpecialCode () || argsUsed)
1360 && ctype_isFunction (idDecl_getCtype (t)))
28bf4b0b 1361 {
616915dd 1362 e = uentry_makeIdFunction (t);
1363 reflectSpecialCode (e);
1364 reflectArgsUsed (e);
28bf4b0b 1365 }
616915dd 1366 else
28bf4b0b 1367 {
1368 e = uentry_makeIdVariable (t);
1369 }
1370
616915dd 1371 loc = uentry_whereDeclared (e);
28bf4b0b 1372
616915dd 1373 /*
28bf4b0b 1374 if (context_inGlobalScope ())
616915dd 1375 {
1376 uentry_checkParams was here!
1377 }
28bf4b0b 1378 */
1379
616915dd 1380 if (ctype_isFunction (uentry_getType (e)))
1381 {
28bf4b0b 1382 clabstract_prepareFunction (e);
616915dd 1383 }
1384
28bf4b0b 1385 DPRINTF (("Superceding... %s", uentry_unparseFull (e)));
616915dd 1386 e = usymtab_supEntrySrefReturn (e);
28bf4b0b 1387 DPRINTF (("After superceding... %s", uentry_unparseFull (e)));
1388
616915dd 1389 if (uentry_isExtern (e) && !context_inGlobalScope ())
1390 {
1391 voptgenerror
1392 (FLG_NESTEDEXTERN,
1393 message ("Declaration using extern inside function scope: %q",
1394 uentry_unparse (e)),
1395 g_currentloc);
1396
1397 uentry_setDefined (e, fileloc_getExternal ());
1398 sRef_setDefined (uentry_getSref (e), fileloc_getExternal ());
1399 }
28bf4b0b 1400
616915dd 1401 if (uentry_isFunction (e))
1402 {
28bf4b0b 1403 if (!context_inXHFile ())
1404 {
1405 checkParamNames (e);
1406 }
616915dd 1407 }
28bf4b0b 1408
1409 if (uentry_isVar (e) && uentry_isCheckedUnknown (e))
616915dd 1410 {
1411 sRef sr = uentry_getSref (e);
28bf4b0b 1412
616915dd 1413 if (sRef_isLocalVar (sr))
1414 {
1415 if (context_getFlag (FLG_IMPCHECKMODINTERNALS))
1416 {
1417 uentry_setCheckMod (e);
1418 }
1419 else
1420 {
1421 uentry_setUnchecked (e);
1422 }
1423 }
1424 else if (sRef_isFileStatic (sr))
1425 {
1426 if (context_getFlag (FLG_IMPCHECKEDSTRICTSTATICS))
1427 {
1428 uentry_setCheckedStrict (e);
1429 }
1430 else if (context_getFlag (FLG_IMPCHECKEDSTATICS))
1431 {
1432 uentry_setChecked (e);
1433 }
1434 else if (context_getFlag (FLG_IMPCHECKMODSTATICS))
1435 {
1436 uentry_setCheckMod (e);
1437 }
1438 else
1439 {
1440 ;
1441 }
1442 }
1443 else /* real global */
1444 {
1445 llassert (sRef_isRealGlobal (sr));
28bf4b0b 1446
616915dd 1447 if (context_getFlag (FLG_IMPCHECKEDSTRICTGLOBALS))
1448 {
1449 uentry_setCheckedStrict (e);
1450 }
1451 else if (context_getFlag (FLG_IMPCHECKEDGLOBALS))
1452 {
1453 uentry_setChecked (e);
1454 }
1455 else if (context_getFlag (FLG_IMPCHECKMODGLOBALS))
1456 {
1457 uentry_setCheckMod (e);
1458 }
1459 else
1460 {
1461 ;
1462 }
1463 }
1464 }
1465 }
1466 }
1467 else if (ProcessingTypedef)
1468 {
1469 ctype ct = idDecl_getCtype (t);
1470 uentry e;
28bf4b0b 1471
616915dd 1472 DPRINTF (("Processing typedef: %s", ctype_unparse (ct)));
1473
1474 e = uentry_makeIdDatatype (t);
1475
1476 if (cstring_equal (idDecl_getName (t), context_getBoolName ())) {
1477 ctype rt = ctype_realType (ct);
1478
1479 if (ctype_isEnum (rt)) {
1480 ;
1481 } else {
1482 if (!(ctype_isInt (rt)
1483 || ctype_isUnknown (rt)
1484 || ctype_isChar (rt))) {
1485 (void) llgenerror
1486 (FLG_BOOLTYPE,
1487 message ("Boolean type %s defined using non-standard type %s (integral, char or enum type expected)",
1488 context_getBoolName (),
1489 ctype_unparse (ct)),
1490 uentry_whereLast (e));
1491 }
1492
1493 ct = ctype_bool;
1494 uentry_setType (e, ct);
1495 }
1496 }
1497
1498 reflectStorageClass (e);
1499 checkTypeDecl (e, ct);
1500
1501 e = usymtab_supReturnTypeEntry (e);
616915dd 1502 }
1503 else
1504 {
1505 llparseerror (message ("Suspect missing struct or union keyword: %q",
1506 idDecl_unparse (t)));
1507 }
1508
1509 }
1510
1511/*
1512** moved from grammar
1513*/
1514
1515static idDecl fixStructDecl (/*@returned@*/ idDecl d)
1516{
1517 if (ctype_isVisiblySharable (idDecl_getCtype (d))
1518 && context_getFlag (FLG_STRUCTIMPONLY))
1519 {
1520 if (!qualList_hasAliasQualifier (idDecl_getQuals (d)))
1521 {
1522 if (qualList_hasExposureQualifier (idDecl_getQuals (d)))
1523 {
1524 idDecl_addQual (d, qual_createDependent ());
1525 }
1526 else
1527 {
1528 idDecl_addQual (d, qual_createImpOnly ());
1529 }
1530 }
1531 }
1532
1533 return d;
1534}
1535
1536ctype
1537declareUnnamedStruct (/*@only@*/ uentryList f)
1538{
28bf4b0b 1539 DPRINTF (("Unnamed struct: %s", uentryList_unparse (f)));
1540
616915dd 1541 if (context_maybeSet (FLG_NUMSTRUCTFIELDS))
1542 {
1543 int num = uentryList_size (f);
1544 int max = context_getValue (FLG_NUMSTRUCTFIELDS);
1545
1546 if (num > max)
1547 {
1548 voptgenerror
1549 (FLG_NUMSTRUCTFIELDS,
1550 message ("Structure declared with %d fields "
1551 "(limit is set to %d)",
1552 num, max),
1553 g_currentloc);
1554 }
1555 }
1556
1557 return (ctype_createUnnamedStruct (f));
1558}
1559
1560ctype
1561declareUnnamedUnion (/*@only@*/ uentryList f)
1562{
1563 if (context_maybeSet (FLG_NUMSTRUCTFIELDS))
1564 {
1565 int num = uentryList_size (f);
1566 int max = context_getValue (FLG_NUMSTRUCTFIELDS);
1567
1568 if (num > max)
1569 {
1570 voptgenerror
1571 (FLG_NUMSTRUCTFIELDS,
1572 message ("Union declared with %d fields "
1573 "(limit is set to %d)",
1574 num, max),
1575 g_currentloc);
1576 }
1577 }
1578
1579 return (ctype_createUnnamedUnion (f));
1580}
1581
1582ctype declareStruct (cstring id, /*@only@*/ uentryList f)
1583{
1584 ctype ct;
1585 uentry ue;
1586 int num = uentryList_size (f);
1587
28bf4b0b 1588 DPRINTF (("Declare struct: %s / %s", id, uentryList_unparse (f)));
1589
616915dd 1590 ct = ctype_createStruct (cstring_copy (id), f);
28bf4b0b 1591
1592 DPRINTF (("Ctype: %s", ctype_unparse (ct)));
1593
616915dd 1594 ue = uentry_makeStructTagLoc (id, ct);
1595
28bf4b0b 1596 DPRINTF (("ue: %s", uentry_unparseFull (ue)));
1597
616915dd 1598 if (context_maybeSet (FLG_NUMSTRUCTFIELDS))
1599 {
1600 int max = context_getValue (FLG_NUMSTRUCTFIELDS);
1601
1602 if (num > max)
1603 {
1604 voptgenerror
1605 (FLG_NUMSTRUCTFIELDS,
1606 message ("Structure %q declared with %d fields "
1607 "(limit is set to %d)",
1608 uentry_getName (ue), num, max),
1609 uentry_whereLast (ue));
1610 }
1611 }
1612
1613 return (usymtab_supTypeEntry (ue));
1614}
1615
1616ctype declareUnion (cstring id, uentryList f)
1617{
1618 ctype ct;
1619 uentry ue;
1620 int num = uentryList_size (f);
1621
1622 ct = ctype_createUnion (cstring_copy (id), f);
1623 ue = uentry_makeUnionTagLoc (id, ct);
1624
1625 if (context_maybeSet (FLG_NUMSTRUCTFIELDS))
1626 {
1627 int max = context_getValue (FLG_NUMSTRUCTFIELDS);
1628
1629 if (num > max)
1630 {
1631 voptgenerror
1632 (FLG_NUMSTRUCTFIELDS,
1633 message ("Union %q declared with %d fields "
1634 "(limit is set to %d)",
1635 uentry_getName (ue), num, max),
1636 uentry_whereLast (ue));
1637 }
1638 }
1639
1640 return (usymtab_supTypeEntry (ue));
1641}
1642
1643ctype handleStruct (/*@only@*/ cstring id)
1644{
1645 if (usymtab_existsStructTag (id))
1646 {
1647 ctype ct = uentry_getAbstractType (usymtab_lookupStructTag (id));
1648
1649 cstring_free (id);
1650 return ct;
1651 }
1652 else
1653 {
1654 return (ctype_createForwardStruct (id));
1655 }
1656}
1657
1658ctype handleUnion (/*@only@*/ cstring id)
1659{
1660 if (usymtab_existsUnionTag (id))
1661 {
1662 ctype ret = uentry_getAbstractType (usymtab_lookupUnionTag (id));
1663 cstring_free (id);
1664 return (ret);
1665 }
1666 else
1667 {
1668 return (ctype_createForwardUnion (id));
1669 }
1670}
1671
1672ctype
1673handleEnum (cstring id)
1674{
1675 if (usymtab_existsEnumTag (id))
1676 {
1677 ctype ret = uentry_getAbstractType (usymtab_lookupEnumTag (id));
1678 cstring_free (id);
1679 return ret;
1680 }
1681 else
1682 {
1683 return (declareEnum (id, enumNameList_new ()));
1684 }
1685}
1686
1687bool processingIterVars (void)
1688{
1689 return ProcessingIterVars;
1690}
1691
1692uentry getCurrentIter (void)
1693{
1694 return currentIter;
1695}
1696
1697static bool flipOldStyle = FALSE;
1698static bool flipNewStyle = TRUE;
1699
1700void setFlipOldStyle () { flipOldStyle = TRUE; }
1701bool isFlipOldStyle () { return flipOldStyle; }
1702bool isNewStyle () { return flipNewStyle; }
1703void setNewStyle () { flipNewStyle = TRUE; }
1704
1705/*@dependent@*/ uentryList handleParamIdList (/*@dependent@*/ uentryList params)
1706{
1707 int paramno = 0;
1708
1709 /*
1710 ** this is a really YUCKY hack to handle old style
1711 ** declarations.
1712 */
1713
1714 voptgenerror (FLG_OLDSTYLE,
1715 cstring_makeLiteral ("Old style function declaration"),
1716 g_currentloc);
1717
1718 uentryList_elements (params, current)
1719 {
1720 uentry_setParam (current);
1721 uentry_setSref (current, sRef_makeParam (paramno, ctype_unknown));
1722 paramno++;
1723 } end_uentryList_elements;
1724
1725 setGenericParamList (params);
1726 g_expectingTypeName = TRUE;
1727
1728 return params;
1729}
1730
1731/*@dependent@*/ uentryList handleParamTypeList (/*@returned@*/ uentryList params)
1732{
1733 if (flipOldStyle)
1734 {
1735 uentryList_fixMissingNames (params);
1736
1737 voptgenerror (FLG_OLDSTYLE,
1738 cstring_makeLiteral ("Old style function declaration."),
1739 g_currentloc);
1740
1741 setGenericParamList (params);
1742 flipOldStyle = FALSE;
1743 g_expectingTypeName = TRUE;
1744 }
1745
1746 return (params);
1747}
1748
1749void
1750doVaDcl ()
1751{
1752 ctype c = ctype_unknown;
1753 cstring id = cstring_makeLiteral ("va_alist");
1754 uentry e;
1755
1756 if (ProcessingParams)
1757 {
1758 int i = uentryList_lookupRealName (saveParamList, id);
1759
1760 if (i >= 0)
1761 {
1762 e = uentry_makeVariableSrefParam (id, c, sRef_makeParam (i, c));
1763 }
1764 else
1765 {
1766 e = uentry_undefined; /* suppress gcc message */
1767 llfatalerrorLoc (cstring_makeLiteral ("va_dcl used without va_alist"));
1768 }
1769 }
1770 else
1771 {
1772 llerror (FLG_SYNTAX, cstring_makeLiteral ("va_dcl used outside of function declaration"));
1773 e = uentry_makeVariableLoc (id, c);
1774 }
1775
1776 cstring_free (id);
1777 uentry_setUsed (e, g_currentloc);
1778 usymtab_supEntrySref (e);
1779}
1780
28bf4b0b 1781/*@exposed@*/ sRef modListPointer (/*@exposed@*/ sRef s)
616915dd 1782{
1783 ctype ct = sRef_getType (s);
1784 ctype rt = ctype_realType (ct);
1785
1786 if (ctype_isAP (rt))
1787 {
1788 if (context_inHeader () && ctype_isAbstract (ct))
1789 {
1790 voptgenerror
1791 (FLG_ABSTRACT,
1792 message
1793 ("Modifies clause in header file dereferences abstract "
1794 "type %s (interface modifies clause should not depend "
1795 "on or expose type representation): %q",
1796 ctype_unparse (ct),
1797 sRef_unparse (s)),
1798 g_currentloc);
1799 }
1800
1801 return (sRef_constructPointer (s));
1802 }
1803 else
1804 {
1805 if (ctype_isKnown (rt))
1806 {
1807 voptgenerror
1808 (FLG_TYPE,
1809 message ("Implementation modifies clause dereferences non-pointer (type %s): %q",
1810 ctype_unparse (rt),
1811 sRef_unparse (s)),
1812 g_currentloc);
1813 }
1814
1815 return s;
1816 }
1817}
1818
1819/*@exposed@*/ sRef modListFieldAccess (sRef s, cstring f)
1820{
1821 ctype ct = sRef_getType (s);
1822 ctype rt = ctype_realType (ct);
1823
1824 if (ctype_isStructorUnion (rt))
1825 {
1826 uentry tf = uentryList_lookupField (ctype_getFields (rt), f);
1827
1828 if (uentry_isUndefined (tf))
1829 {
1830 voptgenerror (FLG_TYPE,
1831 message ("Modifies list accesses non-existent "
1832 "field %s of %t: %q", f, ct,
1833 sRef_unparse (s)),
1834 g_currentloc);
1835
1836 cstring_free (f);
1837 return sRef_undefined;
1838 }
1839 else
1840 {
1841 if (ctype_isAbstract (ct) && context_inHeader ())
1842 {
1843 voptgenerror
1844 (FLG_ABSTRACT,
1845 message
1846 ("Modifies clause in header file accesses abstract "
1847 "type %s (interface modifies clause should not depend "
1848 "on or expose type representation): %q",
1849 ctype_unparse (ct),
1850 sRef_unparse (s)),
1851 g_currentloc);
1852 }
1853 }
1854
1855 cstring_markOwned (f);
1856 return (sRef_makeField (s, f));
1857 }
1858 else
1859 {
1860 voptgenerror
1861 (FLG_TYPE,
1862 message ("Modifies clause dereferences non-pointer (type %s): %q",
1863 ctype_unparse (rt),
1864 sRef_unparse (s)),
1865 g_currentloc);
1866
1867 cstring_free (f);
1868 return s;
1869 }
1870}
1871
28bf4b0b 1872/*@dependent@*/ sRef clabstract_unrecognizedGlobal (cstring s)
616915dd 1873{
1874 if (cstring_equalLit (s, "nothing"))
1875 {
1876 return sRef_makeNothing ();
1877 }
1878 else if (cstring_equalLit (s, "internalState"))
1879 {
1880 return sRef_makeInternalState ();
1881 }
1882 else if (cstring_equalLit (s, "fileSystem")
1883 || cstring_equalLit (s, "systemState"))
1884 {
1885 return sRef_makeSystemState ();
1886 }
1887 else
1888 {
1889 voptgenerror
1890 (FLG_UNRECOG,
1891 message ("Unrecognized identifier in globals list: %s", s),
1892 g_currentloc);
1893
1894 return sRef_undefined;
1895 }
1896}
1897
1898/*@exposed@*/ sRef modListArrowAccess (sRef s, cstring f)
1899{
1900 ctype ct = sRef_getType (s);
1901 ctype rt = ctype_realType (ct);
1902
1903 if (ctype_isRealPointer (rt))
1904 {
1905 ctype b = ctype_baseArrayPtr (rt);
1906 ctype rb = ctype_realType (b);
1907
1908 if (ctype_isStructorUnion (rb))
1909 {
1910 uentry tf = uentryList_lookupField (ctype_getFields (rb), f);
1911
1912 if (uentry_isUndefined (tf))
1913 {
1914 voptgenerror (FLG_TYPE,
1915 message ("Modifies list arrow accesses non-existent "
1916 "field %s of %t: %q", f, b,
1917 sRef_unparse (s)),
1918 g_currentloc);
1919
1920 cstring_free (f);
1921 return sRef_undefined;
1922 }
1923 else
1924 {
1925 if (context_inHeader ())
1926 {
1927 if (ctype_isAbstract (b))
1928 {
1929 voptgenerror
1930 (FLG_ABSTRACT,
1931 message
1932 ("Modifies clause in header file arrow accesses abstract "
1933 "type %s (interface modifies clause should not depend "
1934 "on or expose type representation): %q",
1935 ctype_unparse (b),
1936 sRef_unparse (s)),
1937 g_currentloc);
1938 }
1939 }
1940 else
1941 {
1942 if (ctype_isAbstract (ct))
1943 {
1944 voptgenerror
1945 (FLG_ABSTRACT,
1946 message
1947 ("Modifies clause in header file arrow accesses abstract "
1948 "type %s (interface modifies clause should not depend "
1949 "on or expose type representation): %q",
1950 ctype_unparse (ct),
1951 sRef_unparse (s)),
1952 g_currentloc);
1953 }
1954 }
1955 }
1956
1957 cstring_markOwned (f);
1958 return (sRef_makeArrow (s, f));
1959 }
1960 else
1961 {
1962 voptgenerror
1963 (FLG_TYPE,
1964 message ("Modifies clause arrow accesses pointer to "
1965 "non-structure (type %s): %q",
1966 ctype_unparse (rt),
1967 sRef_unparse (s)),
1968 g_currentloc);
1969 }
1970 }
1971 else
1972 {
1973 voptgenerror
1974 (FLG_TYPE,
1975 message ("Modifies clause arrow accesses non-pointer (type %s): %q",
1976 ctype_unparse (rt),
1977 sRef_unparse (s)),
1978 g_currentloc);
1979 }
1980
1981 cstring_free (f);
1982 return s;
1983}
1984
28bf4b0b 1985sRef checkStateClausesId (uentry ue)
616915dd 1986{
1987 cstring s = uentry_rawName (ue);
1988
28bf4b0b 1989 if (sRef_isFileOrGlobalScope (uentry_getSref (ue)))
616915dd 1990 {
1991 voptgenerror
28bf4b0b 1992 (FLG_COMMENTERROR,
616915dd 1993 message ("Global variable %s used special clause. (Global variables "
1994 "are not recognized in special clauses. If there is "
1995 "sufficient interest in support for this, it may be "
1996 "added to a future release. Send mail to "
1997 "lclint@cs.virginia.edu.)",
1998 s),
1999 g_currentloc);
2000
2001 return sRef_undefined;
2002 }
2003 else
2004 {
2005 if (cstring_equalLit (s, "result"))
2006 {
2007 if (optgenerror
2008 (FLG_SYNTAX,
2009 message ("Special clause list uses %s which is a variable and has special "
2010 "meaning in a modifies list. (Special meaning assumed.)", s),
2011 g_currentloc))
2012 {
2013 uentry_showWhereDeclared (ue);
2014 }
2015 }
2016
2017 return uentry_getSref (ue);
2018 }
2019}
9280addf 2020/*drl:1/19/2001
2021 oops to 1/8/2000
2022 date is wronge ..
2023 don;t know what the real date is...
2024
2025*/
616915dd 2026
2027/*drl
2028 added 1/8/2000
2029 based on checkSpecClausesId
2030 called by grammar
2031*/
b37cf05e 2032
616915dd 2033sRef checkbufferConstraintClausesId (uentry ue)
2034{
2035 cstring s = uentry_rawName (ue);
08eb3d0e 2036
616915dd 2037 if (cstring_equalLit (s, "result"))
2038 {
2039 if (optgenerror
2040 (FLG_SYNTAX,
08eb3d0e 2041 message ("Function clause list uses %s which is a variable and has special "
616915dd 2042 "meaning in a modifies list. (Special meaning assumed.)", s),
2043 g_currentloc))
2044 {
2045 uentry_showWhereDeclared (ue);
2046 }
2047 }
2048
08eb3d0e 2049 return sRef_saveCopy (uentry_getSref (ue)); /*@i523 why the saveCopy? */
616915dd 2050}
2051
2052void checkModifiesId (uentry ue)
2053{
2054 cstring s = uentry_rawName (ue);
2055
2056 if (cstring_equalLit (s, "nothing")
2057 || cstring_equalLit (s, "internalState")
2058 || cstring_equalLit (s, "systemState")
2059 || (cstring_equalLit (s, "fileSystem")))
2060 {
2061 if (optgenerror
2062 (FLG_SYNTAX,
2063 message ("Modifies list uses %s which is a variable and has special "
2064 "meaning in a modifies list. (Special meaning assumed.)", s),
2065 g_currentloc))
2066 {
2067 uentry_showWhereDeclared (ue);
2068 }
2069 }
2070}
2071
2072/*@exposed@*/ sRef fixModifiesId (cstring s)
2073{
2074 sRef ret;
2075 cstring pname = makeParam (s);
2076 uentry ue = usymtab_lookupSafe (pname);
2077
2078 cstring_free (pname);
2079
2080 if (cstring_equalLit (s, "nothing"))
2081 {
2082 ret = sRef_makeNothing ();
2083 }
2084 else if (cstring_equalLit (s, "internalState"))
2085 {
2086 ret = sRef_makeInternalState ();
2087 }
2088 else if (cstring_equalLit (s, "fileSystem")
2089 || cstring_equalLit (s, "systemState"))
2090 {
2091 ret = sRef_makeSystemState ();
2092 }
2093 else
2094 {
2095 ret = sRef_undefined;
2096 }
2097
2098 if (sRef_isValid (ret))
2099 {
2100 if (uentry_isValid (ue))
2101 {
2102 voptgenerror
2103 (FLG_SYNTAX,
2104 message ("Modifies list uses %s which is a parameter and has special "
2105 "meaning in a modifies list. (Special meaning assumed.)", s),
2106 g_currentloc);
2107 }
2108 }
2109 else
2110 {
2111 if (uentry_isValid (ue))
2112 {
2113 ret = uentry_getSref (ue);
2114 }
2115 else
2116 {
2117 fileloc loc = fileloc_decColumn (g_currentloc, cstring_length (s));
2118 ret = sRef_undefined;
2119
2120 voptgenerror
2121 (FLG_UNRECOG,
2122 message ("Unrecognized identifier in modifies comment: %s", s),
2123 loc);
2124
2125 fileloc_free (loc);
2126 }
2127 }
2128
2129 return ret;
2130}
2131
28bf4b0b 2132sRef fixStateClausesId (cstring s)
616915dd 2133{
2134 sRef ret;
2135 cstring pname = makeParam (s);
2136 uentry ue = usymtab_lookupSafe (pname);
2137
2138 cstring_free (pname);
2139
2140 if (cstring_equalLit (s, "result"))
2141 {
b072092f 2142 ret = sRef_makeResult (ctype_unknown);
616915dd 2143 }
2144 else
2145 {
2146 ret = sRef_undefined;
2147 }
2148
2149 if (sRef_isValid (ret))
2150 {
2151 if (uentry_isValid (ue))
2152 {
2153 voptgenerror
2154 (FLG_SYNTAX,
d9a28762 2155 message ("Function clause uses %s which is a parameter and has special "
2156 "meaning in a function clause. (Special meaning assumed.)", s),
616915dd 2157 g_currentloc);
2158 }
2159 }
2160 else
2161 {
2162 if (uentry_isValid (ue))
2163 {
2164 ret = uentry_getSref (ue);
2165
28bf4b0b 2166 if (sRef_isFileOrGlobalScope (ret))
616915dd 2167 {
2168 voptgenerror
2169 (FLG_SYNTAX,
d9a28762 2170 message ("Global variable %s used in function clause. (Global variables "
2171 "are not recognized in function clauses. If there is "
616915dd 2172 "sufficient interest in support for this, it may be "
2173 "added to a future release. Send mail to "
2174 "lclint@cs.virginia.edu.)",
2175 s),
2176 g_currentloc);
2177
2178 ret = sRef_undefined;
2179 }
2180 }
2181 else
2182 {
2183 fileloc loc = fileloc_decColumn (g_currentloc, cstring_length (s));
2184 ret = sRef_undefined;
2185
2186 voptgenerror
2187 (FLG_UNRECOG,
d9a28762 2188 message ("Unrecognized identifier in function clause: %s", s),
616915dd 2189 loc);
2190
2191 fileloc_free (loc);
2192 }
2193 }
2194
2195 return ret;
2196}
2197
28bf4b0b 2198sRef modListArrayFetch (/*@exposed@*/ sRef s, /*@unused@*/ sRef mexp)
616915dd 2199{
2200 ctype ct = sRef_getType (s);
2201 ctype rt = ctype_realType (ct);
2202
2203 if (ctype_isAP (rt))
2204 {
2205 if (context_inHeader () && ctype_isAbstract (ct))
2206 {
2207 voptgenerror
2208 (FLG_ABSTRACT,
2209 message
2210 ("Modifies clause in header file indexes abstract "
2211 "type %s (interface modifies clause should not depend "
2212 "on or expose type representation): %q",
2213 ctype_unparse (ct),
2214 sRef_unparse (s)),
2215 g_currentloc);
2216 }
2217
2218 return (sRef_makeAnyArrayFetch (s));
2219 }
2220 else
2221 {
2222 voptgenerror
2223 (FLG_TYPE,
2224 message
2225 ("Implementation modifies clause uses array fetch on non-array (type %s): %q",
2226 ctype_unparse (ct), sRef_unparse (s)),
2227 g_currentloc);
2228 return s;
2229 }
2230}
2231
28bf4b0b 2232static void clabstract_prepareFunction (uentry e)
2233{
2234 uentry_checkParams (e);
2235 DPRINTF (("After prepare: %s", uentry_unparseFull (e)));
2236}
2237
2238sRef clabstract_checkGlobal (exprNode e)
2239{
2240 sRef s;
2241 llassert (exprNode_isInitializer (e));
2242
2243 s = exprNode_getSref (e);
2244 DPRINTF (("Initializer: %s -> %s", exprNode_unparse (e), sRef_unparse (s)));
2245
2246 exprNode_free (e);
2247 return sRef_copy (s);
2248}
2249
616915dd 2250
2251
2252
2253
2254
2255
2256
This page took 0.581348 seconds and 5 git commands to generate.