2 ** LCLint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2001 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 lclint: lclint-request@cs.virginia.edu
21 ** To report a bug: lclint-bug@cs.virginia.edu
22 ** For more information: http://lclint.cs.virginia.edu
25 ** mtDeclarationNode.c
28 # include "lclintMacros.nf"
30 # include "mtgrammar.h"
32 extern mtDeclarationNode mtDeclarationNode_create (mttok name, mtDeclarationPieces pieces) /*@*/
34 mtDeclarationNode res = (mtDeclarationNode) dmalloc (sizeof (*res));
36 res->name = mttok_getText (name);
37 res->loc = mttok_stealLoc (name);
44 extern cstring mtDeclarationNode_unparse (mtDeclarationNode node) /*@*/
46 return message ("state %s %q",
48 mtDeclarationPieces_unparse (node->pieces));
51 extern void mtDeclarationNode_process (mtDeclarationNode node, bool isglobal)
56 mtDeclarationPieces pieces;
57 mtDeclarationPiece mtp;
58 mtContextNode mtcontext;
59 stateCombinationTable tsc;
60 stateCombinationTable tmerge;
65 pieces = node->pieces;
68 ** First, we need to find the values piece.
71 mtp = mtDeclarationPieces_findPiece (pieces, MTP_VALUES);
73 if (mtDeclarationPiece_isUndefined (mtp))
75 voptgenerror (FLG_SYNTAX,
76 message ("Metastate declaration missing values clause: %s",
77 mtDeclarationNode_getName (node)),
78 mtDeclarationNode_getLoc (node));
83 mtValuesNode mtv = mtDeclarationPiece_getValues (mtp);
84 mvals = mtValuesNode_getValues (mtv);
87 /*@-usedef@*/ /*@i34 lclint should figure this out... */
88 nvalues = cstringList_size (mvals);
91 mtp = mtDeclarationPieces_findPiece (pieces, MTP_CONTEXT);
93 if (mtDeclarationPiece_isUndefined (mtp))
95 ; /* No context, assume anywhere is okay. */
96 mtcontext = mtContextNode_createAny ();
100 mtcontext = mtDeclarationPiece_stealContext (mtp);
106 ** For global state, instead of a transfers piece, we have constraints.
109 mtp = mtDeclarationPieces_findPiece (pieces, MTP_TRANSFERS);
111 if (!mtDeclarationPiece_isUndefined (mtp))
113 voptgenerror (FLG_SYNTAX,
114 message ("Global state declaration uses transfers clause. Should use preconditions and postconsitions clauses instead: %s",
115 mtDeclarationNode_getName (node)),
116 mtDeclarationNode_getLoc (node));
117 mtContextNode_free (mtcontext);
121 mtp = mtDeclarationPieces_findPiece (pieces, MTP_PRECONDITIONS);
123 if (mtDeclarationPiece_isUndefined (mtp))
125 voptgenerror (FLG_SYNTAX,
126 message ("Metastate declaration missing preconditions clause: %s",
127 mtDeclarationNode_getName (node)),
128 mtDeclarationNode_getLoc (node));
129 mtContextNode_free (mtcontext);
134 mtTransferClauseList mtransfers = mtDeclarationPiece_getPreconditions (mtp);
135 tsc = stateCombinationTable_create (nvalues);
137 mtTransferClauseList_elements (mtransfers, transfer)
139 cstring tfrom = mtTransferClause_getFrom (transfer);
140 cstring tto = mtTransferClause_getTo (transfer);
141 mtTransferAction taction = mtTransferClause_getAction (transfer);
142 cstring vname = mtTransferAction_getValue (taction);
148 DPRINTF (("Transfer: %s", mtTransferClause_unparse (transfer)));
150 if (cstringList_contains (mvals, tfrom))
152 fromindex = cstringList_getIndex (mvals, tfrom);
158 message ("Precondition clause uses unrecognized caller value %s: %q",
159 tfrom, mtTransferClause_unparse (transfer)),
160 mtTransferClause_getLoc (transfer));
164 if (cstringList_contains (mvals, tto))
166 toindex = cstringList_getIndex (mvals, tto);
172 message ("Precondition clause uses unrecognized constraint value %s: %q",
173 tto, mtTransferClause_unparse (transfer)),
174 mtTransferClause_getLoc (transfer));
178 if (mtTransferAction_isError (taction))
180 vindex = metaState_error;
184 if (cstringList_contains (mvals, vname))
186 vindex = cstringList_getIndex (mvals, vname);
192 message ("Precondition clause uses unrecognized result state %s: %q",
193 vname, mtTransferClause_unparse (transfer)),
194 mtTransferClause_getLoc (transfer));
199 if (mtTransferAction_isError (taction))
201 stateCombinationTable_set
202 (tsc, fromindex, toindex,
204 cstring_copy (mtTransferAction_getMessage (taction)));
208 stateCombinationTable_set (tsc, fromindex, toindex,
212 } end_mtTransferClauseList_elements ;
217 mtp = mtDeclarationPieces_findPiece (pieces, MTP_PRECONDITIONS);
219 if (!mtDeclarationPiece_isUndefined (mtp))
223 message ("Non-global state declaration uses preconditions clause. "
224 "Should use transfers clause instead: %s",
225 mtDeclarationNode_getName (node)),
226 mtDeclarationNode_getLoc (node));
227 mtContextNode_free (mtcontext);
231 mtp = mtDeclarationPieces_findPiece (pieces, MTP_POSTCONDITIONS);
233 if (!mtDeclarationPiece_isUndefined (mtp))
237 message ("Non-global state declaration uses postconditions clause. "
238 "Should use transfers clause instead: %s",
239 mtDeclarationNode_getName (node)),
240 mtDeclarationNode_getLoc (node));
241 mtContextNode_free (mtcontext);
245 mtp = mtDeclarationPieces_findPiece (pieces, MTP_TRANSFERS);
247 if (mtDeclarationPiece_isUndefined (mtp))
249 voptgenerror (FLG_SYNTAX,
250 message ("Metastate declaration missing transfers clause: %s",
251 mtDeclarationNode_getName (node)),
252 mtDeclarationNode_getLoc (node));
253 mtContextNode_free (mtcontext);
258 mtTransferClauseList mtransfers = mtDeclarationPiece_getTransfers (mtp);
259 tsc = stateCombinationTable_create (nvalues);
261 mtTransferClauseList_elements (mtransfers, transfer)
263 cstring tfrom = mtTransferClause_getFrom (transfer);
264 cstring tto = mtTransferClause_getTo (transfer);
265 mtTransferAction taction = mtTransferClause_getAction (transfer);
266 cstring vname = mtTransferAction_getValue (taction);
272 DPRINTF (("Transfer: %s", mtTransferClause_unparse (transfer)));
274 if (cstringList_contains (mvals, tfrom))
276 fromindex = cstringList_getIndex (mvals, tfrom);
282 message ("Transfer clause uses unrecognized from value %s: %q",
283 tfrom, mtTransferClause_unparse (transfer)),
284 mtTransferClause_getLoc (transfer));
288 if (cstringList_contains (mvals, tto))
290 toindex = cstringList_getIndex (mvals, tto);
296 message ("Transfer clause uses unrecognized to value %s: %q",
297 tto, mtTransferClause_unparse (transfer)),
298 mtTransferClause_getLoc (transfer));
302 if (mtTransferAction_isError (taction))
304 vindex = metaState_error;
308 if (cstringList_contains (mvals, vname))
310 vindex = cstringList_getIndex (mvals, vname);
316 message ("Transfer clause uses unrecognized result state %s: %q",
317 vname, mtTransferClause_unparse (transfer)),
318 mtTransferClause_getLoc (transfer));
323 if (mtTransferAction_isError (taction))
325 stateCombinationTable_set
326 (tsc, fromindex, toindex,
328 cstring_copy (mtTransferAction_getMessage (taction)));
332 stateCombinationTable_set (tsc, fromindex, toindex,
336 } end_mtTransferClauseList_elements ;
340 mtp = mtDeclarationPieces_findPiece (pieces, MTP_LOSERS);
342 if (mtDeclarationPiece_isDefined (mtp))
344 mtLoseReferenceList mlosers = mtDeclarationPiece_getLosers (mtp);
346 mtLoseReferenceList_elements (mlosers, loseref)
348 cstring tfrom = mtLoseReference_getFrom (loseref);
349 mtTransferAction taction = mtLoseReference_getAction (loseref);
351 /* Losing reference is represented by transfer to nvalues */
352 int toindex = nvalues;
353 int vindex = metaState_error;
355 llassert (mtTransferAction_isError (taction));
357 if (cstringList_contains (mvals, tfrom))
359 fromindex = cstringList_getIndex (mvals, tfrom);
365 message ("Lose reference uses unrecognized from value %s: %q",
366 tfrom, mtLoseReference_unparse (loseref)),
367 mtLoseReference_getLoc (loseref));
372 stateCombinationTable_set
373 (tsc, fromindex, toindex, vindex,
374 cstring_copy (mtTransferAction_getMessage (taction)));
376 } end_mtLoseReferenceList_elements ;
380 DPRINTF (("metastate: %s", metaStateInfo_unparse (msinfo)));
383 tmerge = stateCombinationTable_create (nvalues);
385 /* Default merge is to make all incompatible mergers errors. */
387 for (i = 0; i < nvalues; i++)
389 for (j = 0; j < nvalues; j++)
393 stateCombinationTable_set
394 (tmerge, i, j, metaState_error,
395 cstring_makeLiteral ("Incompatible state merge (default behavior)"));
400 mtp = mtDeclarationPieces_findPiece (pieces, MTP_MERGE);
402 if (mtDeclarationPiece_isDefined (mtp))
404 mtMergeNode mtmerge = mtDeclarationPiece_getMerge (mtp);
405 mtMergeClauseList mclauses = mtMergeNode_getClauses (mtmerge);
407 DPRINTF (("Merge node: %s", mtMergeNode_unparse (mtmerge)));
409 mtMergeClauseList_elements (mclauses, merge)
411 mtMergeItem item1 = mtMergeClause_getItem1 (merge);
412 mtMergeItem item2 = mtMergeClause_getItem2 (merge);
413 mtTransferAction taction = mtMergeClause_getAction (merge);
414 int low1index, high1index;
415 int low2index, high2index;
418 DPRINTF (("Merge %s X %s => %s",
419 mtMergeItem_unparse (item1),
420 mtMergeItem_unparse (item2),
421 mtTransferAction_unparse (taction)));
423 if (!mtMergeItem_isStar (item1))
425 if (cstringList_contains (mvals, mtMergeItem_getValue (item1)))
427 low1index = cstringList_getIndex (mvals, mtMergeItem_getValue (item1));
428 high1index = low1index;
434 message ("Merge clause uses unrecognized first value %s: %q",
435 mtMergeItem_getValue (item1),
436 mtMergeClause_unparse (merge)),
437 mtMergeClause_getLoc (merge));
444 high1index = nvalues - 1;
447 if (!mtMergeItem_isStar (item2))
449 if (cstringList_contains (mvals, mtMergeItem_getValue (item2)))
451 low2index = cstringList_getIndex (mvals, mtMergeItem_getValue (item2));
452 high2index = low2index;
458 message ("Merge clause uses unrecognized second value %s: %q",
459 mtMergeItem_getValue (item2),
460 mtMergeClause_unparse (merge)),
461 mtMergeItem_getLoc (item2));
468 high2index = nvalues - 1;
471 if (mtTransferAction_isError (taction))
473 vindex = metaState_error;
477 cstring vname = mtTransferAction_getValue (taction);
479 if (cstringList_contains (mvals, vname))
481 vindex = cstringList_getIndex (mvals, vname);
487 message ("Merge clause uses unrecognized result state %s: %q",
488 vname, mtMergeClause_unparse (merge)),
489 mtTransferAction_getLoc (taction));
494 for (i = low1index; i <= high1index; i++)
496 for (j = low2index; j <= high2index; j++)
498 /*@i32 check for multiple definitions! */
500 if (mtTransferAction_isError (taction))
502 stateCombinationTable_update
506 cstring_copy (mtTransferAction_getMessage (taction)));
510 stateCombinationTable_update
518 } end_mtMergeClauseList_elements ;
521 msinfo = metaStateInfo_create (cstring_copy (mtDeclarationNode_getName (node)),
522 cstringList_copy (mvals),
524 /*@-usedef@*/ tsc, /*@=usedef@*/
526 fileloc_copy (mtDeclarationNode_getLoc (node)));
528 mtp = mtDeclarationPieces_findPiece (pieces, MTP_ANNOTATIONS);
530 if (mtDeclarationPiece_isDefined (mtp))
532 mtAnnotationsNode mtannots = mtDeclarationPiece_getAnnotations (mtp);
533 mtAnnotationList mtalist = mtAnnotationsNode_getAnnotations (mtannots);
535 DPRINTF (("Has annotations: %s", mtAnnotationList_unparse (mtalist)));
537 mtAnnotationList_elements (mtalist, annot)
539 cstring aname = mtAnnotationDecl_getName (annot);
540 cstring avalue = mtAnnotationDecl_getValue (annot);
542 DPRINTF (("Process annotation: %s", mtAnnotationDecl_unparse (annot)));
544 if (cstringList_contains (mvals, avalue))
546 int vindex = cstringList_getIndex (mvals, avalue);
547 mtContextNode acontext = mtAnnotationDecl_stealContext (annot);
549 context_addAnnotation
550 (annotationInfo_create (cstring_copy (aname), msinfo,
552 fileloc_copy (mtAnnotationDecl_getLoc (annot))));
558 message ("Annotation declaration uses unrecognized value name %s: %q",
559 avalue, mtAnnotationDecl_unparse (annot)),
560 mtAnnotationDecl_getLoc (annot));
563 } end_mtAnnotationList_elements ;
566 mtp = mtDeclarationPieces_findPiece (pieces, MTP_DEFAULTS);
568 if (mtDeclarationPiece_isDefined (mtp))
570 mtDefaultsNode mdn = mtDeclarationPiece_getDefaults (mtp);
571 mtDefaultsDeclList mdecls = mtDefaultsNode_getDecls (mdn);
573 llassert (!isglobal);
575 mtDefaultsDeclList_elements (mdecls, mdecl)
577 mtContextNode mcontext = mtDefaultsDecl_getContext (mdecl);
578 cstring mvalue = mtDefaultsDecl_getValue (mdecl);
580 if (cstringList_contains (mvals, mvalue))
582 int vindex = cstringList_getIndex (mvals, mvalue);
584 if (mtContextNode_isRef (mcontext))
586 if (metaStateInfo_getDefaultRefValue (msinfo) != stateValue_error)
590 message ("Duplicate defaults declaration for context %q: %q",
591 mtContextNode_unparse (mcontext),
592 mtDefaultsDecl_unparse (mdecl)),
593 mtDefaultsDecl_getLoc (mdecl));
597 metaStateInfo_setDefaultRefValue (msinfo, vindex);
600 else if (mtContextNode_isParameter (mcontext))
602 if (metaStateInfo_getDefaultParamValue (msinfo) != stateValue_error)
606 message ("Duplicate defaults declaration for context %q: %q",
607 mtContextNode_unparse (mcontext),
608 mtDefaultsDecl_unparse (mdecl)),
609 mtDefaultsDecl_getLoc (mdecl));
613 metaStateInfo_setDefaultParamValue (msinfo, vindex);
625 message ("Defaults declaration uses unrecognized value name %s: %q",
626 mvalue, mtDefaultsDecl_unparse (mdecl)),
627 mtDefaultsDecl_getLoc (mdecl));
629 } end_mtDefaultsDeclList_elements ;
632 mtp = mtDeclarationPieces_findPiece (pieces, MTP_DEFAULTVALUE);
634 if (mtDeclarationPiece_isDefined (mtp))
636 cstring mvalue = mtDeclarationPiece_getDefaultValue (mtp);
639 if (cstringList_contains (mvals, mvalue))
641 int vindex = cstringList_getIndex (mvals, mvalue);
643 if (metaStateInfo_getDefaultRefValue (msinfo) != stateValue_error)
647 message ("Duplicate default value declaration for global state: %s",
649 mtDeclarationNode_getLoc (node));
653 metaStateInfo_setDefaultRefValue (msinfo, vindex);
660 message ("Default value declaration uses unrecognized value name: %s",
662 mtDeclarationNode_getLoc (node));
666 context_addMetaState (cstring_copy (mtDeclarationNode_getName (node)),
670 extern void mtDeclarationNode_free (/*@only@*/ mtDeclarationNode node)
672 mtDeclarationPieces_free (node->pieces);
673 cstring_free (node->name);
674 fileloc_free (node->loc);
678 extern fileloc mtDeclarationNode_getLoc (mtDeclarationNode node)
683 extern /*@observer@*/ cstring mtDeclarationNode_getName (mtDeclarationNode node)