]> andersk Git - splint.git/blob - src/stateClauseList.c
Merged code tree with Dave Evans's version. Many changes to numberous to list....
[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                           if (!specialResult)
309                             {
310                               sstate pstate = sRef_getDefState (res);
311                               
312                               if (!sRef_makeStateSpecial (res))
313                                 {
314                                   voptgenerror
315                                     (FLG_INCONDEFS,
316                                      message ("Function result is used in %q clause of %q "
317                                               "but was previously annotated with %s: %q",
318                                               stateClause_unparseKind (cl),
319                                               uentry_getName (ue),
320                                               sstate_unparse (pstate),
321                                               sRef_unparse (el)),
322                                      uentry_whereLast (ue));
323                                 }
324                               
325                               specialResult = TRUE;
326                             }
327                         }
328                       
329                       (void) sRef_fixResultType (el, sRef_getType (res), ue);
330                     }
331                 }
332               else if (sRef_isParam (rb))
333                 {
334                   DPRINTF (("Make special: %s", sRef_unparseFull (rb)));
335                   
336                   if (!sRef_makeStateSpecial (rb))
337                     {
338                       if (fileloc_isXHFile (uentry_whereLast (ue)))
339                         {
340                           ; /* Okay to override in .xh files */
341                         }
342                       else
343                         {
344                           voptgenerror 
345                             (FLG_INCONDEFS,
346                              message ("Reference %q used in %q clause of %q, "
347                                       "but was previously annotated with %s: %q",
348                                       sRef_unparse (rb),
349                                       stateClause_unparseKind (cl),
350                                       uentry_getName (ue),
351                                       sstate_unparse (sRef_getDefState (res)),
352                                       sRef_unparse (el)),
353                              uentry_whereLast (ue));
354                         }
355                     }
356                   
357                   DPRINTF (("Made special: %s", sRef_unparseFull (rb)));
358                 }
359               else if (sRef_isInvalid (rb))
360                 {
361                   /*@innercontinue@*/ continue;
362                 }
363               else 
364                 {
365                   BADBRANCHCONT;
366                   /*@innercontinue@*/ continue;
367                 }
368               
369               if (stateClause_isMemoryAllocation (cl))
370                 {
371                   if (!ctype_isVisiblySharable (sRef_getType (el)))
372                     {
373                       voptgenerror
374                         (FLG_ANNOTATIONERROR,
375                          /*@-sefparams@*/ /* This is okay because its fresh storage. */ /*@i32@*/
376                          message 
377                          ("%q clauses includes %q of "
378                           "non-dynamically allocated type %s",
379                           cstring_capitalizeFree (stateClause_unparseKind (cl)),
380                           sRef_unparse (el), 
381                           ctype_unparse (sRef_getType (el))),
382                          uentry_whereLast (ue));
383                       /*@=sefparams@*/
384                     }
385                 }
386               
387             } end_sRefSet_allElements ;
388         }
389     } end_stateClauseList_elements ;
390 }
391   
392 void stateClauseList_checkEqual (uentry old, uentry unew)
393 {
394   stateClauseList oldClauses = uentry_getStateClauseList (old);
395   stateClauseList newClauses = uentry_getStateClauseList (unew);
396
397   if (stateClauseList_isDefined (newClauses))
398     {
399       stateClauseList_elements (newClauses, cl)
400         {
401           if (stateClause_isGlobal (cl))
402             {
403               ;
404             }
405           else
406             {
407               sRefSet sc = stateClauseList_getClause (oldClauses, cl);
408               
409               if (!sRefSet_equal (sc, stateClause_getRefs (cl)))
410                 {
411                   if (optgenerror
412                       (FLG_INCONDEFS,
413                        message ("Function %q %rdeclared with inconsistent %q clause: %q",
414                                 uentry_getName (old),
415                                 uentry_isDeclared (old),
416                                 stateClause_unparseKind (cl),
417                                 sRefSet_unparsePlain (stateClause_getRefs (cl))),
418                        g_currentloc))
419                     {
420                       uentry_showWhereLastExtra (old, sRefSet_unparsePlain (sc));
421                     }
422                 }
423             }
424         } end_stateClauseList_elements ;
425         
426       stateClauseList_elements (oldClauses, cl)
427         {
428           if (stateClause_isGlobal (cl))
429             {
430               ; /*@i32@*/ 
431             }
432           else
433             {
434               sRefSet sc = stateClauseList_getClause (newClauses, cl);
435               
436               if (sRefSet_isUndefined (sc) && !sRefSet_isEmpty (stateClause_getRefs (cl)))
437                 {
438                   if (optgenerror
439                       (FLG_INCONDEFS,
440                        message ("Function %q %rdeclared without %q clause (either "
441                                 "use no special clauses in redeclaration, or "
442                                 "they must match exactly: %q",
443                                 uentry_getName (old),
444                                 uentry_isDeclared (old),
445                                 stateClause_unparseKind (cl),
446                                 sRefSet_unparsePlain (stateClause_getRefs (cl))),
447                        g_currentloc))
448                     {
449                       uentry_showWhereLastExtra (old, sRefSet_unparsePlain (sc));
450                     }
451                 }
452             }
453         } end_stateClauseList_elements ;
454     }
455 }
456
457
458
This page took 0.457563 seconds and 5 git commands to generate.