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