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