7 # include <ctype.h> /* for isdigit */
8 # include "lclintMacros.nf"
10 # include "cgrammar.h"
11 # include "cgrammar_tokens.h"
13 # include "exprChecks.h"
14 # include "exprNodeSList.h"
18 /*@access exprNode @*/
21 static /*@only@*/ cstring constraint_printDetailedPostCondition (/*@observer@*/ /*@temp@*/ constraint p_c);
24 static /*@notnull@*/ /*@special@*/ constraint constraint_makeNew (void)
25 /*@post:isnull result->or, result->orig, result->generatingExpr, result->fcnPre @*/ /*@defines result->or, result->generatingExpr, result->orig, result->fcnPre @*/;
27 /* constraint makeConstraintParse (sRef x, lltok relOp, exprNode cconstant) */
33 /* ret = constraint_makeNew(); */
34 /* llassert (sRef_isValid(x) ); */
35 /* if (!sRef_isValid(x)) */
39 /* ret->lexpr = constraintExpr_makeTermsRef (x); */
40 /* #warning fix abstraction */
42 /* if (relOp.tok == GE_OP) */
44 /* else if (relOp.tok == LE_OP) */
46 /* else if (relOp.tok == EQ_OP) */
49 /* llfatalbug(message ("Unsupported relational operator") ); */
52 /* t = cstring_toCharsSafe (exprNode_unparse(cconstant)); */
54 /* ret->expr = constraintExpr_makeIntLiteral (c); */
56 /* ret->post = TRUE; */
57 /* // ret->orig = ret; */
58 /* DPRINTF(("GENERATED CONSTRAINT:")); */
59 /* DPRINTF( (message ("%s", constraint_print(ret) ) ) ); */
65 advanceField (char **s)
67 reader_checkChar (s, '@');
72 static constraint makeConstraintParse2 (constraintExpr l, lltok relOp, exprNode cconstant)
77 ret = constraint_makeNew();
78 llassert (constraintExpr_isDefined(l) );
80 ret->lexpr = constraintExpr_copy (l);
83 if (relOp.tok == GE_OP)
85 else if (relOp.tok == LE_OP)
87 else if (relOp.tok == EQ_OP)
90 llfatalbug(message("Unsupported relational operator") );
93 t = cstring_toCharsSafe (exprNode_unparse(cconstant));
95 ret->expr = constraintExpr_makeIntLiteral (c);
99 DPRINTF(("GENERATED CONSTRAINT:"));
100 DPRINTF( (message ("%s", constraint_print(ret) ) ) );
104 bool constraint_same (constraint c1, constraint c2)
107 if (c1->ar != c2->ar)
110 if (!constraintExpr_similar (c1->lexpr, c2->lexpr) )
113 if (!constraintExpr_similar (c1->expr, c2->expr) )
119 constraint makeConstraintParse3 (constraintExpr l, lltok relOp, constraintExpr r)
122 ret = constraint_makeNew();
123 llassert (constraintExpr_isDefined(l) );
125 ret->lexpr = constraintExpr_copy (l);
127 if (relOp.tok == GE_OP)
129 else if (relOp.tok == LE_OP)
131 else if (relOp.tok == EQ_OP)
134 llfatalbug( message("Unsupported relational operator") );
136 ret->expr = constraintExpr_copy (r);
140 ret->orig = constraint_copy(ret);
142 ret = constraint_simplify (ret);
145 DPRINTF(("GENERATED CONSTRAINT:"));
146 DPRINTF( (message ("%s", constraint_print(ret) ) ) );
150 constraint constraint_copy (/*@temp@*/ /*@observer@*/ constraint c)
154 llassert (constraint_isDefined(c) );
155 // DPRINTF((message("Copying constraint %q", constraint_print) ));
157 ret = constraint_makeNew();
158 ret->lexpr = constraintExpr_copy (c->lexpr);
160 ret->expr = constraintExpr_copy (c->expr);
163 ret->generatingExpr = c->generatingExpr;
168 ret->orig = constraint_copy (c->orig);
173 ret->or = constraint_copy (c->or);
177 ret->fcnPre = c->fcnPre;
182 /*like copy expect it doesn't allocate memory for the constraint*/
184 void constraint_overWrite (constraint c1, constraint c2)
186 llassert (constraint_isDefined(c1) );
190 DPRINTF((message("OverWriteing constraint %q with %q", constraint_print(c1),
191 constraint_print(c2) ) ));
193 constraintExpr_free(c1->lexpr);
194 constraintExpr_free(c1->expr);
196 c1->lexpr = constraintExpr_copy (c2->lexpr);
198 c1->expr = constraintExpr_copy (c2->expr);
201 if (c1->orig != NULL)
202 constraint_free (c1->orig);
204 if (c2->orig != NULL)
205 c1->orig = constraint_copy (c2->orig);
209 /*@i33 make sure that the or is freed correctly*/
211 constraint_free (c1->or);
214 c1->or = constraint_copy (c2->or);
218 c1->fcnPre = c2->fcnPre;
221 c1->generatingExpr = c2->generatingExpr;
227 static /*@notnull@*/ /*@special@*/ constraint constraint_makeNew (void)
228 /*@post:isnull result->or, result->orig, result->generatingExpr, result->fcnPre @*/ /*@defines result->or, result->generatingExpr, result->orig, result->fcnPre @*/
231 ret = dmalloc(sizeof (*ret) );
238 ret->generatingExpr = NULL;
243 constraint constraint_addGeneratingExpr (/*@returned@*/ constraint c, exprNode e)
246 if (c->generatingExpr == NULL)
248 c->generatingExpr = e;
249 DPRINTF ((message ("setting generatingExpr for %s to %s", constraint_print(c), exprNode_unparse(e) ) ));
253 DPRINTF ((message ("Not setting generatingExpr for %s to %s", constraint_print(c), exprNode_unparse(e) ) ));
258 constraint constraint_origAddGeneratingExpr (/*@returned@*/ constraint c, exprNode e)
261 if (c->orig != constraint_undefined)
263 c->orig = constraint_addGeneratingExpr(c->orig, e);
267 DPRINTF ((message ("constraint_origAddGeneratingExpr: Not setting generatingExpr for %s to %s", constraint_print(c), exprNode_unparse(e) ) ));
272 constraint constraint_setFcnPre (/*@returned@*/ constraint c )
275 if (c->orig != constraint_undefined)
277 c->orig->fcnPre = TRUE;
282 // DPRINTF(( message("Warning Setting fcnPre directly") ));
290 fileloc constraint_getFileloc (constraint c)
292 if (exprNode_isDefined(c->generatingExpr) )
293 return (fileloc_copy (exprNode_getfileloc (c->generatingExpr) ) );
295 return (constraintExpr_getFileloc (c->lexpr) );
300 static bool checkForMaxSet (constraint c)
302 if (constraintExpr_hasMaxSet(c->lexpr) || constraintExpr_hasMaxSet(c->expr) )
308 bool constraint_hasMaxSet(constraint c)
312 if (checkForMaxSet(c->orig) )
316 return (checkForMaxSet(c) );
319 constraint constraint_makeReadSafeExprNode ( exprNode po, exprNode ind)
321 constraint ret = constraint_makeNew();
322 // constraintTerm term;
325 ret->lexpr = constraintExpr_makeMaxReadExpr(po);
327 ret->expr = constraintExpr_makeValueExpr (ind);
332 constraint constraint_makeWriteSafeInt ( exprNode po, int ind)
334 constraint ret = constraint_makeNew();
337 ret->lexpr =constraintExpr_makeMaxSetExpr(po);
339 ret->expr = constraintExpr_makeIntLiteral (ind);
343 constraint constraint_makeSRefSetBufferSize (sRef s, long int size)
345 constraint ret = constraint_makeNew();
346 ret->lexpr = constraintExpr_makeSRefMaxset (s);
348 ret->expr = constraintExpr_makeIntLiteral ((int)size);
353 constraint constraint_makeSRefWriteSafeInt (sRef s, int ind)
355 constraint ret = constraint_makeNew();
358 ret->lexpr = constraintExpr_makeSRefMaxset ( s );
360 ret->expr = constraintExpr_makeIntLiteral (ind);
365 /* drl added 01/12/2000
367 makes the constraint: Ensures index <= MaxRead(buffer) */
369 constraint constraint_makeEnsureLteMaxRead(exprNode index, exprNode buffer)
371 constraint ret = constraint_makeNew();
373 ret->lexpr = constraintExpr_makeValueExpr (index);
375 ret->expr = constraintExpr_makeMaxReadExpr(buffer);
380 constraint constraint_makeWriteSafeExprNode (exprNode po, exprNode ind)
382 constraint ret = constraint_makeNew();
385 ret->lexpr =constraintExpr_makeMaxSetExpr(po);
387 ret->expr = constraintExpr_makeValueExpr (ind);
392 constraint constraint_makeReadSafeInt ( exprNode t1, int index)
394 constraint ret = constraint_makeNew();
396 ret->lexpr = constraintExpr_makeMaxReadExpr(t1);
398 ret->expr = constraintExpr_makeIntLiteral (index);
403 constraint constraint_makeSRefReadSafeInt (sRef s, int ind)
405 constraint ret = constraint_makeNew();
408 ret->lexpr = constraintExpr_makeSRefMaxRead (s );
410 ret->expr = constraintExpr_makeIntLiteral (ind);
415 constraint constraint_makeEnsureMaxReadAtLeast (exprNode t1, exprNode t2, fileloc sequencePoint)
419 ret = constraint_makeReadSafeExprNode(t1, t2);
421 ret->lexpr = constraintExpr_setFileloc (ret->lexpr, sequencePoint);
425 // fileloc_incColumn (ret->lexpr->term->loc);
429 static constraint constraint_makeEnsuresOpConstraintExpr (/*@only@*/ constraintExpr c1, /*@only@*/ constraintExpr c2, fileloc sequencePoint, arithType ar)
434 llassert(constraintExpr_isDefined(c1) && constraintExpr_isDefined(c2) );
435 // llassert(sequencePoint);
437 ret = constraint_makeNew();
443 ret->lexpr = constraintExpr_setFileloc (ret->lexpr, sequencePoint);
447 static constraint constraint_makeEnsuresOp (/*@dependent@*/ exprNode e1, /*@dependent@*/ exprNode e2, fileloc sequencePoint, arithType ar)
449 constraintExpr c1, c2;
453 if (! (exprNode_isDefined(e1) && exprNode_isDefined(e2) ) )
455 llcontbug((message("null exprNode, Exprnodes are %s and %s",
456 exprNode_unparse(e1), exprNode_unparse(e2) )
460 // llassert (sequencePoint);
463 c1 = constraintExpr_makeValueExpr (e);
466 c2 = constraintExpr_makeValueExpr (e);
468 ret = constraint_makeEnsuresOpConstraintExpr (c1, c2, sequencePoint, ar);
474 /* make constraint ensures e1 == e2 */
476 constraint constraint_makeEnsureEqual (exprNode e1, exprNode e2, fileloc sequencePoint)
478 return ( constraint_makeEnsuresOp (e1, e2, sequencePoint, EQ) );
481 /*make constraint ensures e1 < e2 */
482 constraint constraint_makeEnsureLessThan (exprNode e1, exprNode e2, fileloc sequencePoint)
484 constraintExpr t1, t2;
486 t1 = constraintExpr_makeValueExpr (e1);
487 t2 = constraintExpr_makeValueExpr (e2);
489 /*change this to e1 <= (e2 -1) */
491 t2 = constraintExpr_makeDecConstraintExpr (t2);
493 return ( constraint_makeEnsuresOpConstraintExpr (t1, t2, sequencePoint, LTE) );
496 constraint constraint_makeEnsureLessThanEqual (exprNode e1, exprNode e2, fileloc sequencePoint)
498 return ( constraint_makeEnsuresOp (e1, e2, sequencePoint, LTE) );
501 constraint constraint_makeEnsureGreaterThan (exprNode e1, exprNode e2, fileloc sequencePoint)
503 constraintExpr t1, t2;
505 t1 = constraintExpr_makeValueExpr (e1);
506 t2 = constraintExpr_makeValueExpr (e2);
509 /* change this to e1 >= (e2 + 1) */
510 t2 = constraintExpr_makeIncConstraintExpr (t2);
513 return ( constraint_makeEnsuresOpConstraintExpr (t1, t2, sequencePoint, GTE) );
516 constraint constraint_makeEnsureGreaterThanEqual (exprNode e1, exprNode e2, fileloc sequencePoint)
518 return ( constraint_makeEnsuresOp (e1, e2, sequencePoint, GTE) );
522 exprNode exprNode_copyConstraints (/*@returned@*/ exprNode dst, exprNode src)
524 constraintList_free(dst->ensuresConstraints);
525 constraintList_free(dst->requiresConstraints);
526 constraintList_free(dst->trueEnsuresConstraints);
527 constraintList_free(dst->falseEnsuresConstraints);
529 dst->ensuresConstraints = constraintList_copy (src->ensuresConstraints );
530 dst->requiresConstraints = constraintList_copy (src->requiresConstraints );
531 dst->trueEnsuresConstraints = constraintList_copy (src->trueEnsuresConstraints );
532 dst->falseEnsuresConstraints = constraintList_copy (src->falseEnsuresConstraints );
536 /* Makes the constraint e = e + f */
537 constraint constraint_makeAddAssign (exprNode e, exprNode f, fileloc sequencePoint)
539 constraintExpr x1, x2, y;
542 ret = constraint_makeNew();
544 x1 = constraintExpr_makeValueExpr (e);
545 x2 = constraintExpr_copy(x1);
546 y = constraintExpr_makeValueExpr (f);
551 ret->expr = constraintExpr_makeAddExpr (x2, y);
553 ret->lexpr = constraintExpr_setFileloc (ret->lexpr, sequencePoint);
559 /* Makes the constraint e = e - f */
560 constraint constraint_makeSubtractAssign (exprNode e, exprNode f, fileloc sequencePoint)
562 constraintExpr x1, x2, y;
565 ret = constraint_makeNew();
567 x1 = constraintExpr_makeValueExpr (e);
568 x2 = constraintExpr_copy(x1);
569 y = constraintExpr_makeValueExpr (f);
574 ret->expr = constraintExpr_makeSubtractExpr (x2, y);
576 ret->lexpr = constraintExpr_setFileloc (ret->lexpr, sequencePoint);
581 constraint constraint_makeMaxSetSideEffectPostDecrement (exprNode e, fileloc sequencePoint)
583 constraint ret = constraint_makeNew();
584 //constraintTerm term;
586 // e = exprNode_fakeCopy(e);
587 ret->lexpr = constraintExpr_makeValueExpr (e);
590 ret->expr = constraintExpr_makeValueExpr (e);
591 ret->expr = constraintExpr_makeDecConstraintExpr (ret->expr);
593 ret->lexpr = constraintExpr_setFileloc (ret->lexpr, sequencePoint);
594 // fileloc_incColumn ( ret->lexpr->term->loc);
595 // fileloc_incColumn ( ret->lexpr->term->loc);
598 constraint constraint_makeMaxSetSideEffectPostIncrement (exprNode e, fileloc sequencePoint)
600 constraint ret = constraint_makeNew();
601 //constraintTerm term;
603 // e = exprNode_fakeCopy(e);
604 ret->lexpr = constraintExpr_makeValueExpr (e);
607 ret->expr = constraintExpr_makeValueExpr (e);
608 ret->expr = constraintExpr_makeIncConstraintExpr (ret->expr);
610 ret->lexpr = constraintExpr_setFileloc (ret->lexpr, sequencePoint);
611 // fileloc_incColumn ( ret->lexpr->term->loc);
612 // fileloc_incColumn ( ret->lexpr->term->loc);
617 void constraint_free (/*@only@*/ constraint c)
619 llassert(constraint_isDefined (c) );
622 if (constraint_isDefined(c->orig) )
623 constraint_free (c->orig);
624 if ( constraint_isDefined(c->or) )
625 constraint_free (c->or);
628 constraintExpr_free(c->lexpr);
629 constraintExpr_free(c->expr);
641 // constraint constraint_makeMaxReadSideEffectPostIncrement (exprNode e, fileloc sequencePoint)
643 // constraint ret = constraint_makeNew();
644 // //constraintTerm term;
646 // e = exprNode_fakeCopy(e);
647 // ret->lexpr = constraintExpr_makeMaxReadExpr(e);
650 // ret->expr = constraintExpr_makeIncConstraintExpr (e);
651 // ret->lexpr = constraintExpr_setFileLoc (ret->lexpr, sequencePoint);
656 cstring arithType_print (arithType ar) /*@*/
658 cstring st = cstring_undefined;
662 st = cstring_makeLiteral (" < ");
665 st = cstring_makeLiteral (" <= ");
668 st = cstring_makeLiteral (" > ");
671 st = cstring_makeLiteral (" >= ");
674 st = cstring_makeLiteral (" == ");
677 st = cstring_makeLiteral (" NONNEGATIVE ");
680 st = cstring_makeLiteral (" POSITIVE ");
689 void constraint_printErrorPostCondition (constraint c, fileloc loc)
692 fileloc errorLoc, temp;
694 string = constraint_printDetailedPostCondition (c);
700 temp = constraint_getFileloc(c);
702 if (fileloc_isDefined(temp) )
705 voptgenerror ( FLG_CHECKPOST, string, errorLoc);
710 voptgenerror ( FLG_CHECKPOST, string, errorLoc);
717 void constraint_printError (constraint c, fileloc loc)
720 fileloc errorLoc, temp;
722 string = constraint_printDetailed (c);
728 temp = constraint_getFileloc(c);
730 if (fileloc_isDefined(temp) )
736 voptgenerror (FLG_FUNCTIONPOST, string, errorLoc);
740 voptgenerror (FLG_FUNCTIONCONSTRAINT, string, errorLoc);
749 voptgenerror (FLG_FUNCTIONPOST, string, errorLoc);
753 voptgenerror (FLG_FUNCTIONCONSTRAINT, string, errorLoc);
760 static cstring constraint_printDeep (constraint c)
763 cstring st = cstring_undefined;
765 st = constraint_print(c);
768 if (c->orig != constraint_undefined)
770 genExpr = exprNode_unparse(c->orig->generatingExpr);
774 st = cstring_concatFree(st, (message(" derived from %s precondition: %q", genExpr, constraint_printDeep(c->orig) )
777 st = cstring_concatFree(st,(message(" needed to satisfy %q",
778 constraint_printDeep(c->orig) )
784 st = cstring_concatFree(st,(message("derived from: %q",
785 constraint_printDeep(c->orig) )
795 static /*@only@*/ cstring constraint_printDetailedPostCondition (/*@observer@*/ /*@temp@*/ constraint c)
797 cstring st = cstring_undefined;
800 st = message ("Unsatisfied ensures constraint condition:\nLCLint is unable to verify the constraint %q", constraint_printDeep (c) );
802 genExpr = exprNode_unparse (c->generatingExpr);
804 if (context_getFlag (FLG_CONSTRAINTLOCATION) )
807 // llassert (c->generatingExpr);
808 temp = message ("\nOriginal Generating expression %q: %s\n", fileloc_unparse( exprNode_getfileloc (c->generatingExpr) ),
810 st = cstring_concatFree (st, temp);
812 if (constraint_hasMaxSet(c) )
814 temp = message ("Has MaxSet\n");
815 st = cstring_concatFree (st, temp);
821 cstring constraint_printDetailed (constraint c)
823 cstring st = cstring_undefined;
828 st = message ("Unresolved constraint:\nLclint is unable to resolve %q", constraint_printDeep (c) );
832 st = message ("Block Post condition:\nThis function block has the post condition %q", constraint_printDeep (c) );
835 genExpr = exprNode_unparse (c->generatingExpr);
837 if (context_getFlag (FLG_CONSTRAINTLOCATION) )
840 // llassert (c->generatingExpr);
841 temp = message ("\nOriginal Generating expression %q: %s\n", fileloc_unparse( exprNode_getfileloc (c->generatingExpr) ),
843 st = cstring_concatFree (st, temp);
845 if (constraint_hasMaxSet(c) )
847 temp = message ("Has MaxSet\n");
848 st = cstring_concatFree (st, temp);
854 /*@only@*/ cstring constraint_print (constraint c) /*@*/
856 cstring st = cstring_undefined;
857 cstring type = cstring_undefined;
861 type = cstring_makeLiteral ("Ensures: ");
865 type = cstring_makeLiteral ("Requires: ");
867 st = message ("%q: %q %q %q",
869 constraintExpr_print (c->lexpr),
870 arithType_print(c->ar),
871 constraintExpr_print(c->expr)
876 cstring constraint_printOr (constraint c) /*@*/
881 ret = cstring_undefined;
884 ret = cstring_concatFree (ret, constraint_print(temp) );
888 while ( constraint_isDefined(temp) )
890 ret = cstring_concatFree (ret, cstring_makeLiteral (" OR ") );
891 ret = cstring_concatFree (ret, constraint_print(temp) );
899 /*@only@*/ constraint constraint_doSRefFixBaseParam (/*@returned@*/ /*@only@*/ constraint precondition,
900 exprNodeList arglist)
902 precondition->lexpr = constraintExpr_doSRefFixBaseParam (precondition->lexpr,
904 precondition->expr = constraintExpr_doSRefFixBaseParam (precondition->expr,
911 constraint constraint_doFixResult (constraint postcondition, /*@dependent@*/ exprNode fcnCall)
913 postcondition = constraint_copy (postcondition);
914 postcondition->lexpr = constraintExpr_doFixResult (postcondition->lexpr, fcnCall);
915 postcondition->expr = constraintExpr_doFixResult (postcondition->expr, fcnCall);
917 return postcondition;
920 /*@only@*/ constraint constraint_doSRefFixConstraintParam (constraint precondition,
921 exprNodeList arglist)
924 precondition = constraint_copy (precondition);
925 precondition->lexpr = constraintExpr_doSRefFixConstraintParam (precondition->lexpr, arglist);
926 precondition->expr = constraintExpr_doSRefFixConstraintParam (precondition->expr, arglist);
928 precondition->fcnPre = FALSE;
932 // bool constraint_hasTerm (constraint c, constraintTerm term)
934 // DPRINTF((message ("Constraint %s", constraint_print (c) ) ) );
936 // if (constraintExpr_includesTerm (c->lexpr, term) )
939 // if (constraintExpr_includesTerm (c->expr, term) )
945 constraint constraint_preserveOrig (/*@returned@*/ constraint c) /*@modifies c @*/
948 DPRINTF( (message("Doing constraint_preserverOrig for %q ", constraint_printDetailed(c) ) ));
950 if (c->orig == constraint_undefined)
951 c->orig = constraint_copy (c);
953 else if (c->orig->fcnPre)
959 /* avoid infinite loop */
961 c->orig = constraint_copy (c);
962 if (c->orig->orig == NULL)
964 c->orig->orig = temp;
969 llcontbug((message("Expected c->orig->orig to be null" ) ));
970 constraint_free(c->orig->orig);
971 c->orig->orig = temp;
977 DPRINTF( (message("Not changing constraint") ));
980 DPRINTF( (message("After Doing constraint_preserverOrig for %q ", constraint_printDetailed(c) ) ));
989 constraint constraint_togglePost (/*@returned@*/ constraint c)
995 constraint constraint_togglePostOrig (/*@returned@*/ constraint c)
998 c->orig = constraint_togglePost(c->orig);
1002 bool constraint_hasOrig( /*@observer@*/ /*@temp@*/ constraint c)
1004 if (c->orig == NULL)
1011 constraint constraint_undump (FILE *f)
1018 constraintExpr lexpr;
1019 constraintExpr expr;
1026 s = mstring_create (MAX_DUMP_LINE_LENGTH);
1030 s = fgets(os, MAX_DUMP_LINE_LENGTH, f);
1032 /*@i33*/ /*this should probably be wrappered...*/
1034 fcnPre = (bool) reader_getInt (&s);
1036 post = (bool) reader_getInt (&s);
1038 ar = (arithType) reader_getInt (&s);
1040 s = fgets(os, MAX_DUMP_LINE_LENGTH, f);
1042 reader_checkChar (&s, 'l');
1044 lexpr = constraintExpr_undump (f);
1046 s = fgets(os, MAX_DUMP_LINE_LENGTH, f);
1048 reader_checkChar (&s, 'r');
1049 expr = constraintExpr_undump (f);
1051 c = constraint_makeNew();
1065 void constraint_dump (/*@observer@*/ constraint c, FILE *f)
1071 constraintExpr lexpr;
1072 constraintExpr expr;
1081 fprintf(f, "%d@%d@%d\n", (int) fcnPre, (int) post, (int) ar);
1083 constraintExpr_dump (lexpr, f);
1085 constraintExpr_dump (expr, f);