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