]> andersk Git - splint.git/blob - src/constraint.c
Fixes after removing -unrecogcomments flag for make splintme.
[splint.git] / src / constraint.c
1 /*
2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 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 splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
23 */
24
25 /*
26 ** constraint.c
27 */
28
29 /* #define DEBUGPRINT 1 */
30
31 # include "splintMacros.nf"
32 # include "basic.h"
33 # include "cgrammar.h"
34 # include "cgrammar_tokens.h"
35 # include "exprChecks.h"
36 # include "exprNodeSList.h"
37
38 static /*@only@*/ cstring 
39 constraint_unparseDetailedPostCondition (/*@observer@*/ /*@temp@*/ constraint p_c);
40
41 static /*@notnull@*/ /*@special@*/ constraint constraint_makeNew (void)
42      /*@post:isnull result->or, result->orig,  result->generatingExpr, result->fcnPre @*/
43      /*@defines result->or, result->generatingExpr, result->orig, result->fcnPre @*/;
44      
45 static void
46 advanceField (char **s)
47 {
48   reader_checkChar (s, '@');
49 }
50
51 bool constraint_same (constraint c1, constraint c2)
52 {
53   llassert (c1 != NULL);
54   llassert (c2 != NULL);
55
56   if (c1->ar != c2->ar)
57     {
58       return FALSE;
59     }
60   
61   if (!constraintExpr_similar (c1->lexpr, c2->lexpr))
62     {
63       return FALSE;
64     }
65
66   if (!constraintExpr_similar (c1->expr, c2->expr))
67     {
68       return FALSE;
69     }
70
71   return TRUE;
72 }
73
74 constraint makeConstraintParse3 (constraintExpr l, lltok relOp, constraintExpr r)     
75 {
76   constraint ret;
77   ret = constraint_makeNew ();
78   llassert (constraintExpr_isDefined (l));
79     
80   ret->lexpr = constraintExpr_copy (l);
81
82   if (lltok_getTok (relOp) == GE_OP)
83     {
84       ret->ar = GTE;
85     }
86   else if (lltok_getTok (relOp) == LE_OP)
87     {
88       ret->ar = LTE;
89     }
90   else if (lltok_getTok (relOp) == EQ_OP)
91     {
92       ret->ar = EQ;
93     }
94   else
95     llfatalbug ( message ("Unsupported relational operator"));
96
97   ret->expr = constraintExpr_copy (r);
98
99   ret->post = TRUE;
100
101   ret->orig = constraint_copy (ret);
102
103   ret = constraint_simplify (ret);
104   /* ret->orig = ret; */
105
106   DPRINTF (("GENERATED CONSTRAINT:"));
107   DPRINTF ((message ("%s", constraint_unparse (ret))));
108   return ret;
109 }
110
111 constraint constraint_copy (/*@temp@*/ /*@observer@*/ constraint c)
112 {
113   constraint ret;
114
115   llassert (constraint_isDefined (c));
116
117   ret = constraint_makeNew ();
118   ret->lexpr = constraintExpr_copy (c->lexpr);
119   ret->ar = c->ar;
120   ret->expr =  constraintExpr_copy (c->expr);
121   ret->post = c->post;
122   /*@-assignexpose@*/
123   ret->generatingExpr = c->generatingExpr;
124   /*@=assignexpose@*/
125   
126   if (c->orig != NULL)
127     ret->orig = constraint_copy (c->orig);
128   else
129     ret->orig = NULL;
130
131   if (c->or != NULL)
132     ret->or = constraint_copy (c->or);
133   else
134     ret->or = NULL;
135
136   ret->fcnPre = c->fcnPre;
137   
138   return ret;
139 }
140
141 /*like copy except it doesn't allocate memory for the constraint*/
142
143 void constraint_overWrite (constraint c1, constraint c2) 
144 {
145   llassert (constraint_isDefined (c1) && constraint_isDefined (c2));
146
147   llassert (c1 != c2);
148
149   DPRINTF ((message ("OverWriteing constraint %q with %q", constraint_unparse (c1),
150                    constraint_unparse (c2))));
151   
152   constraintExpr_free (c1->lexpr);
153   constraintExpr_free (c1->expr);
154   
155   c1->lexpr = constraintExpr_copy (c2->lexpr);
156   c1->ar = c2->ar;
157   c1->expr =  constraintExpr_copy (c2->expr);
158   c1->post = c2->post;
159
160   if (c1->orig != NULL)
161     constraint_free (c1->orig);
162
163   if (c2->orig != NULL)
164     c1->orig = constraint_copy (c2->orig);
165   else
166     c1->orig = NULL;
167
168   if (c1->or != NULL)
169     constraint_free (c1->or);
170
171   if (c2->or != NULL)
172     c1->or = constraint_copy (c2->or);
173   else
174     c1->or = NULL;
175
176   c1->fcnPre = c2->fcnPre;
177
178   /*@-assignexpose@*/
179   c1->generatingExpr = c2->generatingExpr;
180   /*@=assignexpose@*/
181 }
182
183
184
185 static /*@notnull@*/  /*@special@*/ constraint constraint_makeNew (void)
186      /*@post:isnull result->or, result->orig,  result->generatingExpr, result->fcnPre @*/ 
187      /*@defines result->or, result->generatingExpr, result->orig, result->fcnPre @*/
188 {
189   constraint ret;
190   ret = dmalloc (sizeof (*ret));
191   ret->lexpr = NULL;
192   ret->expr = NULL;
193   ret->ar = LT;
194   ret->post = FALSE;
195   ret->orig = NULL;
196   ret->or = NULL;
197   ret->generatingExpr = NULL;
198   ret->fcnPre = NULL;
199   return ret;
200 }
201
202 /*@access exprNode@*/ 
203
204 constraint constraint_addGeneratingExpr (/*@returned@*/ constraint c, /*@exposed@*/ exprNode e)
205 {
206   
207   llassert (constraint_isDefined (c) );
208   
209   if (c->generatingExpr == NULL)
210     {
211       c->generatingExpr = e;
212       DPRINTF ((message ("setting generatingExpr for %s to %s", constraint_unparse (c), exprNode_unparse (e)) ));
213     }
214   else
215     {
216       DPRINTF ((message ("Not setting generatingExpr for %s to %s", constraint_unparse (c), exprNode_unparse (e)) ));
217     }
218   return c;
219 }
220 /*@noaccess exprNode@*/ 
221
222 constraint constraint_origAddGeneratingExpr (/*@returned@*/ constraint c, exprNode e)
223 {
224   llassert (constraint_isDefined (c) );
225  
226   if (c->orig != constraint_undefined)
227     {
228       c->orig = constraint_addGeneratingExpr (c->orig, e);
229     }
230   else
231     {
232       DPRINTF ((message ("constraint_origAddGeneratingExpr: Not setting generatingExpr for %s to %s", constraint_unparse (c), exprNode_unparse (e)) ));
233     }
234   return c;
235 }
236
237 constraint constraint_setFcnPre (/*@returned@*/ constraint c)
238 {
239
240   llassert (constraint_isDefined (c) );
241  
242   if (c->orig != constraint_undefined)
243     {
244       c->orig->fcnPre = TRUE;
245     }
246   else
247     {
248       c->fcnPre = TRUE;
249       DPRINTF (( message ("Warning Setting fcnPre directly")));
250     }
251   return c;
252 }
253
254
255
256
257 fileloc constraint_getFileloc (constraint c)
258 {
259   llassert (constraint_isDefined (c) );
260  
261   if (exprNode_isDefined (c->generatingExpr))
262     return (fileloc_copy (exprNode_loc (c->generatingExpr)));
263   
264   return (constraintExpr_getFileloc (c->lexpr));
265 }
266
267 static bool checkForMaxSet (constraint c)
268 {  
269   llassert (constraint_isDefined (c));
270   return (constraintExpr_hasMaxSet (c->lexpr) || constraintExpr_hasMaxSet (c->expr));
271 }
272
273 bool constraint_hasMaxSet (constraint c)
274 {
275   llassert (constraint_isDefined (c) );
276  
277   if (checkForMaxSet (c))
278     return TRUE;
279   
280   if (c->orig != NULL)
281     {
282       if (checkForMaxSet (c->orig))
283         return TRUE;
284     }
285
286   return FALSE;
287 }
288
289 constraint constraint_makeReadSafeExprNode (exprNode po, exprNode ind)
290 {
291   constraint ret = constraint_makeNew ();
292
293   po = po;
294   ind = ind;
295   ret->lexpr = constraintExpr_makeMaxReadExpr (po);
296   ret->ar = GTE;
297   ret->expr = constraintExpr_makeValueExpr (ind);
298   ret->post = FALSE;
299   return ret;
300 }
301
302 constraint constraint_makeWriteSafeInt (exprNode po, int ind)
303 {
304   constraint ret = constraint_makeNew ();
305   ret->lexpr =constraintExpr_makeMaxSetExpr (po);
306   ret->ar = GTE;
307   ret->expr =  constraintExpr_makeIntLiteral (ind);
308   /*@i1*/ return ret;
309 }
310
311 constraint constraint_makeSRefSetBufferSize (sRef s, long int size)
312 {
313   constraint ret = constraint_makeNew ();
314   ret->lexpr = constraintExpr_makeSRefMaxset (s);
315   ret->ar = EQ;
316   ret->expr =  constraintExpr_makeIntLiteral ((int)size);
317   ret->post = TRUE;
318   return ret;
319 }
320
321 constraint constraint_makeSRefWriteSafeInt (sRef s, int ind)
322 {
323   constraint ret = constraint_makeNew ();
324   ret->lexpr = constraintExpr_makeSRefMaxset ( s);
325   ret->ar = GTE;
326   ret->expr = constraintExpr_makeIntLiteral (ind);
327   ret->post = TRUE;
328   return ret;
329 }
330
331 /* drl added 01/12/2000
332 ** makes the constraint: Ensures index <= MaxRead (buffer) 
333 */
334
335 constraint constraint_makeEnsureLteMaxRead (exprNode index, exprNode buffer)
336 {
337   constraint ret = constraint_makeNew ();
338
339   ret->lexpr = constraintExpr_makeValueExpr (index);
340   ret->ar = LTE;
341   ret->expr = constraintExpr_makeMaxReadExpr (buffer);
342   ret->post = TRUE;
343   return ret;
344 }
345
346 constraint constraint_makeWriteSafeExprNode (exprNode po, exprNode ind)
347 {
348   constraint ret = constraint_makeNew ();
349  
350   ret->lexpr =constraintExpr_makeMaxSetExpr (po);
351   ret->ar = GTE;
352   ret->expr =  constraintExpr_makeValueExpr (ind);
353   /*@i1*/return ret;
354 }
355
356
357 constraint constraint_makeReadSafeInt (exprNode t1, int index)
358 {
359   constraint ret = constraint_makeNew ();
360
361   ret->lexpr = constraintExpr_makeMaxReadExpr (t1);
362   ret->ar = GTE;
363   ret->expr = constraintExpr_makeIntLiteral (index);
364   ret->post = FALSE;
365   return ret;
366 }
367
368 constraint constraint_makeSRefReadSafeInt (sRef s, int ind)
369 {
370   constraint ret = constraint_makeNew ();
371   
372   ret->lexpr = constraintExpr_makeSRefMaxRead (s);
373   ret->ar = GTE;
374   ret->expr =  constraintExpr_makeIntLiteral (ind);
375   ret->post = TRUE;
376   return ret;
377 }
378
379 constraint constraint_makeEnsureMaxReadAtLeast (exprNode t1, exprNode t2, fileloc sequencePoint)
380 {
381   constraint ret = constraint_makeReadSafeExprNode (t1, t2);   
382   llassert (constraint_isDefined (ret));
383  
384   ret->lexpr = constraintExpr_setFileloc (ret->lexpr, sequencePoint);  
385   ret->post = TRUE;  
386
387   return ret;
388 }
389
390 static constraint 
391 constraint_makeEnsuresOpConstraintExpr (/*@only@*/ constraintExpr c1, /*@only@*/ constraintExpr c2, 
392                                         fileloc sequencePoint, arithType ar)
393 {
394   constraint ret = constraint_makeNew ();
395   llassert (constraintExpr_isDefined (c1) && constraintExpr_isDefined (c2));
396   ret->lexpr = c1;
397   ret->ar = ar;
398   ret->post = TRUE;
399   ret->expr = c2;
400   ret->lexpr = constraintExpr_setFileloc (ret->lexpr, sequencePoint);
401   return ret;
402 }
403
404 static constraint 
405 constraint_makeEnsuresOp (/*@dependent@*/ exprNode e1, /*@dependent@*/ exprNode e2, 
406                           fileloc sequencePoint, arithType ar)
407 {
408   constraintExpr c1, c2;
409   
410   if (!(exprNode_isDefined (e1) && exprNode_isDefined (e2)))
411     {
412       llcontbug (message ("Invalid exprNode, Exprnodes are %s and %s",
413                           exprNode_unparse (e1), exprNode_unparse (e2)));
414     }
415   
416   c1 = constraintExpr_makeValueExpr (e1);
417   c2 = constraintExpr_makeValueExpr (e2);
418
419   return constraint_makeEnsuresOpConstraintExpr (c1, c2, sequencePoint, ar);
420 }
421
422 /* make constraint ensures e1 == e2 */
423
424 constraint constraint_makeEnsureEqual (exprNode e1, exprNode e2, fileloc sequencePoint)
425 {
426   return (constraint_makeEnsuresOp (e1, e2, sequencePoint, EQ));
427 }
428
429 /* make constraint ensures e1 < e2 */
430 constraint constraint_makeEnsureLessThan (exprNode e1, exprNode e2, fileloc sequencePoint)
431 {
432   constraintExpr t1, t2;
433   constraint t3;
434
435   t1 = constraintExpr_makeValueExpr (e1);
436   t2 = constraintExpr_makeValueExpr (e2);
437
438   /* change this to e1 <= (e2 -1) */
439
440   t2 = constraintExpr_makeDecConstraintExpr (t2);
441   t3 = constraint_makeEnsuresOpConstraintExpr (t1, t2, sequencePoint, LTE);
442   t3 = constraint_simplify (t3);
443   return (t3);
444 }
445
446 constraint constraint_makeEnsureLessThanEqual (exprNode e1, exprNode e2, fileloc sequencePoint)
447 {
448   return (constraint_makeEnsuresOp (e1, e2, sequencePoint, LTE));
449 }
450
451 constraint constraint_makeEnsureGreaterThan (exprNode e1, exprNode e2, fileloc sequencePoint)
452 {
453   constraintExpr t1, t2;
454   constraint t3;
455
456   t1 = constraintExpr_makeValueExpr (e1);
457   t2 = constraintExpr_makeValueExpr (e2);
458
459   /* change this to e1 >= (e2 + 1) */
460   t2 = constraintExpr_makeIncConstraintExpr (t2);
461   
462   t3 =  constraint_makeEnsuresOpConstraintExpr (t1, t2, sequencePoint, GTE);
463   t3 = constraint_simplify(t3);
464   
465   return t3;
466 }
467
468 constraint constraint_makeEnsureGreaterThanEqual (exprNode e1, exprNode e2, fileloc sequencePoint)
469 {
470  return ( constraint_makeEnsuresOp (e1, e2, sequencePoint, GTE));
471 }
472
473
474
475 /* Makes the constraint e = e + f */
476 constraint constraint_makeAddAssign (exprNode e, exprNode f, fileloc sequencePoint)
477 {
478   constraintExpr x1, x2, y;
479   constraint ret;
480
481   ret = constraint_makeNew ();
482
483   x1 =  constraintExpr_makeValueExpr (e);
484   x2 =  constraintExpr_copy (x1);
485   y  =  constraintExpr_makeValueExpr (f);
486
487   ret->lexpr = x1;
488   ret->ar = EQ;
489   ret->post = TRUE;
490   ret->expr = constraintExpr_makeAddExpr (x2, y);
491   
492   ret->lexpr = constraintExpr_setFileloc (ret->lexpr, sequencePoint);
493
494   return ret;
495 }
496
497
498 /* Makes the constraint e = e - f */
499 constraint constraint_makeSubtractAssign (exprNode e, exprNode f, fileloc sequencePoint)
500 {
501   constraintExpr x1, x2, y;
502   constraint ret;
503
504   ret = constraint_makeNew ();
505
506   x1 =  constraintExpr_makeValueExpr (e);
507   x2 =  constraintExpr_copy (x1);
508   y  =  constraintExpr_makeValueExpr (f);
509
510   ret->lexpr = x1;
511   ret->ar = EQ;
512   ret->post = TRUE;
513   ret->expr = constraintExpr_makeSubtractExpr (x2, y);
514   
515   ret->lexpr = constraintExpr_setFileloc (ret->lexpr, sequencePoint);
516
517   return ret;
518 }
519
520 constraint constraint_makeMaxSetSideEffectPostDecrement (exprNode e, fileloc sequencePoint)
521 {
522   constraint ret = constraint_makeNew ();
523
524   ret->lexpr = constraintExpr_makeValueExpr (e);
525   ret->ar = EQ;
526   ret->post = TRUE;
527   ret->expr =  constraintExpr_makeValueExpr (e);
528   ret->expr =  constraintExpr_makeDecConstraintExpr (ret->expr);
529   ret->lexpr = constraintExpr_setFileloc (ret->lexpr, sequencePoint);
530   return ret;
531 }
532 constraint constraint_makeMaxSetSideEffectPostIncrement (exprNode e, fileloc sequencePoint)
533 {
534   constraint ret = constraint_makeNew ();
535
536   ret->lexpr = constraintExpr_makeValueExpr (e);
537   ret->ar = EQ;
538   ret->post = TRUE;
539   ret->expr =  constraintExpr_makeValueExpr (e);
540   ret->expr =  constraintExpr_makeIncConstraintExpr (ret->expr);
541
542   ret->lexpr = constraintExpr_setFileloc (ret->lexpr, sequencePoint);
543   return ret;
544 }
545
546
547 void constraint_free (/*@only@*/ constraint c)
548 {
549   llassert (constraint_isDefined (c));
550
551
552   if (constraint_isDefined (c->orig))
553     constraint_free (c->orig);
554   if ( constraint_isDefined (c->or))
555     constraint_free (c->or);
556
557   
558   constraintExpr_free (c->lexpr);
559   constraintExpr_free (c->expr);
560
561   c->orig = NULL;
562   c->or = NULL;
563   c->lexpr = NULL;
564   c->expr  = NULL;
565
566   free (c);
567   
568 }
569
570 cstring arithType_print (arithType ar) /*@*/
571 {
572   cstring st = cstring_undefined;
573   switch (ar)
574     {
575     case LT:
576       st = cstring_makeLiteral ("<");
577       break;
578     case        LTE:
579       st = cstring_makeLiteral ("<=");
580       break;
581     case        GT:
582       st = cstring_makeLiteral (">");
583       break;
584     case        GTE:
585       st = cstring_makeLiteral (">=");
586       break;
587     case        EQ:
588       st = cstring_makeLiteral ("==");
589       break;
590     case        NONNEGATIVE:
591       st = cstring_makeLiteral ("NONNEGATIVE");
592       break;
593     case        POSITIVE:
594       st = cstring_makeLiteral ("POSITIVE");
595       break;
596     default:
597       llassert (FALSE);
598       break;
599     }
600   return st;
601 }
602
603 void constraint_printErrorPostCondition (constraint c, fileloc loc)
604 {
605   cstring string;
606   fileloc errorLoc, temp;
607   
608   string = constraint_unparseDetailedPostCondition (c);
609
610   errorLoc = loc;
611
612   loc = NULL;
613
614   temp = constraint_getFileloc (c);
615
616     
617   if (context_getFlag (FLG_BOUNDSCOMPACTERRORMESSAGES ) )
618     {
619       string = cstring_replaceChar(string, '\n', ' ');
620     }
621   
622   if (fileloc_isDefined (temp))
623     {
624       errorLoc = temp;
625       voptgenerror (  FLG_CHECKPOST, string, errorLoc);
626       fileloc_free (temp);
627     }
628   else
629     {
630       voptgenerror (  FLG_CHECKPOST, string, errorLoc);
631     }
632 }
633
634  /*drl added 8-11-001*/
635 cstring constraint_printLocation (/*@observer@*/ /*@temp@*/ constraint c) /*@*/
636 {
637   cstring string, ret;
638   fileloc errorLoc;
639   
640   string = constraint_unparse (c);
641
642   errorLoc = constraint_getFileloc (c);
643
644   ret = message ("constraint: %q @ %q", string, fileloc_unparse (errorLoc));
645
646   fileloc_free (errorLoc);
647   return ret;
648
649 }
650
651
652
653 void constraint_printError (constraint c, fileloc loc)
654 {
655   cstring string;
656   fileloc errorLoc, temp;
657
658   bool isLikely;
659
660     
661   llassert (constraint_isDefined (c) );
662  
663   /*drl 11/26/2001 avoid printing tautological constraints */
664   if (constraint_isAlwaysTrue (c))
665     {
666       return;
667     }
668
669
670   string = constraint_unparseDetailed (c);
671
672   errorLoc = loc;
673
674   temp = constraint_getFileloc (c);
675
676   if (fileloc_isDefined (temp))
677     {
678       errorLoc = temp;
679     }
680   else
681     {
682       llassert (FALSE);
683       DPRINTF (("constraint %s had undefined fileloc %s", constraint_unparse (c), fileloc_unparse (temp)));
684       fileloc_free (temp);
685       errorLoc = fileloc_copy (errorLoc);
686     }
687
688   
689   if (context_getFlag (FLG_BOUNDSCOMPACTERRORMESSAGES ) )
690     {
691       string = cstring_replaceChar(string, '\n', ' ');
692     }
693
694   /*drl added 12/19/2002 print
695     a different error fro "likely" bounds-errors*/
696   
697   isLikely = constraint_isConstantOnly(c);
698
699   if (isLikely)
700     {
701       if (c->post)
702         {
703           voptgenerror (FLG_FUNCTIONPOST, string, errorLoc);
704         }
705       else
706         {
707           if (constraint_hasMaxSet (c))
708             {
709               voptgenerror (FLG_LIKELYBOUNDSWRITE, string, errorLoc);
710             }
711           else
712             {
713               voptgenerror (FLG_LIKELYBOUNDSREAD, string, errorLoc);
714             }
715         }
716     }
717   else if (c->post)
718     {
719       voptgenerror (FLG_FUNCTIONPOST, string, errorLoc);
720     }
721   else
722     {
723       if (constraint_hasMaxSet (c))
724         {
725           voptgenerror (FLG_BOUNDSWRITE, string, errorLoc);
726         }
727       else
728         {
729           voptgenerror (FLG_BOUNDSREAD, string, errorLoc);
730         }
731     }
732
733   fileloc_free(errorLoc);
734 }
735
736 static cstring constraint_unparseDeep (constraint c)
737 {
738   cstring genExpr;
739   cstring st;
740
741   llassert (constraint_isDefined (c));
742   st = constraint_unparse (c);
743   
744   if (c->orig != constraint_undefined)
745     {
746       st = cstring_appendChar (st, '\n');
747       genExpr =  exprNode_unparse (c->orig->generatingExpr);
748
749       if (!c->post)
750         {
751           if (c->orig->fcnPre)
752             {
753               st = cstring_concatFree (st, message (" derived from %s precondition: %q", 
754                                                     genExpr, constraint_unparseDeep (c->orig)));
755             }
756           else
757             {
758               st = cstring_concatFree (st, message (" needed to satisfy precondition:\n%q",
759                                                     constraint_unparseDeep (c->orig)));
760             }
761         }
762       else
763         {
764           st = cstring_concatFree (st, message ("derived from: %q",
765                                                constraint_unparseDeep (c->orig)));
766         }
767     }
768
769   return st;  
770 }
771
772
773 static /*@only@*/ cstring  constraint_unparseDetailedPostCondition (/*@observer@*/ /*@temp@*/ constraint c)
774 {
775   cstring st = cstring_undefined;
776   cstring genExpr;
777      
778   llassert (constraint_isDefined (c) );
779  
780   st = message ("Unsatisfied ensures constraint condition:\nSplint is unable to verify the constraint %q",
781                 constraint_unparseDeep (c));
782
783   genExpr = exprNode_unparse (c->generatingExpr);
784     
785   if (context_getFlag (FLG_CONSTRAINTLOCATION))
786     {
787       cstring temp;
788
789       temp = message ("\nOriginal Generating expression %q: %s\n", 
790                       fileloc_unparse (exprNode_loc (c->generatingExpr)),
791                       genExpr);
792       st = cstring_concatFree (st, temp);
793
794       if (constraint_hasMaxSet (c))
795         {
796           temp = message ("Has MaxSet\n");
797           st = cstring_concatFree (st, temp);
798         }
799     }
800   return st;
801 }
802
803 cstring  constraint_unparseDetailed (constraint c)
804 {
805   cstring st = cstring_undefined;
806   cstring temp = cstring_undefined;
807   cstring genExpr;
808   bool isLikely;
809    
810   llassert (constraint_isDefined (c) );
811    
812   if (!c->post)
813     {
814       st = message ("Unable to resolve constraint:\n%q", constraint_unparseDeep (c));
815     }
816   else
817     {
818       st = message ("Block Post condition:\nThis function block has the post condition %q", constraint_unparseDeep (c));
819     }
820
821   isLikely = constraint_isConstantOnly(c);
822
823   if (isLikely)
824     {
825       if (constraint_hasMaxSet (c))
826         {
827           temp = cstring_makeLiteral ("Likely out-of-bounds store:\n");
828         }
829       else
830         {
831           temp = cstring_makeLiteral ("Likely out-of-bounds read:\n");
832         }
833     }
834   else
835     {
836       
837       if (constraint_hasMaxSet (c))
838         {
839           temp = cstring_makeLiteral ("Possible out-of-bounds store:\n");
840         }
841       else
842         {
843           temp = cstring_makeLiteral ("Possible out-of-bounds read:\n");
844         }
845     }
846   
847   genExpr = exprNode_unparse (c->generatingExpr);
848   
849   if (context_getFlag (FLG_CONSTRAINTLOCATION))
850     {
851       cstring temp2;
852       temp2 = message ("%s\n", genExpr);
853       temp = cstring_concatFree (temp, temp2);
854     }
855
856   st  = cstring_concatFree (temp,st);
857   
858   return st;
859 }
860
861 /*@only@*/ cstring  constraint_unparse (constraint c) /*@*/
862 {
863   cstring st = cstring_undefined;
864   cstring type = cstring_undefined;
865   llassert (c !=NULL);
866   if (c->post)
867     {
868       if (context_getFlag (FLG_PARENCONSTRAINT))
869         {
870           type = cstring_makeLiteral ("ensures: ");
871         }
872       else
873         {
874            type = cstring_makeLiteral ("ensures");
875         }
876     }
877   else
878     {
879       if (context_getFlag (FLG_PARENCONSTRAINT))
880         {
881           type = cstring_makeLiteral ("requires: ");
882         }
883       else
884         {
885           type = cstring_makeLiteral ("requires");
886         }
887         
888     }
889       if (context_getFlag (FLG_PARENCONSTRAINT))
890         {
891           st = message ("%q: %q %q %q",
892                         type,
893                         constraintExpr_print (c->lexpr),
894                         arithType_print (c->ar),
895                         constraintExpr_print (c->expr));
896         }
897       else
898         {
899           st = message ("%q %q %q %q",
900                         type,
901                         constraintExpr_print (c->lexpr),
902                         arithType_print (c->ar),
903                         constraintExpr_print (c->expr));
904         }
905   return st;
906 }
907
908 cstring  constraint_unparseOr (constraint c) /*@*/
909 {
910   cstring ret;
911   constraint temp;
912
913   ret = cstring_undefined;
914      
915   llassert (constraint_isDefined (c) );
916  
917   temp = c;
918
919   ret = cstring_concatFree (ret, constraint_unparse (temp));
920
921   temp = temp->or;
922   
923   while ( constraint_isDefined (temp)) 
924     {
925       ret = cstring_concatFree (ret, cstring_makeLiteral (" OR "));
926       ret = cstring_concatFree (ret, constraint_unparse (temp));
927       temp = temp->or;
928     }
929
930   return ret;
931
932 }
933
934 /*@only@*/ constraint constraint_doSRefFixBaseParam (/*@returned@*/ /*@only@*/ constraint precondition,
935                                                    exprNodeList arglist)
936 {
937    
938   llassert (constraint_isDefined (precondition) );
939  
940   precondition->lexpr = constraintExpr_doSRefFixBaseParam (precondition->lexpr,
941                                                            arglist);
942   precondition->expr = constraintExpr_doSRefFixBaseParam (precondition->expr,
943                                                            arglist);
944
945   return precondition;
946 }
947
948
949 constraint constraint_doFixResult (constraint postcondition, /*@dependent@*/ exprNode fcnCall)
950 {
951   postcondition = constraint_copy (postcondition);
952
953   llassert (constraint_isDefined (postcondition) );
954  
955   
956   postcondition->lexpr = constraintExpr_doFixResult (postcondition->lexpr, fcnCall);
957   postcondition->expr = constraintExpr_doFixResult (postcondition->expr, fcnCall);
958
959   return postcondition;
960 }
961 /*Commenting out temporally
962   
963 / *@only@* /constraint  constraint_doSRefFixInvarConstraint(constraint invar, sRef s, ctype ct )
964 {
965
966   invar = constraint_copy (invar);
967   invar->lexpr = constraintExpr_doSRefFixInvarConstraint (invar->lexpr, s, ct);
968   invar->expr = constraintExpr_doSRefFixInvarConstraint (invar->expr, s, ct);
969
970   return invar;
971 }
972 */
973
974 /*@only@*/ constraint constraint_doSRefFixConstraintParam (constraint precondition,
975                                                    exprNodeList arglist)
976 {
977
978   precondition = constraint_copy (precondition);
979
980   llassert (constraint_isDefined (precondition) );
981  
982   precondition->lexpr = constraintExpr_doSRefFixConstraintParam (precondition->lexpr, arglist);
983   precondition->expr = constraintExpr_doSRefFixConstraintParam (precondition->expr, arglist);
984
985   precondition->fcnPre = FALSE;
986   return constraint_simplify(precondition);
987 }
988
989 constraint constraint_preserveOrig (/*@returned@*/ constraint c) /*@modifies c @*/
990 {
991   DPRINTF (("Doing constraint_preserverOrig for %q", constraint_printDetailed (c)));
992   llassert (constraint_isDefined (c));
993
994   if (c->orig == constraint_undefined)
995     {
996       c->orig = constraint_copy (c);
997     }
998   else if (c->orig->fcnPre)
999     {
1000       constraint temp = c->orig;
1001       
1002       /* avoid infinite loop */
1003       c->orig = NULL;
1004       c->orig = constraint_copy (c);
1005       /*drl 03/2/2003 if c != NULL then the copy of c will != null*/
1006       llassert (constraint_isDefined (c->orig) );
1007
1008       if (c->orig->orig == NULL)
1009         {
1010           c->orig->orig = temp;
1011           temp = NULL;
1012         }
1013       else
1014         {
1015           llcontbug ((message ("Expected c->orig->orig to be null")));
1016           constraint_free (c->orig->orig);
1017           c->orig->orig = temp;
1018           temp = NULL;
1019         }
1020     }
1021   else
1022     {
1023       DPRINTF (("Not changing constraint"));
1024     }
1025   
1026   DPRINTF ((message ("After Doing constraint_preserverOrig for %q ", constraint_unparseDetailed (c))));
1027   return c;
1028 }
1029
1030 constraint constraint_togglePost (/*@returned@*/ constraint c)
1031 {
1032   llassert (constraint_isDefined (c));
1033   c->post = !c->post;
1034   return c;
1035 }
1036
1037 constraint constraint_togglePostOrig (/*@returned@*/ constraint c)
1038 {
1039   llassert (constraint_isDefined (c));
1040  
1041   if (c->orig != NULL)
1042     {
1043       c->orig = constraint_togglePost (c->orig);
1044     }
1045
1046   return c;
1047 }
1048
1049 bool constraint_hasOrig ( /*@observer@*/ /*@temp@*/ constraint c)
1050 {
1051   llassert (constraint_isDefined (c));
1052   return (c->orig != NULL);
1053 }
1054
1055
1056 constraint constraint_undump (FILE *f)
1057 {
1058   constraint c;
1059   bool fcnPre, post;
1060   arithType ar;
1061   constraintExpr lexpr, expr;
1062   char *s, *os;
1063   
1064   os = mstring_create (MAX_DUMP_LINE_LENGTH);
1065   s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
1066
1067   if (!mstring_isDefined (s))
1068     {
1069       llfatalbug (message ("Library file is corrupted") );
1070     }
1071   
1072   fcnPre = (bool) reader_getInt (&s);
1073   advanceField (&s);
1074   post = (bool) reader_getInt (&s);
1075   advanceField (&s);
1076   ar = (arithType) reader_getInt (&s);
1077   
1078   s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
1079
1080   if (! mstring_isDefined(s) )
1081     {
1082       llfatalbug(message("Library file is corrupted") );
1083     }
1084   
1085   reader_checkChar (&s, 'l');
1086
1087   lexpr = constraintExpr_undump (f);
1088
1089   s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
1090
1091   reader_checkChar (&s, 'r');
1092   
1093   if (! mstring_isDefined(s) )
1094     {
1095       llfatalbug(message("Library file is corrupted") );
1096     }
1097   
1098   expr = constraintExpr_undump (f);
1099
1100   c = constraint_makeNew ();
1101   
1102   c->fcnPre = fcnPre; 
1103   c->post = post;
1104   c->ar = ar;
1105
1106   c->lexpr = lexpr;
1107   c->expr =  expr;
1108
1109   free (os);
1110   c = constraint_preserveOrig (c);
1111   return c;
1112 }
1113
1114
1115 void constraint_dump (/*@observer@*/ constraint c,  FILE *f)
1116 {
1117   bool           fcnPre;
1118   bool post;
1119   arithType       ar;
1120   
1121   constraintExpr lexpr;
1122   constraintExpr  expr;
1123
1124   llassert (constraint_isDefined (c) );
1125  
1126   fcnPre = c->fcnPre;
1127   post   = c->post;
1128   ar     = c->ar;
1129   lexpr = c->lexpr;
1130   expr = c->expr;
1131   
1132   fprintf (f, "%d@%d@%d\n", (int) fcnPre, (int) post, (int) ar);
1133   fprintf (f,"l\n");
1134   constraintExpr_dump (lexpr, f);
1135   fprintf (f,"r\n");
1136   constraintExpr_dump (expr, f);
1137 }
1138
1139
1140 int constraint_compare (/*@observer@*/ /*@temp@*/ const constraint * c1, /*@observer@*/ /*@temp@*/ const constraint * c2) /*@*/
1141 {
1142   fileloc loc1, loc2;
1143
1144   int ret;
1145   
1146   llassert (constraint_isDefined (*c1));
1147   llassert (constraint_isDefined (*c2));
1148
1149   if (constraint_isUndefined (*c1))
1150     {
1151         if (constraint_isUndefined (*c2))
1152           return 0;
1153         else
1154           return 1;
1155     }
1156
1157   if (constraint_isUndefined (*c2))
1158     {
1159       return -1;
1160     }
1161     
1162   loc1 = constraint_getFileloc (*c1);
1163   loc2 = constraint_getFileloc (*c2);
1164
1165   ret = fileloc_compare (loc1, loc2);
1166
1167   fileloc_free (loc1);
1168   fileloc_free (loc2);
1169     
1170   return ret;
1171 }
1172
1173
1174 bool constraint_isPost  (/*@observer@*/ /*@temp@*/ constraint c)
1175 {
1176   llassert (constraint_isDefined (c));
1177
1178   if (constraint_isUndefined (c))
1179     return FALSE;
1180   
1181   return (c->post);
1182 }
1183
1184
1185 static int constraint_getDepth (/*@observer@*/ /*@temp@*/ constraint c)
1186 {
1187   int l , r;
1188   
1189   llassert (constraint_isDefined (c) );
1190  
1191   l = constraintExpr_getDepth (c->lexpr);
1192   r = constraintExpr_getDepth (c->expr);
1193
1194   if (l > r)
1195     {
1196       DPRINTF (( message ("constraint depth returning %d for %s", l, constraint_unparse (c))));
1197       return l;
1198     }
1199   else
1200     {
1201       DPRINTF (( message ("constraint depth returning %d for %s", r, constraint_unparse (c))));
1202       return r;
1203     }
1204 }
1205
1206
1207 bool constraint_tooDeep (/*@observer@*/ /*@temp@*/ constraint c)
1208 {
1209   int temp;
1210
1211   temp = constraint_getDepth (c);
1212
1213   if (temp >= 20)              
1214     {
1215       return TRUE;
1216     }
1217
1218   return FALSE;
1219   
1220 }
1221
1222 /*drl added 12/19/2002*/
1223 /*whether constraints consist only of
1224   terms which are constants*/
1225 bool constraint_isConstantOnly (constraint c)
1226 {
1227   bool l, r;
1228   
1229   llassert (constraint_isDefined (c) );
1230  
1231   l = constraintExpr_isConstantOnly(c->lexpr);
1232   r = constraintExpr_isConstantOnly(c->expr);
1233
1234   if (l && r)
1235     {
1236       return TRUE;
1237     }
1238
1239   else
1240     {
1241       return FALSE;
1242     }
1243   
1244 }
This page took 0.218699 seconds and 5 git commands to generate.