Two useless/empty bison reductions removed.
[splint-patched.git] / src / constraintTerm.c
blob49315fd0939f97ed1de55d6760f342f9cbd62b48
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.
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
26 ** constraintTerm.c
29 /* #define DEBUGPRINT 1 */
31 # include "splintMacros.nf"
32 # include "basic.h"
34 bool constraintTerm_isDefined (constraintTerm t)
36 return t != NULL;
39 void constraintTerm_free (/*@only@*/ constraintTerm term)
41 llassert (constraintTerm_isDefined (term));
43 fileloc_free (term->loc);
45 switch (term->kind)
47 case CTT_EXPR:
48 /* we don't free an exprNode*/
49 break;
50 case CTT_SREF:
51 /* sref */
52 sRef_free (term->value.sref);
53 break;
54 case CTT_INTLITERAL:
55 /* don't free an int */
56 break;
57 case CTT_ERRORBADCONSTRAINTTERMTYPE:
58 default:
59 /* type was set incorrectly */
60 llcontbug (message("constraintTerm_free type was set incorrectly"));
63 term->kind = CTT_ERRORBADCONSTRAINTTERMTYPE;
64 free (term);
67 /*@only@*/ static/*@out@*/ constraintTerm new_constraintTermExpr (void)
69 constraintTerm ret;
70 ret = dmalloc (sizeof (* ret ) );
71 ret->value.intlit = 0;
72 return ret;
76 bool constraintTerm_isIntLiteral (constraintTerm term)
78 llassert(term != NULL);
80 if (term->kind == CTT_INTLITERAL)
81 return TRUE;
83 return FALSE;
87 bool constraintTerm_isInitBlock (/*@observer@*/ /*@temp@*/ constraintTerm c) /*@*/
89 llassert (c != NULL);
91 if (c->kind == CTT_EXPR)
93 if (exprNode_isInitBlock (c->value.expr))
95 return TRUE;
98 return FALSE;
102 bool constraintTerm_isExprNode (/*@observer@*/ /*@temp@*/ constraintTerm c) /*@*/
104 llassert (c != NULL);
106 if (c->kind == CTT_EXPR)
108 return TRUE;
110 return FALSE;
113 /*@access exprNode@*/
114 int constraintTerm_getInitBlockLength (/*@observer@*/ /*@temp@*/ constraintTerm c) /*@*/
116 exprNodeList list;
117 int ret;
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) )
126 return 1;
129 if (c->value.expr->edata == exprData_undefined)
131 return 1;
133 list = exprData_getArgs(c->value.expr->edata);
135 ret = exprNodeList_size(list);
137 return ret;
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) )
149 return TRUE;
152 return FALSE;
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 ) )
172 long int temp;
174 temp = exprNode_getLongValue (term->value.expr);
175 term->value.intlit = (int)temp;
176 term->kind = CTT_INTLITERAL;
179 return term;
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) );
192 return (t->kind);
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));
207 ret->value.expr = e;
208 ret->kind = CTT_EXPR;
209 ret = constraintTerm_simplify (ret);
210 return 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);
220 return ret;
225 constraintTerm constraintTerm_copy (constraintTerm term)
227 constraintTerm ret;
228 ret = new_constraintTermExpr();
229 ret->loc = fileloc_copy (term->loc);
231 switch (term->kind)
233 case CTT_EXPR:
234 ret->value.expr = term->value.expr;
235 break;
236 case CTT_INTLITERAL:
237 ret->value.intlit = term->value.intlit;
238 break;
240 case CTT_SREF:
241 ret->value.sref = sRef_saveCopy(term->value.sref);
242 break;
243 default:
244 BADEXIT;
246 ret->kind = term->kind;
247 return ret;
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);
258 return term;
262 # ifdef DEADCODE
263 static cstring constraintTerm_getName (constraintTerm term)
265 cstring s;
266 s = cstring_undefined;
268 llassert (term != NULL);
270 switch (term->kind)
272 case CTT_EXPR:
274 s = message ("%s", exprNode_unparse (term->value.expr) );
275 break;
276 case CTT_INTLITERAL:
277 s = message (" %d ", (int) term->value.intlit);
278 break;
280 case CTT_SREF:
281 s = message ("%q", sRef_unparse (term->value.sref) );
283 break;
284 default:
285 BADEXIT;
286 /*@notreached@*/
287 break;
290 return s;
293 constraintTerm
294 constraintTerm_doSRefFixBaseParam (/*@returned@*/constraintTerm term, exprNodeList arglist) /*@modifies term@*/
296 llassert (term != NULL);
298 switch (term->kind)
300 case CTT_EXPR:
302 break;
303 case CTT_INTLITERAL:
304 break;
306 case CTT_SREF:
307 term->value.sref = sRef_fixBaseParam (term->value.sref, arglist);
308 break;
309 default:
310 BADEXIT;
312 return term;
315 # endif /* DEADCODE */
317 cstring constraintTerm_unparse (constraintTerm term) /*@*/
319 cstring s;
320 s = cstring_undefined;
322 llassert (term != NULL);
324 switch (term->kind)
326 case CTT_EXPR:
328 s = message ("%s @ %q", exprNode_unparse (term->value.expr),
329 fileloc_unparse (term->loc) );
330 break;
331 case CTT_INTLITERAL:
332 s = message ("%d", (int)term->value.intlit);
333 break;
335 case CTT_SREF:
336 s = message ("%q", sRef_unparseDebug (term->value.sref) );
338 break;
339 default:
340 BADEXIT;
343 return s;
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;
353 return ret;
356 bool constraintTerm_canGetValue (constraintTerm term)
358 if (term->kind == CTT_INTLITERAL)
360 return TRUE;
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 */
370 else
372 return FALSE;
375 else if (term->kind == CTT_EXPR)
377 return FALSE;
379 else
381 return FALSE;
385 void constraintTerm_setValue (constraintTerm term, long value)
387 if (term->kind == CTT_INTLITERAL)
389 term->value.intlit = value;
391 else
393 BADBRANCH;
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 */
413 else
415 BADBRANCH;
418 else if (term->kind == CTT_EXPR)
420 BADBRANCH;
422 else
424 BADBRANCH;
427 BADEXIT;
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;
459 # ifdef DEADCODE
460 bool constraintTerm_probSame (constraintTerm term1, constraintTerm term2)
462 cstring s1, s2;
464 llassert (term1 !=NULL && term2 !=NULL);
466 DPRINTF ((message
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 ) ) );
478 return TRUE;
480 else
482 DPRINTF ((message (" %q and %q are not same", s1, s2 ) ) );
483 return FALSE;
486 # endif /* DEADCODE */
488 bool constraintTerm_similar (constraintTerm term1, constraintTerm term2)
490 sRef s1, s2;
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) ) */
499 long t1, t2;
501 t1 = constraintTerm_getValue (term1);
502 t2 = constraintTerm_getValue (term2);
504 return (t1 == t2);
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))
516 return FALSE;
519 s1 = constraintTerm_getsRef (term1);
520 s2 = constraintTerm_getsRef (term2);
522 if (!(sRef_isValid(s1) && sRef_isValid(s2)))
524 return FALSE;
527 DPRINTF((message
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) ) ));
536 return TRUE;
538 else
540 DPRINTF ((message (" %s and %s are not same", constraintTerm_unparse(term1), constraintTerm_unparse(term2) ) ));
541 return FALSE;
545 void constraintTerm_dump (/*@observer@*/ constraintTerm t, FILE *f)
547 constraintTermType kind;
548 uentry u;
550 kind = t->kind;
552 fprintf(f, "%d\n", (int) kind);
554 switch (kind)
557 case CTT_EXPR:
558 u = exprNode_getUentry(t->value.expr);
559 fprintf (f, "%s\n", cstring_toCharsSafe (uentry_rawName (u)));
560 break;
562 case CTT_SREF:
564 sRef s;
566 s = t->value.sref;
568 if (sRef_isResult (s ) )
570 fprintf(f, "Result\n");
572 else if (sRef_isParam (s))
574 int param;
575 ctype ct;
576 cstring ctString;
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)) );
591 else
593 u = sRef_getUentry(s);
594 fprintf (f, "%s\n", cstring_toCharsSafe (uentry_rawName (u)));
598 break;
600 case CTT_INTLITERAL:
601 fprintf (f, "%ld\n", t->value.intlit);
602 break;
604 default:
605 BADEXIT;
610 /*@only@*/ constraintTerm constraintTerm_undump (FILE *f)
612 constraintTermType kind;
613 constraintTerm ret;
615 uentry ue;
617 char *str;
618 char *os;
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);
631 switch (kind)
634 case CTT_SREF:
636 sRef s;
637 char * term;
638 term = reader_getWord(&str);
640 if (term == NULL)
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 )
650 int param;
651 char *str2, *ostr2;
653 ctype t;
655 reader_checkChar(&str, ' ');
656 str2 = reader_getWord(&str);
657 param = reader_getInt(&str);
659 if (str2 == NULL)
661 llfatalbug (message ("Library file appears to be corrupted.") );
664 ostr2 = str2;
665 t = ctype_undump(&str2) ;
666 s = sRef_makeParam (param, t, stateInfo_makeLoc (g_currentloc, SA_CREATED));
667 free (ostr2);
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);
684 free(term);
686 break;
688 case CTT_EXPR:
690 sRef s;
691 char * term;
692 cstring termStr;
694 term = reader_getWord(&str);
696 if (term == NULL)
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);
708 free (term);
710 break;
713 case CTT_INTLITERAL:
715 int i;
717 i = reader_getInt(&str);
718 ret = constraintTerm_makeIntLiteral (i);
720 break;
722 default:
723 BADEXIT;
725 free (os);
727 return ret;
732 /* drl added sometime before 10/17/001*/
733 ctype constraintTerm_getCType (constraintTerm term)
735 ctype ct;
737 switch (term->kind)
739 case CTT_EXPR:
740 ct = exprNode_getType (term->value.expr);
741 break;
743 case CTT_INTLITERAL:
744 ct = ctype_signedintegral;
745 break;
747 case CTT_SREF:
748 ct = sRef_getType (term->value.sref) ;
749 break;
750 default:
751 BADEXIT;
753 return ct;
756 bool constraintTerm_isConstantOnly (constraintTerm term)
758 switch (term->kind)
760 case CTT_EXPR:
761 if (exprNode_isNumLiteral (term->value.expr) ||
762 exprNode_isStringLiteral (term->value.expr) ||
763 exprNode_isCharLiteral (term->value.expr) )
765 return TRUE;
767 else
769 return FALSE;
772 case CTT_INTLITERAL:
773 return TRUE;
775 case CTT_SREF:
776 if ( sRef_isConst (term->value.sref) )
778 return TRUE;
780 else
782 return FALSE;
784 default:
785 BADEXIT;
788 BADEXIT;