2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 University of Virginia,
4 ** Massachusetts Institute of Technology
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.
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.
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.
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
29 /* #define DEBUGPRINT 1 */
31 # include "splintMacros.nf"
34 bool constraintTerm_isDefined (constraintTerm t
)
39 void constraintTerm_free (/*@only@*/ constraintTerm term
)
41 llassert (constraintTerm_isDefined (term
));
43 fileloc_free (term
->loc
);
48 /* we don't free an exprNode*/
52 sRef_free (term
->value
.sref
);
55 /* don't free an int */
57 case CTT_ERRORBADCONSTRAINTTERMTYPE
:
59 /* type was set incorrectly */
60 llcontbug (message("constraintTerm_free type was set incorrectly"));
63 term
->kind
= CTT_ERRORBADCONSTRAINTTERMTYPE
;
67 /*@only@*/ static/*@out@*/ constraintTerm
new_constraintTermExpr (void)
70 ret
= dmalloc (sizeof (* ret
) );
71 ret
->value
.intlit
= 0;
76 bool constraintTerm_isIntLiteral (constraintTerm term
)
78 llassert(term
!= NULL
);
80 if (term
->kind
== CTT_INTLITERAL
)
87 bool constraintTerm_isInitBlock (/*@observer@*/ /*@temp@*/ constraintTerm c
) /*@*/
91 if (c
->kind
== CTT_EXPR
)
93 if (exprNode_isInitBlock (c
->value
.expr
))
102 bool constraintTerm_isExprNode (/*@observer@*/ /*@temp@*/ constraintTerm c
) /*@*/
104 llassert (c
!= NULL
);
106 if (c
->kind
== CTT_EXPR
)
113 /*@access exprNode@*/
114 int constraintTerm_getInitBlockLength (/*@observer@*/ /*@temp@*/ constraintTerm c
) /*@*/
118 llassert (c
!= NULL
);
119 llassert (constraintTerm_isInitBlock (c
) );
120 llassert (c
->kind
== CTT_EXPR
);
122 llassert(exprNode_isDefined(c
->value
.expr
) );
124 if (exprNode_isUndefined(c
->value
.expr
) )
129 if (c
->value
.expr
->edata
== exprData_undefined
)
133 list
= exprData_getArgs(c
->value
.expr
->edata
);
135 ret
= exprNodeList_size(list
);
139 /*@noaccess exprNode@*/
142 bool constraintTerm_isStringLiteral (constraintTerm c
) /*@*/
144 llassert (c
!= NULL
);
145 if (c
->kind
== CTT_EXPR
)
147 if (exprNode_knownStringValue(c
->value
.expr
) )
157 cstring
constraintTerm_getStringLiteral (constraintTerm c
)
159 llassert (c
!= NULL
);
160 llassert (constraintTerm_isStringLiteral (c
) );
161 llassert (c
->kind
== CTT_EXPR
);
163 return (cstring_copy ( multiVal_forceString (exprNode_getValue (c
->value
.expr
) ) ) );
166 constraintTerm
constraintTerm_simplify (/*@returned@*/ constraintTerm term
) /*@modifies term@*/
168 if (term
->kind
== CTT_EXPR
)
170 if ( exprNode_knownIntValue (term
->value
.expr
) )
174 temp
= exprNode_getLongValue (term
->value
.expr
);
175 term
->value
.intlit
= (int)temp
;
176 term
->kind
= CTT_INTLITERAL
;
182 fileloc
constraintTerm_getFileloc (constraintTerm t
)
184 llassert (constraintTerm_isDefined (t
));
185 return (fileloc_copy (t
->loc
) );
188 constraintTermType
constraintTerm_getKind (constraintTerm t
)
190 llassert (constraintTerm_isDefined(t
) );
195 /*@exposed@*/ sRef
constraintTerm_getSRef (constraintTerm t
)
197 llassert (constraintTerm_isDefined(t
) );
198 llassert (t
->kind
== CTT_SREF
);
200 return (t
->value
.sref
);
203 /*@only@*/ constraintTerm
constraintTerm_makeExprNode (/*@dependent@*/ exprNode e
)
205 constraintTerm ret
= new_constraintTermExpr ();
206 ret
->loc
= fileloc_copy (exprNode_loc (e
));
208 ret
->kind
= CTT_EXPR
;
209 ret
= constraintTerm_simplify (ret
);
213 /*@only@*/ constraintTerm
constraintTerm_makesRef (/*@temp@*/ /*@observer@*/ sRef s
)
215 constraintTerm ret
= new_constraintTermExpr();
216 ret
->loc
= fileloc_undefined
;
217 ret
->value
.sref
= sRef_saveCopy(s
);
218 ret
->kind
= CTT_SREF
;
219 ret
= constraintTerm_simplify(ret
);
225 constraintTerm
constraintTerm_copy (constraintTerm term
)
228 ret
= new_constraintTermExpr();
229 ret
->loc
= fileloc_copy (term
->loc
);
234 ret
->value
.expr
= term
->value
.expr
;
237 ret
->value
.intlit
= term
->value
.intlit
;
241 ret
->value
.sref
= sRef_saveCopy(term
->value
.sref
);
246 ret
->kind
= term
->kind
;
250 constraintTerm
constraintTerm_setFileloc (/*@returned@*/ constraintTerm term
, fileloc loc
)
252 llassert(term
!= NULL
);
254 if ( fileloc_isDefined( term
->loc
) )
255 fileloc_free(term
->loc
);
257 term
->loc
= fileloc_copy(loc
);
263 static cstring
constraintTerm_getName (constraintTerm term
)
266 s
= cstring_undefined
;
268 llassert (term
!= NULL
);
274 s
= message ("%s", exprNode_unparse (term
->value
.expr
) );
277 s
= message (" %d ", (int) term
->value
.intlit
);
281 s
= message ("%q", sRef_unparse (term
->value
.sref
) );
294 constraintTerm_doSRefFixBaseParam (/*@returned@*/constraintTerm term
, exprNodeList arglist
) /*@modifies term@*/
296 llassert (term
!= NULL
);
307 term
->value
.sref
= sRef_fixBaseParam (term
->value
.sref
, arglist
);
315 # endif /* DEADCODE */
317 cstring
constraintTerm_unparse (constraintTerm term
) /*@*/
320 s
= cstring_undefined
;
322 llassert (term
!= NULL
);
328 s
= message ("%s @ %q", exprNode_unparse (term
->value
.expr
),
329 fileloc_unparse (term
->loc
) );
332 s
= message ("%d", (int)term
->value
.intlit
);
336 s
= message ("%q", sRef_unparseDebug (term
->value
.sref
) );
347 constraintTerm
constraintTerm_makeIntLiteral (long i
)
349 constraintTerm ret
= new_constraintTermExpr();
350 ret
->value
.intlit
= i
;
351 ret
->kind
= CTT_INTLITERAL
;
352 ret
->loc
= fileloc_undefined
;
356 bool constraintTerm_canGetValue (constraintTerm term
)
358 if (term
->kind
== CTT_INTLITERAL
)
362 else if (term
->kind
== CTT_SREF
)
364 if (sRef_hasValue (term
->value
.sref
))
366 multiVal mval
= sRef_getValue (term
->value
.sref
);
368 return multiVal_isInt (mval
); /* for now, only try to deal with int values */
375 else if (term
->kind
== CTT_EXPR
)
385 void constraintTerm_setValue (constraintTerm term
, long value
)
387 if (term
->kind
== CTT_INTLITERAL
)
389 term
->value
.intlit
= value
;
397 long constraintTerm_getValue (constraintTerm term
)
399 llassert (constraintTerm_canGetValue (term
));
401 if (term
->kind
== CTT_INTLITERAL
)
403 return term
->value
.intlit
;
405 else if (term
->kind
== CTT_SREF
)
407 if (sRef_hasValue (term
->value
.sref
))
409 multiVal mval
= sRef_getValue (term
->value
.sref
);
411 return multiVal_forceInt (mval
); /* for now, only try to deal with int values */
418 else if (term
->kind
== CTT_EXPR
)
430 /*drl added this 10.30.001
433 /*@exposed@*/ exprNode
constraintTerm_getExprNode (constraintTerm t
)
435 llassert (t
!= NULL
);
437 llassert (t
->kind
== CTT_EXPR
);
439 return t
->value
.expr
;
443 /*@exposed@*/ sRef
constraintTerm_getsRef (constraintTerm t
)
445 llassert (t
!= NULL
);
446 if (t
->kind
== CTT_EXPR
)
448 return exprNode_getSref(t
->value
.expr
);
451 if (t
->kind
== CTT_SREF
)
453 return t
->value
.sref
;
456 return sRef_undefined
;
460 bool constraintTerm_probSame (constraintTerm term1
, constraintTerm term2
)
464 llassert (term1
!=NULL
&& term2
!=NULL
);
467 ("Comparing srefs for %s and %s ", constraintTerm_unparse(term1
), constraintTerm_unparse(term2
)
472 s1
= constraintTerm_getName (term1
);
473 s2
= constraintTerm_getName (term2
);
475 if (cstring_equal (s1
, s2
) )
477 DPRINTF ((message (" %q and %q are same", s1
, s2
) ) );
482 DPRINTF ((message (" %q and %q are not same", s1
, s2
) ) );
486 # endif /* DEADCODE */
488 bool constraintTerm_similar (constraintTerm term1
, constraintTerm term2
)
492 llassert (term1
!=NULL
&& term2
!=NULL
);
494 if (constraintTerm_canGetValue (term1
) && constraintTerm_canGetValue (term2
))
496 /*3/30/2003 comment updated to reflect name change form INTLITERAL to CTT_INTLITERAL*/
497 /* evans 2001-07-24: was (term1->kind == CTT_INTLITERAL) && (term2->kind == CTT_INTLITERAL) ) */
501 t1
= constraintTerm_getValue (term1
);
502 t2
= constraintTerm_getValue (term2
);
507 /*drl this if statement handles the case where constraintTerm_canGetValue only returns
508 true for term1 or term2 but no both
509 if constraintTerm_canGetValue returned tru for both we would have returned in the previous if statement
510 I suppose this could be done with xor but I've never used xor and don't feel like starting now
511 besides this way is more effecient.
513 if (constraintTerm_canGetValue (term1
) || constraintTerm_canGetValue (term2
))
519 s1
= constraintTerm_getsRef (term1
);
520 s2
= constraintTerm_getsRef (term2
);
522 if (!(sRef_isValid(s1
) && sRef_isValid(s2
)))
528 ("Comparing srefs for %s and %s ", constraintTerm_unparse(term1
), constraintTerm_unparse(term2
)
533 if (sRef_similarRelaxed(s1
, s2
) || sRef_sameName (s1
, s2
) )
535 DPRINTF ((message (" %s and %s are same", constraintTerm_unparse(term1
), constraintTerm_unparse(term2
) ) ));
540 DPRINTF ((message (" %s and %s are not same", constraintTerm_unparse(term1
), constraintTerm_unparse(term2
) ) ));
545 void constraintTerm_dump (/*@observer@*/ constraintTerm t
, FILE *f
)
547 constraintTermType kind
;
552 fprintf(f
, "%d\n", (int) kind
);
558 u
= exprNode_getUentry(t
->value
.expr
);
559 fprintf (f
, "%s\n", cstring_toCharsSafe (uentry_rawName (u
)));
568 if (sRef_isResult (s
) )
570 fprintf(f
, "Result\n");
572 else if (sRef_isParam (s
))
579 ct
= sRef_getType (s
);
580 param
= sRef_getParam(s
);
582 ctString
= ctype_dump(ct
);
584 fprintf(f
, "Param %s %d\n", cstring_toCharsSafe(ctString
), (int) param
);
585 cstring_free(ctString
);
587 else if (sRef_isField (s
) )
589 fprintf(f
, "sRef_dump %s\n", cstring_toCharsSafe(sRef_dump(s
)) );
593 u
= sRef_getUentry(s
);
594 fprintf (f
, "%s\n", cstring_toCharsSafe (uentry_rawName (u
)));
601 fprintf (f
, "%ld\n", t
->value
.intlit
);
610 /*@only@*/ constraintTerm
constraintTerm_undump (FILE *f
)
612 constraintTermType kind
;
620 os
= mstring_create (MAX_DUMP_LINE_LENGTH
);
622 str
= fgets (os
, MAX_DUMP_LINE_LENGTH
, f
);
624 llassert (str
!= NULL
);
626 kind
= (constraintTermType
) reader_getInt(&str
);
627 str
= fgets(os
, MAX_DUMP_LINE_LENGTH
, f
);
629 llassert (str
!= NULL
);
638 term
= reader_getWord(&str
);
642 llfatalbug (message ("Library file appears to be corrupted.") );
644 if (strcmp (term
, "Result") == 0 )
646 s
= sRef_makeResult (ctype_unknown
);
648 else if (strcmp (term
, "Param" ) == 0 )
655 reader_checkChar(&str
, ' ');
656 str2
= reader_getWord(&str
);
657 param
= reader_getInt(&str
);
661 llfatalbug (message ("Library file appears to be corrupted.") );
665 t
= ctype_undump(&str2
) ;
666 s
= sRef_makeParam (param
, t
, stateInfo_makeLoc (g_currentloc
, SA_CREATED
));
669 else if (strcmp (term
, "sRef_dump" ) == 0 )
671 reader_checkChar(&str
, ' ');
672 s
= sRef_undump (&str
);
674 else /* This must be an identified that we can search for in usymTab */
676 cstring termStr
= cstring_makeLiteralTemp(term
);
678 ue
= usymtab_lookup (termStr
);
679 s
= uentry_getSref(ue
);
682 ret
= constraintTerm_makesRef(s
);
694 term
= reader_getWord(&str
);
698 llfatalbug (message ("Library file appears to be corrupted.") );
701 /* This must be an identifier that we can search for in usymTab */
702 termStr
= cstring_makeLiteralTemp(term
);
704 ue
= usymtab_lookup (termStr
);
705 s
= uentry_getSref(ue
);
706 ret
= constraintTerm_makesRef(s
);
717 i
= reader_getInt(&str
);
718 ret
= constraintTerm_makeIntLiteral (i
);
732 /* drl added sometime before 10/17/001*/
733 ctype
constraintTerm_getCType (constraintTerm term
)
740 ct
= exprNode_getType (term
->value
.expr
);
744 ct
= ctype_signedintegral
;
748 ct
= sRef_getType (term
->value
.sref
) ;
756 bool constraintTerm_isConstantOnly (constraintTerm term
)
761 if (exprNode_isNumLiteral (term
->value
.expr
) ||
762 exprNode_isStringLiteral (term
->value
.expr
) ||
763 exprNode_isCharLiteral (term
->value
.expr
) )
776 if ( sRef_isConst (term
->value
.sref
) )