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