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