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