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