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