]> andersk Git - splint.git/blame - src/clabstract.c
Fixed line numbering when multi-line macro parameters are used.
[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
1258 if (warnClause_isDefined (warn))
1259 {
1260 exprNodeList_elements (decls, el)
1261 {
1262 uentry ue = exprNode_getUentry (el);
1263 cstring uname = uentry_getName (ue);
1264
1265 DPRINTF (("Entry: %s", exprNode_unparse (el)));
1266
1267 /*
1268 ** Need to lookup again to make sure we have the right one...
1269 */
1270
15b3d2b2 1271 ue = usymtab_lookupExposeGlob (uname);
e83c79ec 1272
1273 llassert (uentry_isValid (ue));
1274 llassert (uentry_isDatatype (ue));
1275
1276 DPRINTF (("Warning for %s: %s",
1277 uentry_unparse (ue), warnClause_unparse (warn)));
1278
1279 uentry_addWarning (ue, warnClause_copy (warn));
15b3d2b2 1280 cstring_free (uname);
e83c79ec 1281 } end_exprNodeList_elements;
1282 }
1283
1284 warnClause_free (warn);
1285 exprNodeList_free (decls);
1286 unsetProcessingTypedef ();
1287}
1288
616915dd 1289void
1290unsetProcessingTypedef ()
1291{
1292 ProcessingTypedef = FALSE;
1293}
1294
1295void checkConstant (qtype t, idDecl id)
1296{
1297 uentry e;
7534721d 1298
616915dd 1299 id = idDecl_fixBase (id, t);
1300 e = uentry_makeIdConstant (id);
7534721d 1301
616915dd 1302 reflectStorageClass (e);
1303 resetStorageClass ();
1304
d89a0c94 1305 DPRINTF (("Constant: %s", uentry_unparseFull (e)));
616915dd 1306 usymtab_supGlobalEntry (e);
1307}
1308
1309void checkValueConstant (qtype t, idDecl id, exprNode e)
1310{
1311 uentry ue;
1312
1313 id = idDecl_fixBase (id, t);
1314 ue = uentry_makeIdConstant (id);
1315 reflectStorageClass (ue);
1316 resetStorageClass ();
1317
1318 if (exprNode_isDefined (e))
1319 {
1320 if (!exprNode_matchType (uentry_getType (ue), e))
1321 {
1322 (void) gentypeerror
1323 (exprNode_getType (e), e,
1324 uentry_getType (ue), exprNode_undefined,
1325 message ("Constant %q initialized to type %t, expects %t: %s",
1326 uentry_getName (ue),
1327 exprNode_getType (e),
1328 uentry_getType (ue),
1329 exprNode_unparse (e)),
1330 exprNode_loc (e));
1331 }
1332 else
1333 {
1334 if (exprNode_hasValue (e))
1335 {
1336 uentry_mergeConstantValue (ue, multiVal_copy (exprNode_getValue (e)));
1337 }
b9904f57 1338 else
1339 {
1340 DPRINTF (("No value: %s", exprNode_unparse (e)));
1341 }
616915dd 1342 }
1343 }
1344
b9904f57 1345 DPRINTF (("Constant value: %s", uentry_unparseFull (ue)));
616915dd 1346 usymtab_supGlobalEntry (ue);
1347}
1348
616915dd 1349void processNamedDecl (idDecl t)
1350{
1351 if (qtype_isUndefined (processingType))
1352 {
1353 llparseerror (message ("No type before declaration name: %q", idDecl_unparse (t)));
1354
1355 processingType = qtype_create (ctype_unknown);
1356 }
1357
1358 t = idDecl_fixBase (t, processingType);
1359
1360 DPRINTF (("Declare: %s", idDecl_unparse (t)));
7ebcc5bb 1361
616915dd 1362 if (ProcessingGlobals)
1363 {
1364 cstring id = idDecl_getName (t);
1365 uentry ue = usymtab_lookupSafe (id);
28bf4b0b 1366
616915dd 1367 if (!uentry_isValid (ue))
1368 {
1369 llerror (FLG_UNRECOG,
1370 message ("Variable used in globals list is undeclared: %s", id));
1371 }
1372 else
1373 {
1374 if (!ctype_match (uentry_getType (ue), idDecl_getCtype (t)))
1375 {
1376 voptgenerror
1377 (FLG_INCONDEFS,
1378 message ("Variable %s used in globals list declared %s, "
1379 "but listed as %s",
1380 id, ctype_unparse (uentry_getType (ue)),
1381 ctype_unparse (idDecl_getCtype (t))),
1382 g_currentloc);
1383 }
1384 else
1385 {
1386 sRef sr = sRef_copy (uentry_getSref (ue));
616915dd 1387 reflectGlobalQualifiers (sr, idDecl_getQuals (t));
616915dd 1388 }
1389 }
1390 }
1391 else if (ProcessingVars)
1392 {
1393 uentry e;
1394 ctype ct;
1395
1396 ct = ctype_realType (idDecl_getCtype (t));
1397
1398 if (ProcessingParams)
1399 {
1400 cstring id = idDecl_getName (t);
1401 int paramno = uentryList_lookupRealName (saveParamList, id);
1402
1403 if (paramno >= 0)
1404 {
1405 uentry cparam = uentryList_getN (saveParamList, paramno);
1406
7ebcc5bb 1407 DPRINTF (("Processing param: %s", uentry_unparseFull (cparam)));
616915dd 1408 uentry_setType (cparam, idDecl_getCtype (t));
1409 uentry_reflectQualifiers (cparam, idDecl_getQuals (t));
1410 uentry_setDeclaredOnly (cparam, context_getSaveLocation ());
7ebcc5bb 1411 DPRINTF (("Processing param: %s", uentry_unparseFull (cparam)));
616915dd 1412 }
1413 else
1414 {
1415 llfatalerrorLoc
1416 (message ("Old style declaration uses unlisted parameter: %s",
1417 id));
1418 }
1419 }
1420 else
1421 {
1422 fileloc loc;
1423
1424 if (context_inIterDef ())
1425 {
1426 cstring pname = makeParam (idDecl_observeId (t));
1427 uentry p = usymtab_lookupSafe (pname);
1428
1429 cstring_free (pname);
1430
1431 if (uentry_isYield (p))
28bf4b0b 1432 {
1433 e = uentry_makeParam (t, sRef_getParam (uentry_getSref (p)));
1434 uentry_checkYieldParam (p, e);
1435 usymtab_supEntrySref (e);
1436 return;
1437 }
616915dd 1438 }
28bf4b0b 1439
616915dd 1440 if ((hasSpecialCode () || argsUsed)
1441 && ctype_isFunction (idDecl_getCtype (t)))
28bf4b0b 1442 {
616915dd 1443 e = uentry_makeIdFunction (t);
1444 reflectSpecialCode (e);
1445 reflectArgsUsed (e);
28bf4b0b 1446 }
616915dd 1447 else
28bf4b0b 1448 {
1449 e = uentry_makeIdVariable (t);
1450 }
1451
616915dd 1452 loc = uentry_whereDeclared (e);
28bf4b0b 1453
616915dd 1454 /*
28bf4b0b 1455 if (context_inGlobalScope ())
616915dd 1456 {
1457 uentry_checkParams was here!
1458 }
28bf4b0b 1459 */
1460
616915dd 1461 if (ctype_isFunction (uentry_getType (e)))
1462 {
28bf4b0b 1463 clabstract_prepareFunction (e);
616915dd 1464 }
1465
28bf4b0b 1466 DPRINTF (("Superceding... %s", uentry_unparseFull (e)));
616915dd 1467 e = usymtab_supEntrySrefReturn (e);
28bf4b0b 1468 DPRINTF (("After superceding... %s", uentry_unparseFull (e)));
1469
616915dd 1470 if (uentry_isExtern (e) && !context_inGlobalScope ())
1471 {
1472 voptgenerror
1473 (FLG_NESTEDEXTERN,
1474 message ("Declaration using extern inside function scope: %q",
1475 uentry_unparse (e)),
1476 g_currentloc);
1477
1478 uentry_setDefined (e, fileloc_getExternal ());
1479 sRef_setDefined (uentry_getSref (e), fileloc_getExternal ());
1480 }
28bf4b0b 1481
616915dd 1482 if (uentry_isFunction (e))
1483 {
28bf4b0b 1484 if (!context_inXHFile ())
1485 {
1486 checkParamNames (e);
1487 }
616915dd 1488 }
28bf4b0b 1489
1490 if (uentry_isVar (e) && uentry_isCheckedUnknown (e))
616915dd 1491 {
1492 sRef sr = uentry_getSref (e);
28bf4b0b 1493
616915dd 1494 if (sRef_isLocalVar (sr))
1495 {
1496 if (context_getFlag (FLG_IMPCHECKMODINTERNALS))
1497 {
1498 uentry_setCheckMod (e);
1499 }
1500 else
1501 {
1502 uentry_setUnchecked (e);
1503 }
1504 }
1505 else if (sRef_isFileStatic (sr))
1506 {
1507 if (context_getFlag (FLG_IMPCHECKEDSTRICTSTATICS))
1508 {
1509 uentry_setCheckedStrict (e);
1510 }
1511 else if (context_getFlag (FLG_IMPCHECKEDSTATICS))
1512 {
1513 uentry_setChecked (e);
1514 }
1515 else if (context_getFlag (FLG_IMPCHECKMODSTATICS))
1516 {
1517 uentry_setCheckMod (e);
1518 }
1519 else
1520 {
1521 ;
1522 }
1523 }
1524 else /* real global */
1525 {
1526 llassert (sRef_isRealGlobal (sr));
28bf4b0b 1527
616915dd 1528 if (context_getFlag (FLG_IMPCHECKEDSTRICTGLOBALS))
1529 {
1530 uentry_setCheckedStrict (e);
1531 }
1532 else if (context_getFlag (FLG_IMPCHECKEDGLOBALS))
1533 {
1534 uentry_setChecked (e);
1535 }
1536 else if (context_getFlag (FLG_IMPCHECKMODGLOBALS))
1537 {
1538 uentry_setCheckMod (e);
1539 }
1540 else
1541 {
1542 ;
1543 }
1544 }
1545 }
1546 }
1547 }
1548 else if (ProcessingTypedef)
1549 {
1550 ctype ct = idDecl_getCtype (t);
1551 uentry e;
28bf4b0b 1552
616915dd 1553 DPRINTF (("Processing typedef: %s", ctype_unparse (ct)));
1554
1555 e = uentry_makeIdDatatype (t);
1556
1557 if (cstring_equal (idDecl_getName (t), context_getBoolName ())) {
1558 ctype rt = ctype_realType (ct);
1559
1560 if (ctype_isEnum (rt)) {
1561 ;
1562 } else {
1563 if (!(ctype_isInt (rt)
1564 || ctype_isUnknown (rt)
1565 || ctype_isChar (rt))) {
1566 (void) llgenerror
1567 (FLG_BOOLTYPE,
1568 message ("Boolean type %s defined using non-standard type %s (integral, char or enum type expected)",
1569 context_getBoolName (),
1570 ctype_unparse (ct)),
1571 uentry_whereLast (e));
1572 }
1573
1574 ct = ctype_bool;
1575 uentry_setType (e, ct);
1576 }
1577 }
1578
1579 reflectStorageClass (e);
1580 checkTypeDecl (e, ct);
1581
1582 e = usymtab_supReturnTypeEntry (e);
616915dd 1583 }
1584 else
1585 {
1586 llparseerror (message ("Suspect missing struct or union keyword: %q",
1587 idDecl_unparse (t)));
1588 }
1589
1590 }
1591
1592/*
1593** moved from grammar
1594*/
1595
1596static idDecl fixStructDecl (/*@returned@*/ idDecl d)
1597{
1598 if (ctype_isVisiblySharable (idDecl_getCtype (d))
1599 && context_getFlag (FLG_STRUCTIMPONLY))
1600 {
1601 if (!qualList_hasAliasQualifier (idDecl_getQuals (d)))
1602 {
1603 if (qualList_hasExposureQualifier (idDecl_getQuals (d)))
1604 {
1605 idDecl_addQual (d, qual_createDependent ());
1606 }
1607 else
1608 {
1609 idDecl_addQual (d, qual_createImpOnly ());
1610 }
1611 }
1612 }
1613
1614 return d;
1615}
1616
1617ctype
1618declareUnnamedStruct (/*@only@*/ uentryList f)
1619{
28bf4b0b 1620 DPRINTF (("Unnamed struct: %s", uentryList_unparse (f)));
1621
616915dd 1622 if (context_maybeSet (FLG_NUMSTRUCTFIELDS))
1623 {
1624 int num = uentryList_size (f);
1625 int max = context_getValue (FLG_NUMSTRUCTFIELDS);
1626
1627 if (num > max)
1628 {
1629 voptgenerror
1630 (FLG_NUMSTRUCTFIELDS,
1631 message ("Structure declared with %d fields "
1632 "(limit is set to %d)",
1633 num, max),
1634 g_currentloc);
1635 }
1636 }
1637
1638 return (ctype_createUnnamedStruct (f));
1639}
1640
1641ctype
1642declareUnnamedUnion (/*@only@*/ uentryList f)
1643{
1644 if (context_maybeSet (FLG_NUMSTRUCTFIELDS))
1645 {
1646 int num = uentryList_size (f);
1647 int max = context_getValue (FLG_NUMSTRUCTFIELDS);
1648
1649 if (num > max)
1650 {
1651 voptgenerror
1652 (FLG_NUMSTRUCTFIELDS,
1653 message ("Union declared with %d fields "
1654 "(limit is set to %d)",
1655 num, max),
1656 g_currentloc);
1657 }
1658 }
1659
1660 return (ctype_createUnnamedUnion (f));
1661}
1662
1663ctype declareStruct (cstring id, /*@only@*/ uentryList f)
1664{
1665 ctype ct;
1666 uentry ue;
1667 int num = uentryList_size (f);
1668
28bf4b0b 1669 DPRINTF (("Declare struct: %s / %s", id, uentryList_unparse (f)));
1670
616915dd 1671 ct = ctype_createStruct (cstring_copy (id), f);
28bf4b0b 1672
1673 DPRINTF (("Ctype: %s", ctype_unparse (ct)));
1674
616915dd 1675 ue = uentry_makeStructTagLoc (id, ct);
1676
28bf4b0b 1677 DPRINTF (("ue: %s", uentry_unparseFull (ue)));
1678
616915dd 1679 if (context_maybeSet (FLG_NUMSTRUCTFIELDS))
1680 {
1681 int max = context_getValue (FLG_NUMSTRUCTFIELDS);
1682
1683 if (num > max)
1684 {
1685 voptgenerror
1686 (FLG_NUMSTRUCTFIELDS,
1687 message ("Structure %q declared with %d fields "
1688 "(limit is set to %d)",
1689 uentry_getName (ue), num, max),
1690 uentry_whereLast (ue));
1691 }
1692 }
1693
1694 return (usymtab_supTypeEntry (ue));
1695}
1696
1697ctype declareUnion (cstring id, uentryList f)
1698{
1699 ctype ct;
1700 uentry ue;
1701 int num = uentryList_size (f);
1702
1703 ct = ctype_createUnion (cstring_copy (id), f);
1704 ue = uentry_makeUnionTagLoc (id, ct);
1705
1706 if (context_maybeSet (FLG_NUMSTRUCTFIELDS))
1707 {
1708 int max = context_getValue (FLG_NUMSTRUCTFIELDS);
1709
1710 if (num > max)
1711 {
1712 voptgenerror
1713 (FLG_NUMSTRUCTFIELDS,
1714 message ("Union %q declared with %d fields "
1715 "(limit is set to %d)",
1716 uentry_getName (ue), num, max),
1717 uentry_whereLast (ue));
1718 }
1719 }
1720
1721 return (usymtab_supTypeEntry (ue));
1722}
1723
1724ctype handleStruct (/*@only@*/ cstring id)
1725{
1726 if (usymtab_existsStructTag (id))
1727 {
1728 ctype ct = uentry_getAbstractType (usymtab_lookupStructTag (id));
1729
1730 cstring_free (id);
1731 return ct;
1732 }
1733 else
1734 {
1735 return (ctype_createForwardStruct (id));
1736 }
1737}
1738
1739ctype handleUnion (/*@only@*/ cstring id)
1740{
1741 if (usymtab_existsUnionTag (id))
1742 {
1743 ctype ret = uentry_getAbstractType (usymtab_lookupUnionTag (id));
1744 cstring_free (id);
1745 return (ret);
1746 }
1747 else
1748 {
1749 return (ctype_createForwardUnion (id));
1750 }
1751}
1752
1753ctype
1754handleEnum (cstring id)
1755{
1756 if (usymtab_existsEnumTag (id))
1757 {
1758 ctype ret = uentry_getAbstractType (usymtab_lookupEnumTag (id));
1759 cstring_free (id);
1760 return ret;
1761 }
1762 else
1763 {
1764 return (declareEnum (id, enumNameList_new ()));
1765 }
1766}
1767
1768bool processingIterVars (void)
1769{
1770 return ProcessingIterVars;
1771}
1772
1773uentry getCurrentIter (void)
1774{
1775 return currentIter;
1776}
1777
1778static bool flipOldStyle = FALSE;
1779static bool flipNewStyle = TRUE;
1780
1781void setFlipOldStyle () { flipOldStyle = TRUE; }
1782bool isFlipOldStyle () { return flipOldStyle; }
1783bool isNewStyle () { return flipNewStyle; }
1784void setNewStyle () { flipNewStyle = TRUE; }
1785
1786/*@dependent@*/ uentryList handleParamIdList (/*@dependent@*/ uentryList params)
1787{
1788 int paramno = 0;
1789
1790 /*
1791 ** this is a really YUCKY hack to handle old style
1792 ** declarations.
1793 */
1794
1795 voptgenerror (FLG_OLDSTYLE,
1796 cstring_makeLiteral ("Old style function declaration"),
1797 g_currentloc);
1798
7ebcc5bb 1799 DPRINTF (("Handle old style params: %s", uentryList_unparseFull (params)));
1800
616915dd 1801 uentryList_elements (params, current)
1802 {
1803 uentry_setParam (current);
6970c11b 1804 uentry_setSref (current, sRef_makeParam (paramno, ctype_unknown, stateInfo_makeLoc (uentry_whereLast (current))));
616915dd 1805 paramno++;
1806 } end_uentryList_elements;
1807
1808 setGenericParamList (params);
1809 g_expectingTypeName = TRUE;
1810
1811 return params;
1812}
1813
1814/*@dependent@*/ uentryList handleParamTypeList (/*@returned@*/ uentryList params)
1815{
1816 if (flipOldStyle)
1817 {
1818 uentryList_fixMissingNames (params);
1819
1820 voptgenerror (FLG_OLDSTYLE,
1821 cstring_makeLiteral ("Old style function declaration."),
1822 g_currentloc);
1823
1824 setGenericParamList (params);
1825 flipOldStyle = FALSE;
1826 g_expectingTypeName = TRUE;
1827 }
1828
1829 return (params);
1830}
1831
1832void
1833doVaDcl ()
1834{
1835 ctype c = ctype_unknown;
1836 cstring id = cstring_makeLiteral ("va_alist");
1837 uentry e;
1838
1839 if (ProcessingParams)
1840 {
1841 int i = uentryList_lookupRealName (saveParamList, id);
1842
1843 if (i >= 0)
1844 {
6970c11b 1845 fileloc loc = context_getSaveLocation ();
1846 e = uentry_makeVariableSrefParam (id, c, loc, sRef_makeParam (i, c, stateInfo_makeLoc (loc)));
616915dd 1847 }
1848 else
1849 {
1850 e = uentry_undefined; /* suppress gcc message */
1851 llfatalerrorLoc (cstring_makeLiteral ("va_dcl used without va_alist"));
1852 }
1853 }
1854 else
1855 {
1856 llerror (FLG_SYNTAX, cstring_makeLiteral ("va_dcl used outside of function declaration"));
1857 e = uentry_makeVariableLoc (id, c);
1858 }
1859
1860 cstring_free (id);
1861 uentry_setUsed (e, g_currentloc);
1862 usymtab_supEntrySref (e);
1863}
1864
28bf4b0b 1865/*@exposed@*/ sRef modListPointer (/*@exposed@*/ sRef s)
616915dd 1866{
1867 ctype ct = sRef_getType (s);
1868 ctype rt = ctype_realType (ct);
1869
1870 if (ctype_isAP (rt))
1871 {
1872 if (context_inHeader () && ctype_isAbstract (ct))
1873 {
1874 voptgenerror
1875 (FLG_ABSTRACT,
1876 message
1877 ("Modifies clause in header file dereferences abstract "
1878 "type %s (interface modifies clause should not depend "
1879 "on or expose type representation): %q",
1880 ctype_unparse (ct),
1881 sRef_unparse (s)),
1882 g_currentloc);
1883 }
1884
1885 return (sRef_constructPointer (s));
1886 }
1887 else
1888 {
1889 if (ctype_isKnown (rt))
1890 {
1891 voptgenerror
1892 (FLG_TYPE,
1893 message ("Implementation modifies clause dereferences non-pointer (type %s): %q",
1894 ctype_unparse (rt),
1895 sRef_unparse (s)),
1896 g_currentloc);
1897 }
1898
1899 return s;
1900 }
1901}
1902
1903/*@exposed@*/ sRef modListFieldAccess (sRef s, cstring f)
1904{
1905 ctype ct = sRef_getType (s);
1906 ctype rt = ctype_realType (ct);
1907
1908 if (ctype_isStructorUnion (rt))
1909 {
1910 uentry tf = uentryList_lookupField (ctype_getFields (rt), f);
1911
1912 if (uentry_isUndefined (tf))
1913 {
1914 voptgenerror (FLG_TYPE,
1915 message ("Modifies list accesses non-existent "
1916 "field %s of %t: %q", f, ct,
1917 sRef_unparse (s)),
1918 g_currentloc);
1919
1920 cstring_free (f);
1921 return sRef_undefined;
1922 }
1923 else
1924 {
1925 if (ctype_isAbstract (ct) && context_inHeader ())
1926 {
1927 voptgenerror
1928 (FLG_ABSTRACT,
1929 message
1930 ("Modifies clause in header file accesses abstract "
1931 "type %s (interface modifies clause should not depend "
1932 "on or expose type representation): %q",
1933 ctype_unparse (ct),
1934 sRef_unparse (s)),
1935 g_currentloc);
1936 }
1937 }
1938
1939 cstring_markOwned (f);
1940 return (sRef_makeField (s, f));
1941 }
1942 else
1943 {
1944 voptgenerror
1945 (FLG_TYPE,
1946 message ("Modifies clause dereferences non-pointer (type %s): %q",
1947 ctype_unparse (rt),
1948 sRef_unparse (s)),
1949 g_currentloc);
1950
1951 cstring_free (f);
1952 return s;
1953 }
1954}
1955
28bf4b0b 1956/*@dependent@*/ sRef clabstract_unrecognizedGlobal (cstring s)
616915dd 1957{
1958 if (cstring_equalLit (s, "nothing"))
1959 {
1960 return sRef_makeNothing ();
1961 }
1962 else if (cstring_equalLit (s, "internalState"))
1963 {
1964 return sRef_makeInternalState ();
1965 }
1966 else if (cstring_equalLit (s, "fileSystem")
1967 || cstring_equalLit (s, "systemState"))
1968 {
1969 return sRef_makeSystemState ();
1970 }
1971 else
1972 {
1973 voptgenerror
1974 (FLG_UNRECOG,
1975 message ("Unrecognized identifier in globals list: %s", s),
1976 g_currentloc);
1977
1978 return sRef_undefined;
1979 }
1980}
1981
1982/*@exposed@*/ sRef modListArrowAccess (sRef s, cstring f)
1983{
1984 ctype ct = sRef_getType (s);
1985 ctype rt = ctype_realType (ct);
1986
1987 if (ctype_isRealPointer (rt))
1988 {
1989 ctype b = ctype_baseArrayPtr (rt);
1990 ctype rb = ctype_realType (b);
1991
1992 if (ctype_isStructorUnion (rb))
1993 {
1994 uentry tf = uentryList_lookupField (ctype_getFields (rb), f);
1995
1996 if (uentry_isUndefined (tf))
1997 {
1998 voptgenerror (FLG_TYPE,
1999 message ("Modifies list arrow accesses non-existent "
2000 "field %s of %t: %q", f, b,
2001 sRef_unparse (s)),
2002 g_currentloc);
2003
2004 cstring_free (f);
2005 return sRef_undefined;
2006 }
2007 else
2008 {
2009 if (context_inHeader ())
2010 {
2011 if (ctype_isAbstract (b))
2012 {
2013 voptgenerror
2014 (FLG_ABSTRACT,
2015 message
2016 ("Modifies clause in header file arrow accesses abstract "
2017 "type %s (interface modifies clause should not depend "
2018 "on or expose type representation): %q",
2019 ctype_unparse (b),
2020 sRef_unparse (s)),
2021 g_currentloc);
2022 }
2023 }
2024 else
2025 {
146e25eb 2026 if (ctype_isAbstract (rt))
616915dd 2027 {
2028 voptgenerror
2029 (FLG_ABSTRACT,
2030 message
146e25eb 2031 ("Modifies clause arrow accesses inaccessible abstract "
616915dd 2032 "type %s (interface modifies clause should not depend "
2033 "on or expose type representation): %q",
146e25eb 2034 ctype_unparse (rt),
616915dd 2035 sRef_unparse (s)),
2036 g_currentloc);
2037 }
2038 }
2039 }
2040
2041 cstring_markOwned (f);
2042 return (sRef_makeArrow (s, f));
2043 }
2044 else
2045 {
2046 voptgenerror
2047 (FLG_TYPE,
2048 message ("Modifies clause arrow accesses pointer to "
2049 "non-structure (type %s): %q",
2050 ctype_unparse (rt),
2051 sRef_unparse (s)),
2052 g_currentloc);
2053 }
2054 }
2055 else
2056 {
2057 voptgenerror
2058 (FLG_TYPE,
2059 message ("Modifies clause arrow accesses non-pointer (type %s): %q",
2060 ctype_unparse (rt),
2061 sRef_unparse (s)),
2062 g_currentloc);
2063 }
2064
2065 cstring_free (f);
2066 return s;
2067}
2068
28bf4b0b 2069sRef checkStateClausesId (uentry ue)
616915dd 2070{
2071 cstring s = uentry_rawName (ue);
2072
28bf4b0b 2073 if (sRef_isFileOrGlobalScope (uentry_getSref (ue)))
616915dd 2074 {
2075 voptgenerror
28bf4b0b 2076 (FLG_COMMENTERROR,
1b8ae690 2077 message ("Global variable %s used state clause. (Global variables "
2078 "are not recognized in state clauses. If there is "
616915dd 2079 "sufficient interest in support for this, it may be "
2080 "added to a future release. Send mail to "
155af98d 2081 "info@splint.org.)",
616915dd 2082 s),
2083 g_currentloc);
2084
2085 return sRef_undefined;
2086 }
2087 else
2088 {
2089 if (cstring_equalLit (s, "result"))
2090 {
2091 if (optgenerror
2092 (FLG_SYNTAX,
2093 message ("Special clause list uses %s which is a variable and has special "
2094 "meaning in a modifies list. (Special meaning assumed.)", s),
2095 g_currentloc))
2096 {
2097 uentry_showWhereDeclared (ue);
2098 }
2099 }
2100
2101 return uentry_getSref (ue);
2102 }
2103}
9280addf 2104/*drl:1/19/2001
2105 oops to 1/8/2000
2106 date is wronge ..
2107 don;t know what the real date is...
2108
2109*/
616915dd 2110
2111/*drl
2112 added 1/8/2000
2113 based on checkSpecClausesId
2114 called by grammar
2115*/
b37cf05e 2116
616915dd 2117sRef checkbufferConstraintClausesId (uentry ue)
2118{
2119 cstring s = uentry_rawName (ue);
08eb3d0e 2120
616915dd 2121 if (cstring_equalLit (s, "result"))
2122 {
2123 if (optgenerror
2124 (FLG_SYNTAX,
08eb3d0e 2125 message ("Function clause list uses %s which is a variable and has special "
616915dd 2126 "meaning in a modifies list. (Special meaning assumed.)", s),
2127 g_currentloc))
2128 {
2129 uentry_showWhereDeclared (ue);
2130 }
2131 }
2132
b9904f57 2133 DPRINTF (("constrant id: %s", uentry_unparseFull (ue)));
08eb3d0e 2134 return sRef_saveCopy (uentry_getSref (ue)); /*@i523 why the saveCopy? */
616915dd 2135}
2136
2137void checkModifiesId (uentry ue)
2138{
2139 cstring s = uentry_rawName (ue);
2140
2141 if (cstring_equalLit (s, "nothing")
2142 || cstring_equalLit (s, "internalState")
2143 || cstring_equalLit (s, "systemState")
2144 || (cstring_equalLit (s, "fileSystem")))
2145 {
2146 if (optgenerror
2147 (FLG_SYNTAX,
2148 message ("Modifies list uses %s which is a variable and has special "
2149 "meaning in a modifies list. (Special meaning assumed.)", s),
2150 g_currentloc))
2151 {
2152 uentry_showWhereDeclared (ue);
2153 }
2154 }
2155}
2156
2157/*@exposed@*/ sRef fixModifiesId (cstring s)
2158{
2159 sRef ret;
2160 cstring pname = makeParam (s);
2161 uentry ue = usymtab_lookupSafe (pname);
2162
2163 cstring_free (pname);
2164
2165 if (cstring_equalLit (s, "nothing"))
2166 {
2167 ret = sRef_makeNothing ();
2168 }
2169 else if (cstring_equalLit (s, "internalState"))
2170 {
2171 ret = sRef_makeInternalState ();
2172 }
2173 else if (cstring_equalLit (s, "fileSystem")
2174 || cstring_equalLit (s, "systemState"))
2175 {
2176 ret = sRef_makeSystemState ();
2177 }
2178 else
2179 {
2180 ret = sRef_undefined;
2181 }
2182
2183 if (sRef_isValid (ret))
2184 {
2185 if (uentry_isValid (ue))
2186 {
2187 voptgenerror
2188 (FLG_SYNTAX,
2189 message ("Modifies list uses %s which is a parameter and has special "
2190 "meaning in a modifies list. (Special meaning assumed.)", s),
2191 g_currentloc);
2192 }
2193 }
2194 else
2195 {
2196 if (uentry_isValid (ue))
2197 {
2198 ret = uentry_getSref (ue);
2199 }
2200 else
2201 {
abd7f895 2202 fileloc loc = fileloc_decColumn (g_currentloc, size_toInt (cstring_length (s)));
616915dd 2203 ret = sRef_undefined;
2204
2205 voptgenerror
2206 (FLG_UNRECOG,
2207 message ("Unrecognized identifier in modifies comment: %s", s),
2208 loc);
2209
2210 fileloc_free (loc);
2211 }
2212 }
2213
2214 return ret;
2215}
2216
28bf4b0b 2217sRef fixStateClausesId (cstring s)
616915dd 2218{
2219 sRef ret;
2220 cstring pname = makeParam (s);
2221 uentry ue = usymtab_lookupSafe (pname);
2222
2223 cstring_free (pname);
2224
2225 if (cstring_equalLit (s, "result"))
2226 {
b072092f 2227 ret = sRef_makeResult (ctype_unknown);
616915dd 2228 }
2229 else
2230 {
2231 ret = sRef_undefined;
2232 }
2233
2234 if (sRef_isValid (ret))
2235 {
2236 if (uentry_isValid (ue))
2237 {
2238 voptgenerror
2239 (FLG_SYNTAX,
d9a28762 2240 message ("Function clause uses %s which is a parameter and has special "
2241 "meaning in a function clause. (Special meaning assumed.)", s),
616915dd 2242 g_currentloc);
2243 }
2244 }
2245 else
2246 {
2247 if (uentry_isValid (ue))
2248 {
2249 ret = uentry_getSref (ue);
2250
28bf4b0b 2251 if (sRef_isFileOrGlobalScope (ret))
616915dd 2252 {
2253 voptgenerror
2254 (FLG_SYNTAX,
d9a28762 2255 message ("Global variable %s used in function clause. (Global variables "
2256 "are not recognized in function clauses. If there is "
616915dd 2257 "sufficient interest in support for this, it may be "
2258 "added to a future release. Send mail to "
155af98d 2259 "info@splint.org.)",
616915dd 2260 s),
2261 g_currentloc);
2262
2263 ret = sRef_undefined;
2264 }
2265 }
2266 else
2267 {
86d93ed3 2268 /*@i222@*/
2269 /*drl handle structure invariant */
2270
2271 /*@i222@*/
2272 /*check that we're in a structure */
4dd72714 2273# if 0\r
2274 /*@unused@*/ uentryList ueL;
86d93ed3 2275 /*@unused@*/ uentry ue2;
4dd72714 2276 /*@unused@*/ ctype ct;\r
2277# endif
abd7f895 2278 fileloc loc = fileloc_decColumn (g_currentloc, size_toInt (cstring_length (s)));
616915dd 2279 ret = sRef_undefined;
4dd72714 2280# if 0
86d93ed3 2281 /*drl commenting this out for now
2282 ct = context_getLastStruct ( ct );
2283
2284 llassert( ctype_isStruct(ct) );
2285
2286 ueL = ctype_getFields (ct);
2287
2288 ue2 = uentryList_lookupField (ueL, s);
2289
2290 if (!uentry_isUndefined(ue2) )
2291 {
2292 ret = uentry_getSref(ue2);
2293
2294 DPRINTF((
2295 message("Got field in structure in the annotation constraint: %s (or sref: %s)", s, sRef_unparse(ret) )
2296 ));
2297
2298 return ret;
2299 }
4dd72714 2300 */\r
2301# endif\r
2302
616915dd 2303 voptgenerror
2304 (FLG_UNRECOG,
d9a28762 2305 message ("Unrecognized identifier in function clause: %s", s),
616915dd 2306 loc);
2307
2308 fileloc_free (loc);
2309 }
2310 }
2311
2312 return ret;
2313}
2314
28bf4b0b 2315sRef modListArrayFetch (/*@exposed@*/ sRef s, /*@unused@*/ sRef mexp)
616915dd 2316{
2317 ctype ct = sRef_getType (s);
2318 ctype rt = ctype_realType (ct);
2319
2320 if (ctype_isAP (rt))
2321 {
2322 if (context_inHeader () && ctype_isAbstract (ct))
2323 {
2324 voptgenerror
2325 (FLG_ABSTRACT,
2326 message
2327 ("Modifies clause in header file indexes abstract "
2328 "type %s (interface modifies clause should not depend "
2329 "on or expose type representation): %q",
2330 ctype_unparse (ct),
2331 sRef_unparse (s)),
2332 g_currentloc);
2333 }
2334
2335 return (sRef_makeAnyArrayFetch (s));
2336 }
2337 else
2338 {
2339 voptgenerror
2340 (FLG_TYPE,
2341 message
2342 ("Implementation modifies clause uses array fetch on non-array (type %s): %q",
2343 ctype_unparse (ct), sRef_unparse (s)),
2344 g_currentloc);
2345 return s;
2346 }
2347}
2348
28bf4b0b 2349static void clabstract_prepareFunction (uentry e)
2350{
2351 uentry_checkParams (e);
2352 DPRINTF (("After prepare: %s", uentry_unparseFull (e)));
2353}
2354
2355sRef clabstract_checkGlobal (exprNode e)
2356{
2357 sRef s;
2358 llassert (exprNode_isInitializer (e));
2359
2360 s = exprNode_getSref (e);
2361 DPRINTF (("Initializer: %s -> %s", exprNode_unparse (e), sRef_unparse (s)));
2362
2363 exprNode_free (e);
2364 return sRef_copy (s);
2365}
This page took 0.426821 seconds and 5 git commands to generate.