]> andersk Git - splint.git/blob - src/stateClauseList.c
*** empty log message ***
[splint.git] / src / stateClauseList.c
1 /*
2 ** LCLint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2001 University of Virginia,
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 ** stateClauseList.c
26 */
27
28 # include "lclintMacros.nf"
29 # include "basic.h"
30
31 static /*@notnull@*/ stateClauseList stateClauseList_new (void)
32 {
33   stateClauseList s = (stateClauseList) dmalloc (sizeof (*s));
34   
35   s->nelements = 0;
36   s->nspace = stateClauseListBASESIZE;
37   s->elements = (stateClause *) 
38     dmalloc (sizeof (*s->elements) * stateClauseListBASESIZE);
39
40   return (s);
41 }
42
43 static void
44 stateClauseList_grow (stateClauseList s)
45 {
46   int i;
47   stateClause *newelements;
48
49   llassert (stateClauseList_isDefined (s));
50
51   s->nspace += stateClauseListBASESIZE; 
52   
53   newelements = (stateClause *) 
54     dmalloc (sizeof (*newelements) * (s->nelements + s->nspace));
55   
56   for (i = 0; i < s->nelements; i++)
57     {
58       newelements[i] = s->elements[i];
59     }
60   
61   sfree (s->elements);
62   s->elements = newelements;
63 }
64
65 stateClauseList stateClauseList_add (stateClauseList s, stateClause el)
66 {
67   DPRINTF (("Adding: %s", stateClause_unparse (el)));
68
69   if (stateClauseList_isUndefined (s))
70     {
71       s = stateClauseList_new ();
72     }
73   else
74     {
75       stateClauseList_elements (s, cl)
76         {
77           if (stateClause_sameKind (cl, el))
78             {
79               voptgenerror
80                 (FLG_SYNTAX,
81                  message ("Multiple %q clauses for one function (ignoring second)",
82                           stateClause_unparseKind (cl)),
83                  g_currentloc);
84
85               stateClause_free (el);
86               return s;
87             }
88         } end_stateClauseList_elements ;
89     }
90
91   if (s->nspace <= 0)
92     {
93       stateClauseList_grow (s);
94     }
95   
96   s->nspace--;
97   s->elements[s->nelements] = el;
98   s->nelements++;
99
100   return s;
101 }
102
103 cstring stateClauseList_unparse (stateClauseList s)
104 {
105   cstring st = cstring_undefined;
106   int i;
107   
108   if (stateClauseList_isDefined (s))
109     {
110       for (i = 0; i < stateClauseList_size (s); i++)
111         {
112           if (i == 0)
113             {
114               st = message ("%q;", stateClause_unparse (s->elements[i]));
115             }
116           else
117             st = message ("%q %q;", st, stateClause_unparse (s->elements[i]));
118         }
119     }
120   
121   return (st);
122 }
123
124 stateClauseList stateClauseList_copy (stateClauseList s)
125 {
126   if (stateClauseList_isDefined (s))
127     {
128       stateClauseList t = (stateClauseList) dmalloc (sizeof (*t));
129       int i;
130       
131       t->nelements = s->nelements;
132       t->nspace = 0;
133       
134       if (s->nelements > 0)
135         {
136           t->elements = (stateClause *) dmalloc (sizeof (*t->elements) * t->nelements);
137           for (i = 0; i < s->nelements; i++) 
138             {
139               t->elements[i] = stateClause_copy (s->elements[i]); 
140             }
141         }
142       else
143         {
144           t->elements = NULL;
145         }
146
147       return t;
148     }
149   else
150     {
151       return stateClauseList_undefined;
152     }
153 }
154
155 void
156 stateClauseList_free (stateClauseList s)
157 {
158   if (!stateClauseList_isUndefined (s)) 
159     {
160       int i;
161
162       for (i = 0; i < s->nelements; i++)
163         {
164           stateClause_free (s->elements[i]);  
165         }
166
167       sfree (s->elements);
168       sfree (s);
169     }
170 }
171
172 cstring stateClauseList_dump (stateClauseList s)
173 {
174   cstring st = cstring_undefined;
175
176   if (stateClauseList_isUndefined (s)) return st;
177   
178   stateClauseList_elements (s, current)
179     {
180       st = message ("%q%q$", st, stateClause_dump (current));
181     } end_stateClauseList_elements;
182
183   return st;
184 }
185
186 stateClauseList stateClauseList_undump (char **s)
187 {
188   char c;
189   stateClauseList pn = stateClauseList_new ();
190   int paramno = 0;
191
192   c = **s;
193
194   while (c != '#' && c != '@')
195     {
196       stateClause sc = stateClause_undump (s);
197       
198       pn = stateClauseList_add (pn, sc);
199       reader_checkChar (s, '$');
200       c = **s;
201       paramno++;
202     }
203
204   return pn;
205 }
206
207 int stateClauseList_compare (stateClauseList s1, stateClauseList s2)
208 {
209   if (stateClauseList_isUndefined (s1)
210       && stateClauseList_isUndefined (s2))
211     {
212       return 0;
213     }
214   else
215     {
216       if ((int) s1 > (int) s2) 
217         {
218           return 1;
219         }
220       else
221         {
222           return -1;
223         }
224     }
225 }
226   
227 static /*@exposed@*/ sRefSet
228 stateClauseList_getClause (stateClauseList s, stateClause k)
229 {
230   stateClauseList_elements (s, el)
231     {
232       if (stateClause_matchKind (el, k))
233         {
234           return stateClause_getRefs (el);
235         }
236     } end_stateClauseList_elements ;
237
238   return sRefSet_undefined;
239 }
240
241 void stateClauseList_checkAll (uentry ue)
242 {
243   stateClauseList clauses = uentry_getStateClauseList (ue);
244   sRef res = uentry_getSref (ue);                 
245   bool specialResult = FALSE;
246
247   DPRINTF (("Check state clauses: %s", uentry_unparseFull (ue)));
248
249   stateClauseList_elements (clauses, cl)
250     {
251       bool isPre = stateClause_isBeforeOnly (cl);
252
253       if (stateClause_isGlobal (cl))
254         {
255           /*@i232@*/
256         }
257       else
258         {
259           sRefSet refs = stateClause_getRefs (cl);
260           
261           sRefSet_allElements (refs, el)
262             {
263               sRef rb = sRef_getRootBase (el);
264
265               DPRINTF (("Check: %s", sRef_unparse (el)));
266               
267               if (stateClause_setsMetaState (cl))
268                 {
269                   qual q = stateClause_getMetaQual (cl);
270                   annotationInfo qa = qual_getAnnotationInfo (q);
271
272                   if (!annotationInfo_matchesContextRef (qa, el))
273                     {
274                       if (optgenerror
275                           (FLG_ANNOTATIONERROR,
276                            message ("Meta state anntation %s used on inappropriate reference %q in %q clause of %q: %q",
277                                     qual_unparse (q),
278                                     sRef_unparse (el),
279                                     stateClause_unparseKind (cl),
280                                     uentry_getName (ue),
281                                     stateClause_unparse (cl)),
282                            uentry_whereLast (ue)))
283                         {
284                           /*@i! annotationInfo_showContextError (ainfo, ue); */
285                         }
286                     }
287                 }
288
289               if (sRef_isResult (rb))
290                 {
291                   if (isPre)
292                     {
293                       voptgenerror
294                         (FLG_INCONDEFS,
295                          message ("Function result is used in %q clause of %q "
296                                   "(%q applies to the state before function is "
297                                   "called, so should not use result): %q",
298                                   stateClause_unparseKind (cl),
299                                   uentry_getName (ue),
300                                   stateClause_unparseKind (cl),
301                                   sRef_unparse (el)),
302                          uentry_whereLast (ue));
303                     }
304                   else
305                     {
306                       if (!sRef_isStateSpecial (res))
307                         {
308                           DPRINTF (("Here we are: %s", sRef_unparseFull (res)));
309
310                           if (!specialResult)
311                             {
312                               sstate pstate = sRef_getDefState (res);
313                               
314                               if (!sRef_makeStateSpecial (res))
315                                 {
316                                   if (optgenerror
317                                       (FLG_INCONDEFS,
318                                        message ("Function result is used in %q clause of %q "
319                                                 "but was previously annotated with %s: %q",
320                                                 stateClause_unparseKind (cl),
321                                                 uentry_getName (ue),
322                                                 sstate_unparse (pstate),
323                                                 sRef_unparse (el)),
324                                        uentry_whereLast (ue)))
325                                     {
326                                       specialResult = TRUE;
327                                     }
328                                 }                             
329                             }
330                         }
331                       
332                       DPRINTF (("Fixing result type! %s", sRef_unparseFull (el)));
333                       (void) sRef_fixResultType (el, sRef_getType (res), ue);
334                     }
335                 }
336               else if (sRef_isParam (rb))
337                 {
338                   DPRINTF (("Make special: %s", sRef_unparseFull (rb)));
339                   
340                   if (!sRef_makeStateSpecial (rb))
341                     {
342                       if (fileloc_isXHFile (uentry_whereLast (ue)))
343                         {
344                           ; /* Okay to override in .xh files */
345                         }
346                       else
347                         {
348                           voptgenerror 
349                             (FLG_INCONDEFS,
350                              message ("Reference %q used in %q clause of %q, "
351                                       "but was previously annotated with %s: %q",
352                                       sRef_unparse (rb),
353                                       stateClause_unparseKind (cl),
354                                       uentry_getName (ue),
355                                       sstate_unparse (sRef_getDefState (res)),
356                                       sRef_unparse (el)),
357                              uentry_whereLast (ue));
358                         }
359                     }
360                   
361                   DPRINTF (("Made special: %s", sRef_unparseFull (rb)));
362                 }
363               else if (sRef_isInvalid (rb))
364                 {
365                   /*@innercontinue@*/ continue;
366                 }
367               else 
368                 {
369                   BADBRANCHCONT;
370                   /*@innercontinue@*/ continue;
371                 }
372               
373               if (stateClause_isMemoryAllocation (cl))
374                 {
375                   if (!ctype_isVisiblySharable (sRef_getType (el)))
376                     {
377                       voptgenerror
378                         (FLG_ANNOTATIONERROR,
379                          /*@-sefparams@*/ /* This is okay because its fresh storage. */ /*@i32@*/
380                          message 
381                          ("%q clauses includes %q of "
382                           "non-dynamically allocated type %s",
383                           cstring_capitalizeFree (stateClause_unparseKind (cl)),
384                           sRef_unparse (el), 
385                           ctype_unparse (sRef_getType (el))),
386                          uentry_whereLast (ue));
387                       /*@=sefparams@*/
388                     }
389                 }
390               
391             } end_sRefSet_allElements ;
392         }
393     } end_stateClauseList_elements ;
394 }
395   
396 void stateClauseList_checkEqual (uentry old, uentry unew)
397 {
398   stateClauseList oldClauses = uentry_getStateClauseList (old);
399   stateClauseList newClauses = uentry_getStateClauseList (unew);
400
401   if (stateClauseList_isDefined (newClauses))
402     {
403       stateClauseList_elements (newClauses, cl)
404         {
405           if (stateClause_isGlobal (cl))
406             {
407               ;
408             }
409           else
410             {
411               sRefSet sc = stateClauseList_getClause (oldClauses, cl);
412               
413               if (!sRefSet_equal (sc, stateClause_getRefs (cl)))
414                 {
415                   if (optgenerror
416                       (FLG_INCONDEFS,
417                        message ("Function %q %rdeclared with inconsistent %q clause: %q",
418                                 uentry_getName (old),
419                                 uentry_isDeclared (old),
420                                 stateClause_unparseKind (cl),
421                                 sRefSet_unparsePlain (stateClause_getRefs (cl))),
422                        g_currentloc))
423                     {
424                       uentry_showWhereLastExtra (old, sRefSet_unparsePlain (sc));
425                     }
426                 }
427             }
428         } end_stateClauseList_elements ;
429         
430       stateClauseList_elements (oldClauses, cl)
431         {
432           if (stateClause_isGlobal (cl))
433             {
434               ; /*@i32@*/ 
435             }
436           else
437             {
438               sRefSet sc = stateClauseList_getClause (newClauses, cl);
439               
440               if (sRefSet_isUndefined (sc) && !sRefSet_isEmpty (stateClause_getRefs (cl)))
441                 {
442                   if (optgenerror
443                       (FLG_INCONDEFS,
444                        message ("Function %q %rdeclared without %q clause (either "
445                                 "use no special clauses in redeclaration, or "
446                                 "they must match exactly: %q",
447                                 uentry_getName (old),
448                                 uentry_isDeclared (old),
449                                 stateClause_unparseKind (cl),
450                                 sRefSet_unparsePlain (stateClause_getRefs (cl))),
451                        g_currentloc))
452                     {
453                       uentry_showWhereLastExtra (old, sRefSet_unparsePlain (sc));
454                     }
455                 }
456             }
457         } end_stateClauseList_elements ;
458     }
459 }
460
461
462
This page took 0.105015 seconds and 5 git commands to generate.