2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2002 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
25 ** mtDeclarationNode.c
28 # include "splintMacros.nf"
31 extern mtDeclarationNode mtDeclarationNode_create (mttok name, mtDeclarationPieces pieces) /*@*/
33 mtDeclarationNode res = (mtDeclarationNode) dmalloc (sizeof (*res));
35 res->name = mttok_getText (name);
36 res->loc = mttok_stealLoc (name);
43 extern cstring mtDeclarationNode_unparse (mtDeclarationNode node) /*@*/
45 return message ("state %s %q",
47 mtDeclarationPieces_unparse (node->pieces));
50 extern void mtDeclarationNode_process (mtDeclarationNode node, bool isglobal)
55 mtDeclarationPieces pieces;
56 mtDeclarationPiece mtp;
57 mtContextNode mtcontext;
58 stateCombinationTable tsc;
59 stateCombinationTable tmerge;
64 cstring defaultMergeMessage =
65 cstring_makeLiteralTemp ("Incompatible state merge (default behavior)");
67 pieces = node->pieces;
70 ** First, we need to find the values piece.
73 mtp = mtDeclarationPieces_findPiece (pieces, MTP_VALUES);
75 if (mtDeclarationPiece_isUndefined (mtp))
77 voptgenerror (FLG_SYNTAX,
78 message ("Metastate declaration missing values clause: %s",
79 mtDeclarationNode_getName (node)),
80 mtDeclarationNode_getLoc (node));
85 mtValuesNode mtv = mtDeclarationPiece_getValues (mtp);
86 mvals = mtValuesNode_getValues (mtv);
89 /*@-usedef@*/ /*@i34 splint should figure this out... */
90 nvalues = cstringList_size (mvals);
93 mtp = mtDeclarationPieces_findPiece (pieces, MTP_CONTEXT);
95 if (mtDeclarationPiece_isUndefined (mtp))
97 ; /* No context, assume anywhere is okay. */
98 mtcontext = mtContextNode_createAny ();
102 mtcontext = mtDeclarationPiece_stealContext (mtp);
108 ** For global state, instead of a transfers piece, we have constraints.
111 mtp = mtDeclarationPieces_findPiece (pieces, MTP_TRANSFERS);
113 if (!mtDeclarationPiece_isUndefined (mtp))
115 voptgenerror (FLG_SYNTAX,
116 message ("Global state declaration uses transfers clause. Should use preconditions and postconsitions clauses instead: %s",
117 mtDeclarationNode_getName (node)),
118 mtDeclarationNode_getLoc (node));
119 mtContextNode_free (mtcontext);
123 mtp = mtDeclarationPieces_findPiece (pieces, MTP_PRECONDITIONS);
125 if (mtDeclarationPiece_isUndefined (mtp))
127 voptgenerror (FLG_SYNTAX,
128 message ("Metastate declaration missing preconditions clause: %s",
129 mtDeclarationNode_getName (node)),
130 mtDeclarationNode_getLoc (node));
131 mtContextNode_free (mtcontext);
136 mtTransferClauseList mtransfers = mtDeclarationPiece_getPreconditions (mtp);
137 tsc = stateCombinationTable_create (nvalues);
139 mtTransferClauseList_elements (mtransfers, transfer)
141 cstring tfrom = mtTransferClause_getFrom (transfer);
142 cstring tto = mtTransferClause_getTo (transfer);
143 mtTransferAction taction = mtTransferClause_getAction (transfer);
144 cstring vname = mtTransferAction_getValue (taction);
150 DPRINTF (("Transfer: %s", mtTransferClause_unparse (transfer)));
152 if (cstringList_contains (mvals, tfrom))
154 fromindex = cstringList_getIndex (mvals, tfrom);
160 message ("Precondition clause uses unrecognized caller value %s: %q",
161 tfrom, mtTransferClause_unparse (transfer)),
162 mtTransferClause_getLoc (transfer));
166 if (cstringList_contains (mvals, tto))
168 toindex = cstringList_getIndex (mvals, tto);
174 message ("Precondition clause uses unrecognized constraint value %s: %q",
175 tto, mtTransferClause_unparse (transfer)),
176 mtTransferClause_getLoc (transfer));
180 if (mtTransferAction_isError (taction))
182 vindex = metaState_error;
186 if (cstringList_contains (mvals, vname))
188 vindex = cstringList_getIndex (mvals, vname);
194 message ("Precondition clause uses unrecognized result state %s: %q",
195 vname, mtTransferClause_unparse (transfer)),
196 mtTransferClause_getLoc (transfer));
201 if (mtTransferAction_isError (taction))
203 stateCombinationTable_set
204 (tsc, fromindex, toindex,
206 cstring_copy (mtTransferAction_getMessage (taction)));
210 stateCombinationTable_set (tsc, fromindex, toindex,
214 } end_mtTransferClauseList_elements ;
219 mtp = mtDeclarationPieces_findPiece (pieces, MTP_PRECONDITIONS);
221 if (!mtDeclarationPiece_isUndefined (mtp))
225 message ("Non-global state declaration uses preconditions clause. "
226 "Should use transfers clause instead: %s",
227 mtDeclarationNode_getName (node)),
228 mtDeclarationNode_getLoc (node));
229 mtContextNode_free (mtcontext);
233 mtp = mtDeclarationPieces_findPiece (pieces, MTP_POSTCONDITIONS);
235 if (!mtDeclarationPiece_isUndefined (mtp))
239 message ("Non-global state declaration uses postconditions clause. "
240 "Should use transfers clause instead: %s",
241 mtDeclarationNode_getName (node)),
242 mtDeclarationNode_getLoc (node));
243 mtContextNode_free (mtcontext);
247 mtp = mtDeclarationPieces_findPiece (pieces, MTP_TRANSFERS);
249 if (mtDeclarationPiece_isUndefined (mtp))
251 voptgenerror (FLG_SYNTAX,
252 message ("Metastate declaration missing transfers clause: %s",
253 mtDeclarationNode_getName (node)),
254 mtDeclarationNode_getLoc (node));
255 mtContextNode_free (mtcontext);
260 mtTransferClauseList mtransfers = mtDeclarationPiece_getTransfers (mtp);
261 tsc = stateCombinationTable_create (nvalues);
263 mtTransferClauseList_elements (mtransfers, transfer)
265 cstring tfrom = mtTransferClause_getFrom (transfer);
266 cstring tto = mtTransferClause_getTo (transfer);
267 mtTransferAction taction = mtTransferClause_getAction (transfer);
268 cstring vname = mtTransferAction_getValue (taction);
274 DPRINTF (("Transfer: %s", mtTransferClause_unparse (transfer)));
276 if (cstringList_contains (mvals, tfrom))
278 fromindex = cstringList_getIndex (mvals, tfrom);
284 message ("Transfer clause uses unrecognized from value %s: %q",
285 tfrom, mtTransferClause_unparse (transfer)),
286 mtTransferClause_getLoc (transfer));
290 if (cstringList_contains (mvals, tto))
292 toindex = cstringList_getIndex (mvals, tto);
298 message ("Transfer clause uses unrecognized to value %s: %q",
299 tto, mtTransferClause_unparse (transfer)),
300 mtTransferClause_getLoc (transfer));
304 if (mtTransferAction_isError (taction))
306 vindex = metaState_error;
310 if (cstringList_contains (mvals, vname))
312 vindex = cstringList_getIndex (mvals, vname);
318 message ("Transfer clause uses unrecognized result state %s: %q",
319 vname, mtTransferClause_unparse (transfer)),
320 mtTransferClause_getLoc (transfer));
325 if (mtTransferAction_isError (taction))
327 stateCombinationTable_set
328 (tsc, fromindex, toindex,
330 cstring_copy (mtTransferAction_getMessage (taction)));
334 stateCombinationTable_set (tsc, fromindex, toindex,
338 } end_mtTransferClauseList_elements ;
342 mtp = mtDeclarationPieces_findPiece (pieces, MTP_LOSERS);
344 if (mtDeclarationPiece_isDefined (mtp))
346 mtLoseReferenceList mlosers = mtDeclarationPiece_getLosers (mtp);
348 mtLoseReferenceList_elements (mlosers, loseref)
350 cstring tfrom = mtLoseReference_getFrom (loseref);
351 mtTransferAction taction = mtLoseReference_getAction (loseref);
353 /* Losing reference is represented by transfer to nvalues */
354 int toindex = nvalues;
355 int vindex = metaState_error;
357 llassert (mtTransferAction_isError (taction));
359 if (cstringList_contains (mvals, tfrom))
361 fromindex = cstringList_getIndex (mvals, tfrom);
367 message ("Lose reference uses unrecognized from value %s: %q",
368 tfrom, mtLoseReference_unparse (loseref)),
369 mtLoseReference_getLoc (loseref));
374 stateCombinationTable_set
375 (tsc, fromindex, toindex, vindex,
376 cstring_copy (mtTransferAction_getMessage (taction)));
378 } end_mtLoseReferenceList_elements ;
382 DPRINTF (("metastate: %s", metaStateInfo_unparse (msinfo)));
385 tmerge = stateCombinationTable_create (nvalues);
387 /* Default merge is to make all incompatible mergers errors. */
389 for (i = 0; i < nvalues; i++)
391 for (j = 0; j < nvalues; j++)
395 stateCombinationTable_set
396 (tmerge, i, j, metaState_error, cstring_copy (defaultMergeMessage));
401 mtp = mtDeclarationPieces_findPiece (pieces, MTP_MERGE);
403 if (mtDeclarationPiece_isDefined (mtp))
405 mtMergeNode mtmerge = mtDeclarationPiece_getMerge (mtp);
406 mtMergeClauseList mclauses = mtMergeNode_getClauses (mtmerge);
408 DPRINTF (("Merge node: %s", mtMergeNode_unparse (mtmerge)));
410 mtMergeClauseList_elements (mclauses, merge)
412 mtMergeItem item1 = mtMergeClause_getItem1 (merge);
413 mtMergeItem item2 = mtMergeClause_getItem2 (merge);
414 mtTransferAction taction = mtMergeClause_getAction (merge);
415 int low1index, high1index;
416 int low2index, high2index;
419 DPRINTF (("Merge %s X %s => %s",
420 mtMergeItem_unparse (item1),
421 mtMergeItem_unparse (item2),
422 mtTransferAction_unparse (taction)));
424 if (!mtMergeItem_isStar (item1))
426 if (cstringList_contains (mvals, mtMergeItem_getValue (item1)))
428 low1index = cstringList_getIndex (mvals, mtMergeItem_getValue (item1));
429 high1index = low1index;
435 message ("Merge clause uses unrecognized first value %s: %q",
436 mtMergeItem_getValue (item1),
437 mtMergeClause_unparse (merge)),
438 mtMergeClause_getLoc (merge));
445 high1index = nvalues - 1;
448 if (!mtMergeItem_isStar (item2))
450 if (cstringList_contains (mvals, mtMergeItem_getValue (item2)))
452 low2index = cstringList_getIndex (mvals, mtMergeItem_getValue (item2));
453 high2index = low2index;
459 message ("Merge clause uses unrecognized second value %s: %q",
460 mtMergeItem_getValue (item2),
461 mtMergeClause_unparse (merge)),
462 mtMergeItem_getLoc (item2));
469 high2index = nvalues - 1;
472 if (mtTransferAction_isError (taction))
474 vindex = metaState_error;
478 cstring vname = mtTransferAction_getValue (taction);
480 if (cstringList_contains (mvals, vname))
482 vindex = cstringList_getIndex (mvals, vname);
488 message ("Merge clause uses unrecognized result state %s: %q",
489 vname, mtMergeClause_unparse (merge)),
490 mtTransferAction_getLoc (taction));
495 for (i = low1index; i <= high1index; i++)
497 for (j = low2index; j <= high2index; j++)
499 /*@i32 check for multiple definitions! */
501 if (mtTransferAction_isError (taction))
503 stateCombinationTable_update
507 cstring_copy (mtTransferAction_getMessage (taction)));
511 stateCombinationTable_update
521 ** Unless otherwise indicated, merging is symmetric:
524 for (i = low1index; i <= high1index; i++)
526 for (j = low2index; j <= high2index; j++)
530 if (stateCombinationTable_lookup (tmerge, j, i, &msg) == metaState_error)
532 if (cstring_equal (msg, defaultMergeMessage))
534 /* Override the default action */
535 if (mtTransferAction_isError (taction))
537 stateCombinationTable_update
541 cstring_copy (mtTransferAction_getMessage (taction)));
545 stateCombinationTable_update
555 } end_mtMergeClauseList_elements ;
558 msinfo = metaStateInfo_create (cstring_copy (mtDeclarationNode_getName (node)),
559 cstringList_copy (mvals),
561 /*@-usedef@*/ tsc, /*@=usedef@*/
563 fileloc_copy (mtDeclarationNode_getLoc (node)));
565 mtp = mtDeclarationPieces_findPiece (pieces, MTP_ANNOTATIONS);
567 if (mtDeclarationPiece_isDefined (mtp))
569 mtAnnotationsNode mtannots = mtDeclarationPiece_getAnnotations (mtp);
570 mtAnnotationList mtalist = mtAnnotationsNode_getAnnotations (mtannots);
572 DPRINTF (("Has annotations: %s", mtAnnotationList_unparse (mtalist)));
574 mtAnnotationList_elements (mtalist, annot)
576 cstring aname = mtAnnotationDecl_getName (annot);
577 cstring avalue = mtAnnotationDecl_getValue (annot);
579 DPRINTF (("Process annotation: %s", mtAnnotationDecl_unparse (annot)));
581 if (cstringList_contains (mvals, avalue))
583 int vindex = cstringList_getIndex (mvals, avalue);
584 mtContextNode acontext = mtAnnotationDecl_stealContext (annot);
586 context_addAnnotation
587 (annotationInfo_create (cstring_copy (aname), msinfo,
589 fileloc_copy (mtAnnotationDecl_getLoc (annot))));
595 message ("Annotation declaration uses unrecognized value name %s: %q",
596 avalue, mtAnnotationDecl_unparse (annot)),
597 mtAnnotationDecl_getLoc (annot));
600 } end_mtAnnotationList_elements ;
603 mtp = mtDeclarationPieces_findPiece (pieces, MTP_DEFAULTS);
605 if (mtDeclarationPiece_isDefined (mtp))
607 mtDefaultsNode mdn = mtDeclarationPiece_getDefaults (mtp);
608 mtDefaultsDeclList mdecls = mtDefaultsNode_getDecls (mdn);
610 llassert (!isglobal);
612 mtDefaultsDeclList_elements (mdecls, mdecl)
614 mtContextNode mcontext = mtDefaultsDecl_getContext (mdecl);
615 cstring mvalue = mtDefaultsDecl_getValue (mdecl);
617 if (cstringList_contains (mvals, mvalue))
619 int vindex = cstringList_getIndex (mvals, mvalue);
622 if (mtContextNode_isReference (mcontext))
624 mkind = MTC_REFERENCE;
626 else if (mtContextNode_isParameter (mcontext))
630 else if (mtContextNode_isResult (mcontext))
634 else if (mtContextNode_isLiteral (mcontext))
638 else if (mtContextNode_isNull (mcontext))
644 DPRINTF (("Bad: %s", mtContextNode_unparse (mcontext)));
648 if (metaStateInfo_getDefaultValueContext (msinfo, mkind) != stateValue_error)
652 message ("Duplicate defaults declaration for context %q: %q",
653 mtContextNode_unparse (mcontext),
654 mtDefaultsDecl_unparse (mdecl)),
655 mtDefaultsDecl_getLoc (mdecl));
659 metaStateInfo_setDefaultValueContext (msinfo, mkind, vindex);
666 message ("Defaults declaration uses unrecognized value name %s: %q",
667 mvalue, mtDefaultsDecl_unparse (mdecl)),
668 mtDefaultsDecl_getLoc (mdecl));
670 } end_mtDefaultsDeclList_elements ;
673 mtp = mtDeclarationPieces_findPiece (pieces, MTP_DEFAULTVALUE);
675 if (mtDeclarationPiece_isDefined (mtp))
677 cstring mvalue = mtDeclarationPiece_getDefaultValue (mtp);
680 if (cstringList_contains (mvals, mvalue))
682 int vindex = cstringList_getIndex (mvals, mvalue);
684 if (metaStateInfo_getDefaultRefValue (msinfo) != stateValue_error)
688 message ("Duplicate default value declaration for global state: %s",
690 mtDeclarationNode_getLoc (node));
694 metaStateInfo_setDefaultRefValue (msinfo, vindex);
701 message ("Default value declaration uses unrecognized value name: %s",
703 mtDeclarationNode_getLoc (node));
707 context_addMetaState (cstring_copy (mtDeclarationNode_getName (node)),
711 extern void mtDeclarationNode_free (/*@only@*/ mtDeclarationNode node)
713 mtDeclarationPieces_free (node->pieces);
714 cstring_free (node->name);
715 fileloc_free (node->loc);
719 extern fileloc mtDeclarationNode_getLoc (mtDeclarationNode node)
724 extern /*@observer@*/ cstring mtDeclarationNode_getName (mtDeclarationNode node)