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