]> andersk Git - splint.git/blame - src/constraintResolve.c
*** empty log message ***
[splint.git] / src / constraintResolve.c
CommitLineData
65f973be 1/*
11db3170 2** Splint - annotation-assisted static program checker
c59f5181 3** Copyright (C) 1994-2003 University of Virginia,
65f973be 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**
155af98d 20** For information on splint: info@splint.org
21** To report a bug: splint-bug@splint.org
11db3170 22** For more information: http://www.splint.org
65f973be 23*/
24
616915dd 25/*
26*
27** constraintResolve.c
28*/
29
b7b694d6 30/* #define DEBUGPRINT 1 */
616915dd 31
32# include <ctype.h> /* for isdigit */
1b8ae690 33# include "splintMacros.nf"
616915dd 34# include "basic.h"
35# include "cgrammar.h"
36# include "cgrammar_tokens.h"
37
38# include "exprChecks.h"
616915dd 39# include "exprNodeSList.h"
616915dd 40
616915dd 41
393e573f 42/*@access constraint, exprNode @*/ /*!!! NO! Don't do this so recklessly - design your code more carefully so you don't need to! */
43
28bf4b0b 44static constraint inequalitySubstitute (/*@returned@*/ constraint p_c, constraintList p_p);
616915dd 45
616915dd 46
28bf4b0b 47static bool rangeCheck (arithType p_ar1, /*@observer@*/ constraintExpr p_expr1, arithType p_ar2, /*@observer@*/ constraintExpr p_expr2);
616915dd 48
28bf4b0b 49static constraint inequalitySubstituteUnsound (/*@returned@*/ constraint p_c, constraintList p_p);
616915dd 50
dc7f6a51 51static constraint inequalitySubstituteStrong (/*@returned@*/ constraint p_c, constraintList p_p);
52
28bf4b0b 53static constraint constraint_searchandreplace (/*@returned@*/ constraint p_c, constraintExpr p_old, constraintExpr p_newExpr);
bb25bea6 54
28bf4b0b 55
56static constraint constraint_addOr (/*@returned@*/ constraint p_orig, /*@observer@*/ constraint p_orConstr);
57
9a48d98c 58static bool constraint_resolveOr (/*@temp@*/constraint p_c, /*@observer@*/ /*@temp@*/ constraintList p_list);
28bf4b0b 59
60static /*@only@*/ constraintList reflectChangesEnsuresFree1 (/*@only@*/ constraintList p_pre2, constraintList p_post1);
616915dd 61
9a48d98c 62/*@only@*/ constraintList
63constraintList_mergeEnsuresFreeFirst (constraintList list1, constraintList list2)
bb25bea6 64{
9a48d98c 65 constraintList ret = constraintList_mergeEnsures (list1, list2);
66 constraintList_free (list1);
bb25bea6 67 return ret;
68}
616915dd 69
9a48d98c 70/*@only@*/ constraintList
71constraintList_mergeEnsures (constraintList list1, constraintList list2)
616915dd 72{
73 constraintList ret;
74 constraintList temp;
470b7798 75
9a48d98c 76 llassert (constraintList_isDefined (list1));
77 llassert (constraintList_isDefined (list2));
90bc41f7 78
9a48d98c 79 DPRINTF (("constraintList_mergeEnsures: list1 %s list2 %s",
80 constraintList_unparse (list1), constraintList_unparse (list2)));
616915dd 81
90bc41f7 82 ret = constraintList_fixConflicts (list1, list2);
bb25bea6 83 ret = reflectChangesEnsuresFree1 (ret, list2);
d46ce6a4 84 temp = constraintList_subsumeEnsures (ret, list2);
9a48d98c 85 constraintList_free (ret);
d46ce6a4 86
9a48d98c 87 ret = temp;
d46ce6a4 88 temp = constraintList_subsumeEnsures (list2, ret);
616915dd 89 temp = constraintList_addList (temp, ret);
9a48d98c 90 constraintList_free (ret);
4ab867d6 91
9a48d98c 92 DPRINTF (("constraintList_mergeEnsures: returning %s", constraintList_unparse (temp)));
616915dd 93 return temp;
616915dd 94}
95
9a48d98c 96/*@only@*/ constraintList
97constraintList_mergeRequiresFreeFirst (/*@only@*/ constraintList list1,
98 constraintList list2)
bb25bea6 99{
9a48d98c 100 constraintList ret = constraintList_mergeRequires (list1, list2);
101 constraintList_free (list1);
bb25bea6 102 return ret;
103}
104
9a48d98c 105/*@only@*/ constraintList
106constraintList_mergeRequires (constraintList list1, constraintList list2)
470b7798 107{
108 constraintList ret;
109 constraintList temp;
110
9a48d98c 111 DPRINTF (("constraintList_mergeRequires: merging %s and %s",
112 constraintList_unparse (list1), constraintList_unparse (list2)));
470b7798 113
9a48d98c 114 if (context_getFlag (FLG_REDUNDANTCONSTRAINTS))
4a689c7f 115 {
9a48d98c 116 ret = constraintList_copy (list1);
117 ret = constraintList_addList (ret, list2);
4a689c7f 118 return ret;
119 }
9a48d98c 120
470b7798 121 /* get constraints in list1 not satified by list2 */
9a48d98c 122 temp = constraintList_reflectChanges (list1, list2);
123 DPRINTF (("constraintList_mergeRequires: temp = %s", constraintList_unparse (temp)));
124
125 /* get constraints in list2 not satified by temp*/
126 ret = constraintList_reflectChanges (list2, temp);
127 DPRINTF (("constraintList_mergeRequires: ret = %s", constraintList_unparse(ret)));
470b7798 128
4ab867d6 129 ret = constraintList_addListFree (ret, temp);
9a48d98c 130 DPRINTF (("constraintList_mergeRequires: returning %s", constraintList_unparse(ret)));
470b7798 131
470b7798 132 return ret;
133}
616915dd 134
28bf4b0b 135/* old name mergeResolve renamed for czech naming convention */
136void exprNode_mergeResolve (exprNode parent, exprNode child1, exprNode child2)
616915dd 137{
d46ce6a4 138 constraintList temp, temp2;
616915dd 139
9a48d98c 140 DPRINTF((message ("magically merging constraint into parent:%s for", exprNode_unparse (parent))));
616915dd 141
9a48d98c 142 DPRINTF((message (" children: %s and %s", exprNode_unparse (child1), exprNode_unparse(child2))));
616915dd 143
9a48d98c 144 if (exprNode_isUndefined (parent))
a64ebe74 145 {
9a48d98c 146 llassert (exprNode_isDefined (parent));
a64ebe74 147 return;
148 }
149
150
9a48d98c 151 if (exprNode_isError (child1) || exprNode_isError (child2))
d46ce6a4 152 {
9a48d98c 153 if (exprNode_isError (child1) && !exprNode_isError (child2))
616915dd 154 {
9a48d98c 155 constraintList_free (parent->requiresConstraints);
616915dd 156 parent->requiresConstraints = constraintList_copy (child2->requiresConstraints);
9a48d98c 157 constraintList_free (parent->ensuresConstraints);
d46ce6a4 158
616915dd 159 parent->ensuresConstraints = constraintList_copy (child2->ensuresConstraints);
9a48d98c 160 DPRINTF (("Copied child constraints: pre: %s and post: %s",
161 constraintList_unparse(child2->requiresConstraints),
162 constraintList_unparse (child2->ensuresConstraints)));
616915dd 163 return;
164 }
165 else
166 {
9a48d98c 167 llassert (exprNode_isError (child2));
616915dd 168 return;
169 }
170 }
171
9a48d98c 172 llassert (!exprNode_isError (child1) && !exprNode_isError (child2));
616915dd 173
9a48d98c 174 DPRINTF (("Child constraints are %s %s and %s %s",
175 constraintList_unparse (child1->requiresConstraints),
176 constraintList_unparse (child1->ensuresConstraints),
177 constraintList_unparse (child2->requiresConstraints),
178 constraintList_unparse (child2->ensuresConstraints)));
616915dd 179
9a48d98c 180 constraintList_free (parent->requiresConstraints);
181 parent->requiresConstraints = constraintList_copy (child1->requiresConstraints);
182
183 if (context_getFlag (FLG_ORCONSTRAINT))
184 {
185 temp = constraintList_reflectChangesOr (child2->requiresConstraints, child1->ensuresConstraints);
186 }
187 else
188 {
189 temp = constraintList_reflectChanges(child2->requiresConstraints, child1->ensuresConstraints);
190 }
191
192 temp2 = constraintList_mergeRequires (parent->requiresConstraints, temp);
193 constraintList_free (parent->requiresConstraints);
194 constraintList_free (temp);
195
196 parent->requiresConstraints = temp2;
197
198 DPRINTF (("Parent requires constraints are %s ",
199 constraintList_unparse (parent->requiresConstraints)));
200
201 constraintList_free (parent->ensuresConstraints);
202
203 parent->ensuresConstraints = constraintList_mergeEnsures (child1->ensuresConstraints,
204 child2->ensuresConstraints);
205
206
207 DPRINTF (("Parent constraints are %s and %s ",
208 constraintList_unparse (parent->requiresConstraints),
209 constraintList_unparse (parent->ensuresConstraints)));
616915dd 210}
616915dd 211
9a48d98c 212/*@only@*/ constraintList
213constraintList_subsumeEnsures (constraintList list1, constraintList list2)
616915dd 214{
9a48d98c 215 constraintList ret = constraintList_makeNew ();
216
616915dd 217 constraintList_elements (list1, el)
218 {
9a48d98c 219 DPRINTF (("Examining %s", constraint_unparse (el)));
220 if (!constraintList_resolve (el, list2))
616915dd 221 {
9a48d98c 222 constraint temp = constraint_copy (el);
d46ce6a4 223 ret = constraintList_add (ret, temp);
616915dd 224 }
225 else
226 {
9a48d98c 227 DPRINTF (("Subsuming %s", constraint_unparse (el)));
616915dd 228 }
229 } end_constraintList_elements;
230
231 return ret;
232}
233
bb25bea6 234/* tries to resolve constraints in list pre2 using post1 */
9a48d98c 235/*@only@*/ constraintList
236constraintList_reflectChangesFreePre (/*@only@*/ constraintList pre2, /*@observer@*/ constraintList post1)
bb25bea6 237{
9a48d98c 238 constraintList ret = constraintList_reflectChanges(pre2, post1);
bb25bea6 239 constraintList_free (pre2);
bb25bea6 240 return ret;
241}
242
243
dc7f6a51 244
90bc41f7 245/* tries to resolve constraints in list pre2 using post1 */
9a48d98c 246static /*@only@*/ constraintList
247constraintList_reflectChangesNoOr (/*@observer@*/ /*@temp@*/ constraintList pre2,
248 /*@observer@*/ /*@temp@*/ constraintList post1)
616915dd 249{
9a48d98c 250 constraintList ret = constraintList_makeNew ();
616915dd 251
9a48d98c 252 llassert (!context_getFlag (FLG_ORCONSTRAINT));
253
254 DPRINTF (("reflectChanges: lists %s and %s",
255 constraintList_unparse (pre2), constraintList_unparse (post1)));
616915dd 256
257 constraintList_elements (pre2, el)
258 {
9a48d98c 259 if (!constraintList_resolve (el, post1))
616915dd 260 {
9a48d98c 261 constraint temp = constraint_substitute (el, post1);
262
263 if (!constraintList_resolve (temp, post1))
616915dd 264 {
b7b694d6 265 /* try inequality substitution
266 the inequality substitution may cause us to lose information
267 so we don't want to store the result but we do it anyway
268 */
9a48d98c 269 constraint temp2 = constraint_copy (temp);
920a3797 270 temp2 = inequalitySubstitute (temp2, post1);
9a48d98c 271
272 if (!constraintList_resolve (temp2, post1))
920a3797 273 {
274 temp2 = inequalitySubstituteUnsound (temp2, post1);
9a48d98c 275 if (!constraintList_resolve (temp2, post1))
276 {
277 ret = constraintList_add (ret, temp2);
278 }
920a3797 279 else
9a48d98c 280 {
281 constraint_free (temp2);
282 }
920a3797 283 }
284 else
285 {
9a48d98c 286 constraint_free (temp2);
920a3797 287 }
616915dd 288 }
9a48d98c 289 constraint_free (temp);
616915dd 290 }
291 } end_constraintList_elements;
292
9a48d98c 293 DPRINTF (("reflectChanges: returning %s", constraintList_unparse(ret)));
294 return ret;
616915dd 295}
296
dc7f6a51 297/* tries to resolve constraints in list pre2 using post1 */
9a48d98c 298/*@only@*/ constraintList
299constraintList_reflectChanges (/*@observer@*/ constraintList pre2, /*@observer@*/ constraintList post1)
dc7f6a51 300{
9a48d98c 301 if (context_getFlag (FLG_ORCONSTRAINT))
302 {
303 return constraintList_reflectChangesOr (pre2, post1);
304 }
dc7f6a51 305 else
9a48d98c 306 {
307 return constraintList_reflectChangesNoOr (pre2, post1);
308 }
dc7f6a51 309}
616915dd 310
9a48d98c 311static constraint
312constraint_addOr (/*@returned@*/ constraint orig, /*@observer@*/ constraint orConstr)
90bc41f7 313{
9a48d98c 314 constraint c = orig;
315 llassert (constraint_isDefined (c));
a64ebe74 316
9a48d98c 317 DPRINTF (("constraint_addor: oring %s onto %s",
318 constraint_unparseOr (orConstr), constraint_unparseOr (orig)));
90bc41f7 319
320 while (c->or != NULL)
321 {
322 c = c->or;
323 }
a779b61e 324
9a48d98c 325 c->or = constraint_copy (orConstr);
90bc41f7 326
9a48d98c 327 DPRINTF (("constraint_addor: returning %s",constraint_unparseOr (orig)));
90bc41f7 328 return orig;
329}
330
9a48d98c 331static bool constraint_resolveOr (/*@temp@*/ constraint c, /*@observer@*/ /*@temp@*/ constraintList list)
90bc41f7 332{
9a48d98c 333 constraint temp = c;
334 int numberOr = 0;
a64ebe74 335
9a48d98c 336 llassert (constraint_isDefined(c));
337 DPRINTF (("constraint_resolveOr: constraint %s and list %s",
338 constraint_printOr (c), constraintList_print (list)));
a64ebe74 339
90bc41f7 340 do
341 {
9a48d98c 342 if (constraintList_resolve (temp, list))
343 {
344 return TRUE;
345 }
346
90bc41f7 347 temp = temp->or;
a779b61e 348 numberOr++;
349 llassert(numberOr <= 10);
90bc41f7 350 }
9a48d98c 351 while (constraint_isDefined (temp));
90bc41f7 352
353 return FALSE;
354}
355
9a48d98c 356/* This is a "helper" function for doResolveOr */
90bc41f7 357
bb25bea6 358static /*@only@*/ constraint doResolve (/*@only@*/ constraint c, constraintList post1, bool * resolved)
90bc41f7 359{
9a48d98c 360 llassert (constraint_isDefined (c));
a779b61e 361
9a48d98c 362 DPRINTF (("doResolve:: call on constraint c = : %q and constraintList %q",
363 constraint_unparseOr (c), constraintList_unparse (post1)));
90bc41f7 364
9a48d98c 365 if (!constraint_resolveOr (c, post1))
366 {
367 constraint temp = constraint_substitute (c, post1);
368 DPRINTF (("doResolve:: after substitute temp is %q", constraint_unparseOr (temp)));
d9daf826 369
9a48d98c 370 if (!constraint_resolveOr (temp, post1))
90bc41f7 371 {
b7b694d6 372 /* try inequality substitution */
9a48d98c 373 constraint temp2 = constraint_copy (c);
bb25bea6 374
9a48d98c 375 /*
376 ** the inequality substitution may cause us to lose information
377 ** so we don't want to store the result but we do anyway
b7b694d6 378 */
9a48d98c 379
b7b694d6 380 temp2 = inequalitySubstitute (temp2, post1);
381
9a48d98c 382 if (!constraint_resolveOr (temp2, post1))
b7b694d6 383 {
9a48d98c 384 constraint temp3 = constraint_copy(temp2);
b7b694d6 385 temp3 = inequalitySubstituteStrong (temp3, post1);
9a48d98c 386
387 if (!constraint_resolveOr (temp3, post1))
bb25bea6 388 {
b7b694d6 389 temp2 = inequalitySubstituteUnsound (temp2, post1);
9a48d98c 390
391 if (!constraint_resolveOr (temp2, post1))
dc7f6a51 392 {
9a48d98c 393 if (!constraint_same (temp, temp2))
d9daf826 394 {
395 /* drl added 8/28/2002*/
396 /*make sure that the information from
397 a post condition like i = i + 1 is transfered
398 */
399 constraint tempSub;
400 tempSub = constraint_substitute (temp2, post1);
401
9a48d98c 402 DPRINTF (("doResolve: adding %s", constraint_unparseOr (tempSub)));
403 DPRINTF (("doResolve: not adding %s", constraint_unparseOr (temp2)));
404
d9daf826 405 temp = constraint_addOr (temp, tempSub);
9a48d98c 406 constraint_free (tempSub);
d9daf826 407 }
9a48d98c 408
409 if (!constraint_same (temp, temp3) && !constraint_same (temp3, temp2))
d9daf826 410 {
9a48d98c 411 /* drl added 8/28/2002*/
412 /* make sure that the information from
413 a post condition like i = i + 1 is transfered
d9daf826 414 */
415 constraint tempSub;
416
417 tempSub = constraint_substitute (temp3, post1);
418
9a48d98c 419 DPRINTF (("doResolve: adding %s", constraint_unparseOr (tempSub)));
420 DPRINTF (("doResolve: not adding %s", constraint_unparseOr(temp3)));
d9daf826 421
422 temp = constraint_addOr (temp, tempSub);
d9daf826 423 constraint_free(tempSub);
424 }
9a48d98c 425
b7b694d6 426 *resolved = FALSE;
427
9a48d98c 428 constraint_free (temp2);
429 constraint_free (temp3);
430 constraint_free (c);
b7b694d6 431
432 return temp;
bb25bea6 433 }
9a48d98c 434
435 constraint_free (temp2);
436 constraint_free (temp3);
bb25bea6 437 }
dc7f6a51 438 else
439 {
9a48d98c 440 constraint_free (temp2);
441 constraint_free (temp3);
b7b694d6 442 }
90bc41f7 443 }
b7b694d6 444 else
445 {
9a48d98c 446 constraint_free (temp2);
b7b694d6 447 }
448
90bc41f7 449 }
9a48d98c 450 constraint_free (temp);
b7b694d6 451 }
9a48d98c 452
453 constraint_free (c);
454 /*@i523@*/ /*drl bee: pbr*/ *resolved = TRUE;
b7b694d6 455 return NULL;
90bc41f7 456}
457
9a48d98c 458static /*@only@*/ constraint
459doResolveOr (/*@observer@*/ /*@temp@*/ constraint c, constraintList post1, /*@out@*/ bool *resolved)
90bc41f7 460{
461 constraint ret;
462 constraint next;
463 constraint curr;
a779b61e 464
9a48d98c 465 DPRINTF (("doResolveOr: constraint %s and list %s",
466 constraint_unparseOr (c), constraintList_unparse (post1)));
90bc41f7 467
9a48d98c 468 /*@i523@*/ /*drl bee: pbr*/ *resolved = FALSE;
469
470 llassert (constraint_isDefined (c));
471 ret = constraint_copy (c);
a779b61e 472
9a48d98c 473 llassert (constraint_isDefined (ret));
a64ebe74 474
9a48d98c 475 if (constraintList_isEmpty (post1))
a779b61e 476 {
477 return ret;
478 }
479
90bc41f7 480 next = ret->or;
481 ret->or = NULL;
482
483 ret = doResolve (ret, post1, resolved);
9a48d98c 484
bb25bea6 485 if (*resolved)
486 {
2934b455 487 if (next != NULL)
9a48d98c 488 {
489 constraint_free (next);
490 }
920a3797 491
9a48d98c 492 /* we don't need to free ret when resolved is false because ret is null*/
493 llassert (ret == NULL);
a779b61e 494 return NULL;
bb25bea6 495 }
a779b61e 496
84c9ffbf 497 while (next != NULL)
90bc41f7 498 {
499 curr = next;
500 next = curr->or;
501 curr->or = NULL;
9a48d98c 502
90bc41f7 503 curr = doResolve (curr, post1, resolved);
a779b61e 504
9a48d98c 505 /*@i423@*/ /*drl bee: pbr*/ if (*resolved)
bb25bea6 506 {
4ab867d6 507 /* curr is null so we don't try to free it*/
9a48d98c 508 llassert (curr == NULL);
4ab867d6 509
2934b455 510 if (next != NULL)
9a48d98c 511 {
512 constraint_free (next);
513 }
920a3797 514
9a48d98c 515 constraint_free (ret);
920a3797 516 return NULL;
bb25bea6 517 }
90bc41f7 518 ret = constraint_addOr (ret, curr);
4ab867d6 519 constraint_free(curr);
90bc41f7 520 }
90bc41f7 521 return ret;
522}
523
90bc41f7 524/* tries to resolve constraints in list pr2 using post1 */
9a48d98c 525/*@only@*/ constraintList
526constraintList_reflectChangesOr (constraintList pre2, constraintList post1)
90bc41f7 527{
528 bool resolved;
529 constraintList ret;
530 constraint temp;
c3e695ff 531 ret = constraintList_makeNew();
9a48d98c 532
533 DPRINTF (("constraintList_reflectChangesOr: lists %s and %s",
534 constraintList_unparse (pre2), constraintList_unparse (post1)));
90bc41f7 535
536 constraintList_elements (pre2, el)
537 {
538 temp = doResolveOr (el, post1, &resolved);
9a48d98c 539
90bc41f7 540 if (!resolved)
541 {
542 ret = constraintList_add(ret, temp);
543 }
920a3797 544 else
545 {
9a48d98c 546 /* we don't need to free temp when
547 resolved is false because temp is null */
548 llassert (temp == NULL);
920a3797 549 }
90bc41f7 550 } end_constraintList_elements;
9a48d98c 551
552 DPRINTF (("constraintList_reflectChangesOr: returning %s", constraintList_unparse (ret)));
553 return ret;
90bc41f7 554}
a779b61e 555
9a48d98c 556static /*@only@*/ constraintList
557reflectChangesEnsures (/*@observer@*/ constraintList pre2, constraintList post1)
616915dd 558{
9a48d98c 559 constraintList ret = constraintList_makeNew ();
560
616915dd 561 constraintList_elements (pre2, el)
562 {
9a48d98c 563 if (!constraintList_resolve (el, post1))
616915dd 564 {
9a48d98c 565 constraint temp = constraint_substitute (el, post1);
616915dd 566 llassert (temp != NULL);
9a48d98c 567
568 if (!constraintList_resolve (temp, post1))
569 {
570 ret = constraintList_add (ret, temp);
571 }
920a3797 572 else
9a48d98c 573 {
574 constraint_free (temp);
575 }
616915dd 576 }
577 else
578 {
9a48d98c 579 DPRINTF (("Resolved away %s ", constraint_unparse(el)));
616915dd 580 }
581 } end_constraintList_elements;
9a48d98c 582
583 return ret;
616915dd 584}
585
586
9a48d98c 587static /*@only@*/ constraintList
588reflectChangesEnsuresFree1 (/*@only@*/ constraintList pre2, constraintList post1)
bb25bea6 589{
9a48d98c 590 constraintList ret = reflectChangesEnsures (pre2, post1);
bb25bea6 591 constraintList_free(pre2);
bb25bea6 592 return ret;
593}
594
595
596static bool constraint_conflict (constraint c1, constraint c2)
616915dd 597{
9a48d98c 598 llassert (constraint_isDefined (c1));
599 llassert (constraint_isDefined (c2));
a64ebe74 600
9a48d98c 601 if (constraintExpr_similar (c1->lexpr, c2->lexpr))
616915dd 602 {
9a48d98c 603 if (c1->ar == EQ && (c1->ar == c2->ar))
604 {
605 DPRINTF (("%s conflicts with %s ", constraint_unparse (c1), constraint_unparse(c2)));
606 return TRUE;
607 }
616915dd 608 }
9a48d98c 609
610 /*
611 ** This is a slight kludge to prevent circular constraints like
612 ** strlen(str) == maxRead(s) + strlen(str);
b7b694d6 613 */
a779b61e 614
9a48d98c 615 if (c1->ar == EQ && (c1->ar == c2->ar))
616 {
617 if (constraintExpr_search (c1->lexpr, c2->expr))
618 {
619 if (constraintExpr_isTerm (c1->lexpr))
a779b61e 620 {
9a48d98c 621 constraintTerm term = constraintExpr_getTerm (c1->lexpr);
a779b61e 622
9a48d98c 623 if (constraintTerm_isExprNode (term))
a779b61e 624 {
9a48d98c 625 DPRINTF (("%s conflicts with %s ", constraint_unparse (c1),
626 constraint_unparse (c2)));
a779b61e 627 return TRUE;
628 }
629 }
a779b61e 630 }
9a48d98c 631 }
616915dd 632
9a48d98c 633 if (constraint_tooDeep (c1) || constraint_tooDeep (c2))
634 {
635 DPRINTF (("%s conflicts with %s (constraint is too deep)",
636 constraint_unparse (c1), constraint_unparse (c2)));
637 return TRUE;
638 }
639
640 DPRINTF (("%s doesn't conflict with %s",
641 constraint_unparse (c1), constraint_unparse (c2)));
616915dd 642 return FALSE;
616915dd 643}
644
9a48d98c 645static void
646constraint_fixConflict (/*@temp@*/ constraint good,
647 /*@temp@*/ /*@observer@*/ constraint conflicting)
648 /*@modifies good@*/
616915dd 649{
9a48d98c 650 llassert (constraint_isDefined (conflicting));
a64ebe74 651
9a48d98c 652 if (conflicting->ar ==EQ)
616915dd 653 {
9a48d98c 654 llassert (constraint_isDefined (good));
616915dd 655 good->expr = constraintExpr_searchandreplace (good->expr, conflicting->lexpr, conflicting->expr);
d46ce6a4 656 good = constraint_simplify (good);
616915dd 657 }
616915dd 658}
659
bb25bea6 660static bool conflict (constraint c, constraintList list)
616915dd 661{
90bc41f7 662 constraintList_elements (list, el)
616915dd 663 {
9a48d98c 664 if (constraint_conflict (el, c))
616915dd 665 {
666 constraint_fixConflict (el, c);
667 return TRUE;
668 }
669 } end_constraintList_elements;
9a48d98c 670
671 return FALSE;
616915dd 672}
673
b7b694d6 674/*
9a48d98c 675** Check if constraint in list1 conflicts with constraints in List2. If so we
676** remove form list1 and change list2.
b7b694d6 677*/
678
84c9ffbf 679constraintList constraintList_fixConflicts (constraintList list1, constraintList list2)
616915dd 680{
9a48d98c 681 constraintList ret = constraintList_makeNew ();
682 llassert (constraintList_isDefined (list1));
683
616915dd 684 constraintList_elements (list1, el)
685 {
9a48d98c 686 if (!conflict (el, list2))
616915dd 687 {
9a48d98c 688 constraint temp = constraint_copy (el);
d46ce6a4 689 ret = constraintList_add (ret, temp);
616915dd 690 }
691 } end_constraintList_elements;
9a48d98c 692
693 return ret;
616915dd 694}
695
9a48d98c 696/* Returns true if constraint post satifies constraint pre */
bb25bea6 697static bool satifies (constraint pre, constraint post)
616915dd 698{
9a48d98c 699 llassert (constraint_isDefined (pre));
700 llassert (constraint_isDefined (post));
a64ebe74 701
9a48d98c 702 if (constraint_isAlwaysTrue (pre))
703 {
704 return TRUE;
705 }
616915dd 706
9a48d98c 707 if (!constraintExpr_similar (pre->lexpr, post->lexpr))
616915dd 708 {
9a48d98c 709 return TRUE;
616915dd 710 }
9a48d98c 711
712 if (!constraintExpr_similar (pre->lexpr, post->lexpr))
616915dd 713 {
616915dd 714 return FALSE;
715 }
9a48d98c 716
717 llassertretval (!constraintExpr_isUndefined (post->expr), FALSE);
616915dd 718 return rangeCheck (pre->ar, pre->expr, post->ar, post->expr);
719}
720
9a48d98c 721bool
722constraintList_resolve (/*@observer@*/ constraint c,
723 /*@observer@*/ constraintList p)
bb25bea6 724{
725 constraintList_elements (p, el)
726 {
9a48d98c 727 if (satifies (c, el))
bb25bea6 728 {
9a48d98c 729 DPRINTF (("%s satifies %s", constraint_unparse (el), constraint_unparse(c)));
bb25bea6 730 return TRUE;
731 }
9a48d98c 732 DPRINTF (("%s does not satify %s", constraint_unparse (el), constraint_unparse (c)));
733 } end_constraintList_elements;
734
735 DPRINTF (("no constraints satisfy %s", constraint_unparse (c)));
bb25bea6 736 return FALSE;
737}
738
739static bool arithType_canResolve (arithType ar1, arithType ar2)
616915dd 740{
741 switch (ar1)
742 {
743 case GTE:
744 case GT:
9a48d98c 745 if ((ar2 == GT) || (ar2 == GTE) || (ar2 == EQ))
616915dd 746 {
747 return TRUE;
748 }
749 break;
750
751 case EQ:
752 if (ar2 == EQ)
753 return TRUE;
754 break;
755
756 case LT:
757 case LTE:
9a48d98c 758 if ((ar2 == LT) || (ar2 == LTE) || (ar2 == EQ))
616915dd 759 return TRUE;
84c9ffbf 760 break;
616915dd 761 default:
762 return FALSE;
763 }
764 return FALSE;
765}
766
9a48d98c 767/* Checks for the case expr2 == sizeof buf1 and buf1 is a fixed array*/
e5f31c00 768static bool sizeofBufComp(constraintExpr buf1, constraintExpr expr2)
769{
770 constraintTerm ct;
771 exprNode e, t;
772 sRef s1, s2;
a64ebe74 773
9a48d98c 774 llassert (constraintExpr_isDefined (buf1) && constraintExpr_isDefined (expr2));
a64ebe74 775
9a48d98c 776 /*@i6343 rewrite this to not need access, or move to constraintExpr module */
e5f31c00 777 /*@access constraintExpr@*/
778
9a48d98c 779 if ((expr2->kind != term) && (buf1->kind != term))
780 {
781 return FALSE;
782 }
e5f31c00 783
784 ct = constraintExprData_termGetTerm(expr2->data);
9a48d98c 785
786 if (!constraintTerm_isExprNode(ct))
787 {
788 return FALSE;
789 }
e5f31c00 790
9a48d98c 791 e = constraintTerm_getExprNode (ct);
792
793 llassert (exprNode_isDefined(e));
794
795 if (!exprNode_isDefined (e))
796 {
797 return FALSE;
798 }
a64ebe74 799
e5f31c00 800 if (e->kind != XPR_SIZEOF)
9a48d98c 801 {
802 return FALSE;
803 }
e5f31c00 804
805 t = exprData_getSingle (e->edata);
e5f31c00 806
9a48d98c 807 s1 = exprNode_getSref (t);
808 s2 = constraintTerm_getsRef(constraintExprData_termGetTerm(buf1->data));
e5f31c00 809
810 /*@i223@*/ /*this may be the wronge thing to test for */
9a48d98c 811 if (sRef_similarRelaxed(s1, s2) || sRef_sameName (s1, s2))
e5f31c00 812 {
e5508969 813 /*@i22*/ /* get rid of this test of now */
9a48d98c 814 /* if (ctype_isFixedArray (sRef_getType (s2))) */
e5f31c00 815 return TRUE;
816 }
817 return FALSE;
818}
819
820/* look for the special case of
821 maxSet(buf) >= sizeof(buf) - 1
822*/
823
824/*@i223@*/ /*need to add some type checking */
332e22fa 825
e5f31c00 826static bool sizeOfMaxSet( /*@observer@*/ /*@temp@*/ constraint c)
827{
828 constraintExpr l, r, buf1, buf2, con;
9a48d98c 829
830 DPRINTF (("sizeOfMaxSet: checking %s ", constraint_unparse (c)));
831 llassert (constraint_isDefined (c));
e5f31c00 832
e5f31c00 833 l = c->lexpr;
834 r = c->expr;
9a48d98c 835
836 if (!((c->ar == EQ) || (c->ar == GTE) || (c->ar == LTE)))
837 {
838 return FALSE;
839 }
e5f31c00 840
9a48d98c 841 llassert (constraintExpr_isDefined (l));
842 llassert (constraintExpr_isDefined (r));
e5f31c00 843
9a48d98c 844 /* Check if the constraintExpr is MaxSet(buf) */
a64ebe74 845
e5f31c00 846 if (l->kind == unaryExpr)
847 {
848 if (constraintExprData_unaryExprGetOp(l->data) == MAXSET)
849 {
850 buf1 = constraintExprData_unaryExprGetExpr(l->data);
851 }
852 else
9a48d98c 853 {
854 return FALSE;
855 }
e5f31c00 856 }
857 else
9a48d98c 858 {
859 return FALSE;
860 }
e5f31c00 861
862 if (r->kind != binaryexpr)
9a48d98c 863 {
864 return FALSE;
865 }
e5f31c00 866
9a48d98c 867 buf2 = constraintExprData_binaryExprGetExpr1 (r->data);
868 con = constraintExprData_binaryExprGetExpr2 (r->data);
e5f31c00 869
9a48d98c 870 if (constraintExprData_binaryExprGetOp (r->data) == BINARYOP_MINUS)
e5f31c00 871 {
9a48d98c 872 if (constraintExpr_canGetValue (con))
e5f31c00 873 {
9a48d98c 874 long i = constraintExpr_getValue (con);
875
e5f31c00 876 if (i != 1)
877 {
878 return FALSE;
879 }
880 }
881 else
9a48d98c 882 {
883 return FALSE;
884 }
e5f31c00 885 }
886
9a48d98c 887 if (constraintExprData_binaryExprGetOp (r->data) == BINARYOP_PLUS)
e5f31c00 888 {
9a48d98c 889 if (constraintExpr_canGetValue (con))
e5f31c00 890 {
9a48d98c 891 long i = constraintExpr_getValue (con);
e5f31c00 892
e5f31c00 893 if (i != -1)
894 {
895 return FALSE;
896 }
897 }
898 else
9a48d98c 899 {
900 return FALSE;
901 }
e5f31c00 902 }
9a48d98c 903
904 return (sizeofBufComp (buf1, buf2));
e5f31c00 905}
9a48d98c 906/*@i8423@*/
e5f31c00 907/*@noaccess constraintExpr@*/
908
90bc41f7 909/* We look for constraint which are tautologies */
910
28bf4b0b 911bool constraint_isAlwaysTrue (/*@observer@*/ /*@temp@*/ constraint c)
616915dd 912{
913 constraintExpr l, r;
15b3d2b2 914 bool rHasConstant;
915 int rConstant;
a64ebe74 916
9a48d98c 917 llassert (constraint_isDefined (c));
9280addf 918
616915dd 919 l = c->lexpr;
920 r = c->expr;
90bc41f7 921
9a48d98c 922 DPRINTF((message("constraint_IsAlwaysTrue:examining %s", constraint_unparse(c))));
e5f31c00 923
9a48d98c 924 if (sizeOfMaxSet(c))
e5f31c00 925 return TRUE;
926
9a48d98c 927 if (constraintExpr_canGetValue(l) && constraintExpr_canGetValue(r))
616915dd 928 {
929 int cmp;
930 cmp = constraintExpr_compare (l, r);
931 switch (c->ar)
932 {
933 case EQ:
934 return (cmp == 0);
935 case GT:
936 return (cmp > 0);
937 case GTE:
938 return (cmp >= 0);
939 case LTE:
940 return (cmp <= 0);
941 case LT:
942 return (cmp < 0);
943
944 default:
9280addf 945 BADEXIT;
84c9ffbf 946 /*@notreached@*/
9280addf 947 break;
948 }
949 }
950
9a48d98c 951 if (constraintExpr_similar (l,r))
9280addf 952 {
953 switch (c->ar)
954 {
955 case EQ:
956 case GTE:
957 case LTE:
958 return TRUE;
959
960 case GT:
961 case LT:
962 break;
963 default:
964 BADEXIT;
84c9ffbf 965 /*@notreached@*/
616915dd 966 break;
967 }
968 }
9280addf 969
970 l = constraintExpr_copy (c->lexpr);
971 r = constraintExpr_copy (c->expr);
972
9280addf 973 r = constraintExpr_propagateConstants (r, &rHasConstant, &rConstant);
974
9a48d98c 975 if (constraintExpr_similar (l,r) && (rHasConstant))
9280addf 976 {
9a48d98c 977 DPRINTF((message("constraint_IsAlwaysTrue: after removing constants %s and %s are similar", constraintExpr_unparse(l), constraintExpr_unparse(r))));
978 DPRINTF((message("constraint_IsAlwaysTrue: rconstant is %d", rConstant)));
bb25bea6 979
980 constraintExpr_free(l);
981 constraintExpr_free(r);
982
90bc41f7 983 switch (c->ar)
9280addf 984 {
90bc41f7 985 case EQ:
986 return (rConstant == 0);
987 case LT:
988 return (rConstant > 0);
989 case LTE:
990 return (rConstant >= 0);
991 case GTE:
992 return (rConstant <= 0);
993 case GT:
994 return (rConstant < 0);
995
996 default:
997 BADEXIT;
84c9ffbf 998 /*@notreached@*/
90bc41f7 999 break;
9280addf 1000 }
9280addf 1001 }
90bc41f7 1002 else
1003 {
bb25bea6 1004 constraintExpr_free(l);
1005 constraintExpr_free(r);
9a48d98c 1006 DPRINTF((message("Constraint %s is not always true", constraint_unparse(c))));
90bc41f7 1007 return FALSE;
1008 }
9280addf 1009
1010 BADEXIT;
616915dd 1011}
1012
bb25bea6 1013static bool rangeCheck (arithType ar1, /*@observer@*/ constraintExpr expr1, arithType ar2, /*@observer@*/ constraintExpr expr2)
616915dd 1014
1015{
9a48d98c 1016 DPRINTF ((message ("Doing Range CHECK %s and %s", constraintExpr_unparse(expr1), constraintExpr_unparse(expr2))));
616915dd 1017
9a48d98c 1018 if (! arithType_canResolve (ar1, ar2))
616915dd 1019 return FALSE;
1020
1021 switch (ar1)
1022 {
1023 case GTE:
9a48d98c 1024 if (constraintExpr_similar (expr1, expr2))
2681ee39 1025 return TRUE;
1026 /*@fallthrough@*/
1027 case GT:
616915dd 1028 if (! (constraintExpr_canGetValue (expr1) &&
9a48d98c 1029 constraintExpr_canGetValue (expr2)))
2681ee39 1030 {
1031 constraintExpr e1, e2;
1032 bool p1, p2;
1033 int const1, const2;
1034
1035 e1 = constraintExpr_copy(expr1);
1036 e2 = constraintExpr_copy(expr2);
1037
1038 e1 = constraintExpr_propagateConstants (e1, &p1, &const1);
1039
1040 e2 = constraintExpr_propagateConstants (e2, &p2, &const2);
1041
1042 if (p1 || p2)
1043 {
1044 if (!p1)
1045 const1 = 0;
1046
1047 if (!p2)
1048 const2 = 0;
1049
1050 if (const1 <= const2)
9a48d98c 1051 if (constraintExpr_similar (e1, e2))
2681ee39 1052 {
1053 constraintExpr_free(e1);
1054 constraintExpr_free(e2);
1055 return TRUE;
1056 }
1057 }
bb7c2085 1058 DPRINTF(("Can't Get value"));
2681ee39 1059
1060 constraintExpr_free(e1);
1061 constraintExpr_free(e2);
1062 return FALSE;
1063 }
1064
1065 if (constraintExpr_compare (expr2, expr1) >= 0)
1066 return TRUE;
616915dd 1067
1068 return FALSE;
2681ee39 1069 case EQ:
9a48d98c 1070 if (constraintExpr_similar (expr1, expr2))
2681ee39 1071 return TRUE;
1072
1073 return FALSE;
1074 case LTE:
9a48d98c 1075 if (constraintExpr_similar (expr1, expr2))
2681ee39 1076 return TRUE;
1077 /*@fallthrough@*/
1078 case LT:
1079 if (! (constraintExpr_canGetValue (expr1) &&
9a48d98c 1080 constraintExpr_canGetValue (expr2)))
2681ee39 1081 {
1082 constraintExpr e1, e2;
1083 bool p1, p2;
1084 int const1, const2;
1085
1086 e1 = constraintExpr_copy(expr1);
1087 e2 = constraintExpr_copy(expr2);
1088
1089 e1 = constraintExpr_propagateConstants (e1, &p1, &const1);
1090
1091 e2 = constraintExpr_propagateConstants (e2, &p2, &const2);
1092
1093 if (p1 || p2)
1094 {
1095 if (!p1)
1096 const1 = 0;
1097
1098 if (!p2)
1099 const2 = 0;
1100
1101 if (const1 >= const2)
9a48d98c 1102 if (constraintExpr_similar (e1, e2))
2681ee39 1103 {
1104 constraintExpr_free(e1);
1105 constraintExpr_free(e2);
1106 return TRUE;
1107 }
1108 }
1109 constraintExpr_free(e1);
1110 constraintExpr_free(e2);
1111
bb7c2085 1112 DPRINTF(("Can't Get value"));
2681ee39 1113 return FALSE;
1114 }
1115
1116 if (constraintExpr_compare (expr2, expr1) <= 0)
1117 return TRUE;
1118
1119 return FALSE;
1120
1121 default:
9a48d98c 1122 llcontbug((message("Unhandled case in switch: %q", arithType_print(ar1))));
2681ee39 1123 }
616915dd 1124 BADEXIT;
616915dd 1125}
1126
28bf4b0b 1127static constraint constraint_searchandreplace (/*@returned@*/ constraint c, constraintExpr old, constraintExpr newExpr)
616915dd 1128{
9a48d98c 1129 llassert (constraint_isDefined (c));
1130 DPRINTF (("Doing replace for lexpr"));
a64ebe74 1131
28bf4b0b 1132 c->lexpr = constraintExpr_searchandreplace (c->lexpr, old, newExpr);
9a48d98c 1133 DPRINTF (("Doing replace for expr"));
28bf4b0b 1134 c->expr = constraintExpr_searchandreplace (c->expr, old, newExpr);
616915dd 1135 return c;
1136}
1137
84c9ffbf 1138bool constraint_search (constraint c, constraintExpr old) /*@*/
616915dd 1139{
9a48d98c 1140 bool ret = FALSE;
a64ebe74 1141
9a48d98c 1142 llassert (constraint_isDefined (c));
a64ebe74 1143
616915dd 1144 ret = constraintExpr_search (c->lexpr, old);
1145 ret = ret || constraintExpr_search (c->expr, old);
1146 return ret;
1147}
1148
b7b694d6 1149/* adjust file locs and stuff */
bb25bea6 1150static constraint constraint_adjust (/*@returned@*/ constraint substitute, /*@observer@*/ constraint old)
616915dd 1151{
1152 fileloc loc1, loc2, loc3;
1153
9a48d98c 1154 DPRINTF (("Start adjust on %s and %s", constraint_unparse (substitute),
1155 constraint_unparse (old)));
616915dd 1156
9a48d98c 1157 llassert (constraint_isDefined (substitute));
1158 llassert (constraint_isDefined (old));
a64ebe74 1159
616915dd 1160 loc1 = constraint_getFileloc (old);
616915dd 1161 loc2 = constraintExpr_getFileloc (substitute->lexpr);
616915dd 1162 loc3 = constraintExpr_getFileloc (substitute->expr);
616915dd 1163
b7b694d6 1164 /* special case of an equality that "contains itself" */
9a48d98c 1165 if (constraintExpr_search (substitute->expr, substitute->lexpr))
1166 {
616915dd 1167 if (fileloc_closer (loc1, loc3, loc2))
9a48d98c 1168 {
1169 constraintExpr temp;
1170 DPRINTF (("Doing adjust on %s", constraint_unparse(substitute)));
1171 temp = substitute->lexpr;
1172 substitute->lexpr = substitute->expr;
1173 substitute->expr = temp;
1174 substitute = constraint_simplify(substitute);
1175 }
1176 }
1177
bb25bea6 1178 fileloc_free (loc1);
1179 fileloc_free (loc2);
1180 fileloc_free (loc3);
616915dd 1181 return substitute;
616915dd 1182}
1183
9a48d98c 1184/*
1185** If function preforms substitutes based on inequality
1186** It uses the rule x >= y && b < y ===> x >= b + 1
1187** warning this is sound but throws out information.
1188*/
dc7f6a51 1189
9a48d98c 1190constraint inequalitySubstitute (/*@returned@*/ constraint c, constraintList p)
616915dd 1191{
9a48d98c 1192 llassert (constraint_isDefined (c));
1193
616915dd 1194 if (c->ar != GTE)
9a48d98c 1195 {
1196 return c;
1197 }
616915dd 1198
1199 constraintList_elements (p, el)
1200 {
9a48d98c 1201 llassert (constraint_isDefined (el));
a64ebe74 1202
9a48d98c 1203 if ((el->ar == LT ))
1204 /* if (!constraint_conflict (c, el) ) */ /*@i523 explain this! */
1205 {
1206 constraintExpr temp2;
1207
1208 /*@i22*/
1209
1210 if (constraintExpr_same (el->expr, c->expr))
1211 {
1212 DPRINTF (("inequalitySubstitute Replacing %q in %q with %q",
1213 constraintExpr_print (c->expr),
1214 constraint_unparse (c),
1215 constraintExpr_print (el->expr)));
1216 temp2 = constraintExpr_copy (el->lexpr);
1217 constraintExpr_free(c->expr);
1218 c->expr = constraintExpr_makeIncConstraintExpr (temp2);
1219 }
1220 }
1221 } end_constraintList_elements;
1222
1223 c = constraint_simplify (c);
616915dd 1224 return c;
1225}
1226
dc7f6a51 1227/* drl7x 7/26/001
1228
1229 THis function is like inequalitySubstitute but it adds the rule
1230 added the rules x >= y && y <= b ===> x >= b
1231 x >= y && y < b ===> x >= b + 1
1232
1233 This is sound but sonce it throws out additional information it should only one used
1234 if we're oring constraints.
1235 */
1236
9a48d98c 1237static constraint inequalitySubstituteStrong (/*@returned@*/ constraint c, constraintList p)
dc7f6a51 1238{
9a48d98c 1239 DPRINTF (("inequalitySubstituteStrong examining substituting for %q", constraint_unparse(c)));
1240 llassert (constraint_isDefined (c));
dc7f6a51 1241
9a48d98c 1242 if (!constraint_isDefined (c))
1243 {
1244 return c;
1245 }
a64ebe74 1246
dc7f6a51 1247 if (c->ar != GTE)
9a48d98c 1248 {
1249 return c;
1250 }
dc7f6a51 1251
9a48d98c 1252 DPRINTF (("inequalitySubstituteStrong examining substituting for %q with %q",
1253 constraint_unparse (c), constraintList_unparse (p)));
1254
dc7f6a51 1255 constraintList_elements (p, el)
1256 {
9a48d98c 1257 DPRINTF (("inequalitySubstituteStrong examining substituting %s on %s",
1258 constraint_unparse (el), constraint_unparse (c)));
dc7f6a51 1259
9a48d98c 1260 llassert (constraint_isDefined (el));
1261
1262 if ((el->ar == LT ) || (el->ar == LTE))
b7b694d6 1263 /* if (!constraint_conflict (c, el) ) */ /*@i523@*/
9a48d98c 1264 {
1265 constraintExpr temp2;
1266
1267 /*@i22*/
1268 if (constraintExpr_same (el->lexpr, c->expr))
1269 {
1270 DPRINTF (("inequalitySubstitute Replacing %s in %s with %s",
1271 constraintExpr_print (c->expr),
1272 constraint_unparse (c),
1273 constraintExpr_print (el->expr)));
dc7f6a51 1274
9a48d98c 1275 temp2 = constraintExpr_copy (el->expr);
1276 constraintExpr_free (c->expr);
1277
1278 if ((el->ar == LTE))
1279 {
1280 c->expr = temp2;
1281 }
1282 else
1283 {
1284 c->expr = constraintExpr_makeIncConstraintExpr (temp2);
1285 }
1286 }
1287
1288 }
1289 } end_constraintList_elements;
1290
dc7f6a51 1291 c = constraint_simplify(c);
1292 return c;
1293}
1294
1295
90bc41f7 1296/* This function performs substitutions based on the rule:
1297 for a constraint of the form expr1 >= expr2; a < b =>
1298 a = b -1 for all a in expr1. This will work in most cases.
1299
1300 Like inequalitySubstitute we're throwing away some information
1301*/
1302
9a48d98c 1303static constraint inequalitySubstituteUnsound (/*@returned@*/ constraint c, constraintList p)
90bc41f7 1304{
9a48d98c 1305 DPRINTF (("Doing inequalitySubstituteUnsound"));
1306 llassert (constraint_isDefined (c));
90bc41f7 1307
1308 if (c->ar != GTE)
9a48d98c 1309 {
1310 return c;
1311 }
90bc41f7 1312
1313 constraintList_elements (p, el)
1314 {
9a48d98c 1315 llassert (constraint_isDefined (el));
1316
1317 DPRINTF (("inequalitySubstituteUnsound examining substituting %s on %s",
1318 constraint_unparse (el), constraint_unparse (c)));
1319 if (( el->ar == LTE) || (el->ar == LT))
1320 /* if (!constraint_conflict (c, el) ) */ /*@i532@*/
1321 {
1322 constraintExpr temp2 = constraintExpr_copy (el->expr);
1323
1324 if (el->ar == LT)
1325 {
1326 temp2 = constraintExpr_makeDecConstraintExpr (temp2);
1327 }
1328
1329 DPRINTF (("Replacing %s in %s with %s",
1330 constraintExpr_print (el->lexpr),
1331 constraintExpr_print (c->lexpr),
1332 constraintExpr_print (temp2)));
1333
1334 c->lexpr = constraintExpr_searchandreplace (c->lexpr, el->lexpr, temp2);
1335 constraintExpr_free(temp2);
1336 }
1337 } end_constraintList_elements;
1338
1339 c = constraint_simplify (c);
90bc41f7 1340 return c;
1341}
1342
28bf4b0b 1343/*@only@*/ constraint constraint_substitute (/*@observer@*/ /*@temp@*/ constraint c, constraintList p)
616915dd 1344{
9a48d98c 1345 constraint ret = constraint_copy (c);
1346
616915dd 1347 constraintList_elements (p, el)
1348 {
9a48d98c 1349 llassert (constraint_isDefined (el));
1350 if (el->ar == EQ)
1351 {
1352 if (!constraint_conflict (ret, el))
1353 {
1354 constraint temp = constraint_copy (el);
1355 temp = constraint_adjust (temp, ret);
1356
1357 llassert (constraint_isDefined (temp));
1358
1359 DPRINTF (("constraint_substitute :: Substituting in %s using %s",
1360 constraint_unparse (ret), constraint_unparse (temp)));
1361
1362 ret = constraint_searchandreplace (ret, temp->lexpr, temp->expr);
1363
1364 DPRINTF (("constraint_substitute :: The new constraint is %s", constraint_unparse (ret)));
1365 constraint_free (temp);
1366 }
1367 }
1368 } end_constraintList_elements;
1369
1370 ret = constraint_simplify (ret);
1371 DPRINTF (("constraint_substitute :: The final new constraint is %s", constraint_unparse (ret)));
90bc41f7 1372 return ret;
616915dd 1373}
1374
9a48d98c 1375/*@only@*/ constraintList
1376constraintList_substituteFreeTarget (/*@only@*/ constraintList target,
1377 /*@observer@*/ constraintList subList)
bb25bea6 1378{
9a48d98c 1379 constraintList ret = constraintList_substitute (target, subList);
1380 constraintList_free(target);
1381 return ret;
bb25bea6 1382}
1383
c3e695ff 1384/* we try to do substitutions on each constraint in target using the constraint in sublist*/
1385
9a48d98c 1386/*@only@*/ constraintList
1387constraintList_substitute (constraintList target, /*@observer@*/ constraintList subList)
c3e695ff 1388{
9a48d98c 1389 constraintList ret = constraintList_makeNew();
c3e695ff 1390
1391 constraintList_elements(target, el)
9a48d98c 1392 {
1393 constraint temp = constraint_substitute (el, subList);
1394 /*@i3232@*/ /* drl possible problem : warning make sure that a side effect is not expected */
1395 ret = constraintList_add (ret, temp);
1396 } end_constraintList_elements;
84c9ffbf 1397
bb25bea6 1398 return ret;
c3e695ff 1399}
616915dd 1400
28bf4b0b 1401static constraint constraint_solve (/*@returned@*/ constraint c)
616915dd 1402{
9a48d98c 1403 llassert (constraint_isDefined (c));
1404 DPRINTF (("Solving %s", constraint_unparse (c)));
616915dd 1405 c->expr = constraintExpr_solveBinaryExpr (c->lexpr, c->expr);
9a48d98c 1406 DPRINTF (("Solved and got %s", constraint_unparse (c)));
616915dd 1407 return c;
1408}
1409
1410static arithType flipAr (arithType ar)
1411{
1412 switch (ar)
1413 {
9a48d98c 1414 case LT: return GT;
1415 case LTE: return GTE;
1416 case EQ: return EQ;
1417 case GT: return LT;
1418 case GTE: return LTE;
1419 default: llcontbuglit ("unexpected value: case not handled");
616915dd 1420 }
1421 BADEXIT;
1422}
1423
9a48d98c 1424static constraint constraint_swapLeftRight (/*@returned@*/ constraint c)
616915dd 1425{
1426 constraintExpr temp;
a64ebe74 1427
9a48d98c 1428 llassert (constraint_isDefined (c));
a64ebe74 1429
616915dd 1430 c->ar = flipAr (c->ar);
1431 temp = c->lexpr;
1432 c->lexpr = c->expr;
1433 c->expr = temp;
9a48d98c 1434 DPRINTF (("Swaped left and right sides of constraint"));
616915dd 1435 return c;
1436}
1437
9a48d98c 1438constraint constraint_simplify (/*@returned@*/ constraint c)
616915dd 1439{
9a48d98c 1440 llassert (constraint_isDefined (c));
1441 DPRINTF (("constraint_simplify on %q ", constraint_unparse (c)));
a779b61e 1442
1443 if (constraint_tooDeep(c))
1444 {
9a48d98c 1445 DPRINTF (("constraint_simplify: constraint to complex aborting %q", constraint_unparse (c)));
a779b61e 1446 return c;
a779b61e 1447 }
1448
616915dd 1449 c->lexpr = constraintExpr_simplify (c->lexpr);
1450 c->expr = constraintExpr_simplify (c->expr);
616915dd 1451
9a48d98c 1452 if (constraintExpr_isBinaryExpr (c->lexpr))
c3e695ff 1453 {
1454 c = constraint_solve (c);
c3e695ff 1455 c->lexpr = constraintExpr_simplify (c->lexpr);
1456 c->expr = constraintExpr_simplify (c->expr);
1457 }
1458
9a48d98c 1459 if (constraintExpr_isLit(c->lexpr) && (!constraintExpr_isLit(c->expr)))
616915dd 1460 {
9a48d98c 1461 c = constraint_swapLeftRight (c);
1462 /* I don't think this will be an infinite loop */
1463 c = constraint_simplify (c);
616915dd 1464 }
a779b61e 1465
9a48d98c 1466 DPRINTF (("constraint_simplify returning %q", constraint_unparse (c)));
616915dd 1467 return c;
1468}
1469
9a48d98c 1470/* returns true if fileloc for term1 is closer to file for term2 than term3*/
616915dd 1471
9a48d98c 1472bool fileloc_closer (fileloc loc1, fileloc loc2, fileloc loc3)
616915dd 1473{
9a48d98c 1474 if (!fileloc_isDefined (loc1))
c3e695ff 1475 return FALSE;
9a48d98c 1476
1477 if (!fileloc_isDefined (loc2))
c3e695ff 1478 return FALSE;
1479
9a48d98c 1480 if (!fileloc_isDefined (loc3))
c3e695ff 1481 return TRUE;
c3e695ff 1482
9a48d98c 1483 if (fileloc_equal (loc2, loc3))
c3e695ff 1484 return FALSE;
9a48d98c 1485
1486 if (fileloc_equal (loc1, loc2))
c3e695ff 1487 return TRUE;
9a48d98c 1488
1489 if (fileloc_equal (loc1, loc3))
c3e695ff 1490 return FALSE;
9a48d98c 1491
1492 if (fileloc_lessthan (loc1, loc2))
1493 {
1494 if (fileloc_lessthan (loc2, loc3))
1495 {
1496 llassert (fileloc_lessthan (loc1, loc3));
1497 return TRUE;
1498 }
1499 else
1500 {
1501 return FALSE;
1502 }
1503 }
1504
1505 if (!fileloc_lessthan (loc1, loc2))
1506 {
1507 if (!fileloc_lessthan (loc2, loc3))
1508 {
1509 llassert (!fileloc_lessthan (loc1, loc3));
1510 return TRUE;
1511 }
1512 else
1513 {
1514 return FALSE;
1515 }
1516 }
1517
1518 llassert(FALSE);
1519 return FALSE;
616915dd 1520}
1521
1522
This page took 2.645141 seconds and 5 git commands to generate.