]> andersk Git - splint.git/blob - src/mtDeclarationNode.c
noexpand always false.
[splint.git] / src / mtDeclarationNode.c
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.
19 **
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
23 */
24 /*
25 ** mtDeclarationNode.c
26 */
27
28 # include "splintMacros.nf"
29 # include "basic.h"
30
31 extern mtDeclarationNode mtDeclarationNode_create (mttok name, mtDeclarationPieces pieces) /*@*/ 
32 {
33   mtDeclarationNode res = (mtDeclarationNode) dmalloc (sizeof (*res));
34
35   res->name = mttok_getText (name);
36   res->loc = mttok_stealLoc (name);
37   res->pieces = pieces;
38
39   mttok_free (name);
40   return res;
41 }
42
43 extern cstring mtDeclarationNode_unparse (mtDeclarationNode node) /*@*/ 
44 {
45   return message ("state %s %q",
46                   node->name,
47                   mtDeclarationPieces_unparse (node->pieces));
48 }
49
50 extern void mtDeclarationNode_process (mtDeclarationNode node, bool isglobal)
51 {
52   int i;
53   int j;
54
55   mtDeclarationPieces pieces;
56   mtDeclarationPiece mtp;
57   mtContextNode mtcontext;
58   stateCombinationTable tsc;
59   stateCombinationTable tmerge;
60   cstringList mvals;
61   metaStateInfo msinfo;
62   int nvalues;
63
64   cstring defaultMergeMessage = 
65     cstring_makeLiteralTemp ("Incompatible state merge (default behavior)");
66
67   pieces = node->pieces;
68
69   /*
70   ** First, we need to find the values piece.
71   */
72
73   mtp = mtDeclarationPieces_findPiece (pieces, MTP_VALUES);
74
75   if (mtDeclarationPiece_isUndefined (mtp)) 
76     {
77       voptgenerror (FLG_SYNTAX,
78                     message ("Metastate declaration missing values clause: %s",
79                              mtDeclarationNode_getName (node)),
80                     mtDeclarationNode_getLoc (node));
81       return;
82     }
83   else 
84     {
85       mtValuesNode  mtv = mtDeclarationPiece_getValues (mtp);
86       mvals = mtValuesNode_getValues (mtv);
87     }
88
89   /*@-usedef@*/ /* splint should figure this out... */
90   nvalues = cstringList_size (mvals);
91   /*@=usedef@*/
92
93   mtp = mtDeclarationPieces_findPiece (pieces, MTP_CONTEXT);
94
95   if (mtDeclarationPiece_isUndefined (mtp)) 
96     {
97       ; /* No context, assume anywhere is okay. */
98       mtcontext = mtContextNode_createAny ();
99     }
100   else 
101     {
102       mtcontext = mtDeclarationPiece_stealContext (mtp);
103     }
104
105   if (isglobal)
106     {
107       /*
108       ** For global state, instead of a transfers piece, we have constraints.
109       */
110
111       mtp = mtDeclarationPieces_findPiece (pieces, MTP_TRANSFERS);
112
113       if (!mtDeclarationPiece_isUndefined (mtp)) 
114         {
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);
120           return;
121         } 
122
123       mtp = mtDeclarationPieces_findPiece (pieces, MTP_PRECONDITIONS);
124       
125       if (mtDeclarationPiece_isUndefined (mtp)) 
126         {
127           voptgenerror (FLG_SYNTAX,
128                         message ("Metastate declaration missing preconditions clause: %s",
129                                  mtDeclarationNode_getName (node)),
130                         mtDeclarationNode_getLoc (node));
131           mtContextNode_free (mtcontext);
132           return;
133         } 
134       else 
135         {
136           mtTransferClauseList mtransfers = mtDeclarationPiece_getPreconditions (mtp);
137           tsc = stateCombinationTable_create (nvalues);
138           
139           mtTransferClauseList_elements (mtransfers, transfer)
140             {
141               cstring tfrom = mtTransferClause_getFrom (transfer);
142               cstring tto = mtTransferClause_getTo (transfer);
143               mtTransferAction taction = mtTransferClause_getAction (transfer);
144               cstring vname = mtTransferAction_getValue (taction);
145               
146               int fromindex;
147               int toindex;
148               int vindex;
149               
150               DPRINTF (("Transfer: %s", mtTransferClause_unparse (transfer)));
151               
152               if (cstringList_contains (mvals, tfrom)) 
153                 {
154                   fromindex = cstringList_getIndex (mvals, tfrom);
155                 }
156               else
157                 {
158                   voptgenerror
159                     (FLG_SYNTAX,
160                      message ("Precondition clause uses unrecognized caller value %s: %q",
161                               tfrom, mtTransferClause_unparse (transfer)),
162                      mtTransferClause_getLoc (transfer));
163                   continue;
164                 }
165               
166               if (cstringList_contains (mvals, tto)) 
167                 {
168                   toindex = cstringList_getIndex (mvals, tto);
169                 }
170               else
171                 {
172                   voptgenerror
173                     (FLG_SYNTAX,
174                      message ("Precondition clause uses unrecognized constraint value %s: %q",
175                               tto, mtTransferClause_unparse (transfer)),
176                      mtTransferClause_getLoc (transfer));
177                   continue;
178                 }
179               
180               if (mtTransferAction_isError (taction))
181                 {
182                   vindex = metaState_error;
183                 }
184               else 
185                 {
186                   if (cstringList_contains (mvals, vname)) 
187                     {
188                       vindex = cstringList_getIndex (mvals, vname);
189                     }
190                   else
191                     {
192                       voptgenerror
193                         (FLG_SYNTAX,
194                          message ("Precondition clause uses unrecognized result state %s: %q",
195                                   vname, mtTransferClause_unparse (transfer)),
196                          mtTransferClause_getLoc (transfer));
197                       continue;
198                     }
199                 }
200               
201               if (mtTransferAction_isError (taction))
202                 {
203                   stateCombinationTable_set 
204                     (tsc, fromindex, toindex,
205                      vindex,
206                      cstring_copy (mtTransferAction_getMessage (taction)));
207                 }
208               else
209                 {
210                   stateCombinationTable_set (tsc, fromindex, toindex,
211                                              vindex,
212                                              cstring_undefined);
213                 }
214             } end_mtTransferClauseList_elements ;
215         }
216     }
217   else
218     {
219       mtp = mtDeclarationPieces_findPiece (pieces, MTP_PRECONDITIONS);
220
221       if (!mtDeclarationPiece_isUndefined (mtp)) 
222         {
223           voptgenerror 
224             (FLG_SYNTAX,
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);
230           return;
231         } 
232
233       mtp = mtDeclarationPieces_findPiece (pieces, MTP_POSTCONDITIONS);
234
235       if (!mtDeclarationPiece_isUndefined (mtp)) 
236         {
237           voptgenerror 
238             (FLG_SYNTAX,
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);
244           return;
245         } 
246
247       mtp = mtDeclarationPieces_findPiece (pieces, MTP_TRANSFERS);
248       
249       if (mtDeclarationPiece_isUndefined (mtp)) 
250         {
251           voptgenerror (FLG_SYNTAX,
252                         message ("Metastate declaration missing transfers clause: %s",
253                                  mtDeclarationNode_getName (node)),
254                         mtDeclarationNode_getLoc (node));
255           mtContextNode_free (mtcontext);
256           return;
257         } 
258       else 
259         {
260           mtTransferClauseList mtransfers = mtDeclarationPiece_getTransfers (mtp);
261           tsc = stateCombinationTable_create (nvalues);
262           
263           mtTransferClauseList_elements (mtransfers, transfer)
264             {
265               cstring tfrom = mtTransferClause_getFrom (transfer);
266               cstring tto = mtTransferClause_getTo (transfer);
267               mtTransferAction taction = mtTransferClause_getAction (transfer);
268               cstring vname = mtTransferAction_getValue (taction);
269               
270               int fromindex;
271               int toindex;
272               int vindex;
273               
274               DPRINTF (("Transfer: %s", mtTransferClause_unparse (transfer)));
275               
276               if (cstringList_contains (mvals, tfrom)) 
277                 {
278                   fromindex = cstringList_getIndex (mvals, tfrom);
279                 }
280               else
281                 {
282                   voptgenerror
283                     (FLG_SYNTAX,
284                      message ("Transfer clause uses unrecognized from value %s: %q",
285                               tfrom, mtTransferClause_unparse (transfer)),
286                      mtTransferClause_getLoc (transfer));
287                   continue;
288                 }
289               
290               if (cstringList_contains (mvals, tto)) 
291                 {
292                   toindex = cstringList_getIndex (mvals, tto);
293                 }
294               else
295                 {
296                   voptgenerror
297                     (FLG_SYNTAX,
298                      message ("Transfer clause uses unrecognized to value %s: %q",
299                               tto, mtTransferClause_unparse (transfer)),
300                      mtTransferClause_getLoc (transfer));
301                   continue;
302                 }
303               
304               if (mtTransferAction_isError (taction))
305                 {
306                   vindex = metaState_error;
307                 }
308               else 
309                 {
310                   if (cstringList_contains (mvals, vname)) 
311                     {
312                       vindex = cstringList_getIndex (mvals, vname);
313                     }
314                   else
315                     {
316                       voptgenerror
317                         (FLG_SYNTAX,
318                          message ("Transfer clause uses unrecognized result state %s: %q",
319                                   vname, mtTransferClause_unparse (transfer)),
320                          mtTransferClause_getLoc (transfer));
321                       continue;
322                     }
323                 }
324               
325               if (mtTransferAction_isError (taction))
326                 {
327                   stateCombinationTable_set 
328                     (tsc, fromindex, toindex,
329                      vindex,
330                      cstring_copy (mtTransferAction_getMessage (taction)));
331                 }
332               else
333                 {
334                   stateCombinationTable_set (tsc, fromindex, toindex,
335                                              vindex,
336                                              cstring_undefined);
337                 }
338             } end_mtTransferClauseList_elements ;
339         }
340     }
341
342   mtp = mtDeclarationPieces_findPiece (pieces, MTP_LOSERS);
343
344   if (mtDeclarationPiece_isDefined (mtp))
345     {
346       mtLoseReferenceList mlosers = mtDeclarationPiece_getLosers (mtp);
347       
348       mtLoseReferenceList_elements (mlosers, loseref)
349         {
350           cstring tfrom = mtLoseReference_getFrom (loseref);
351           mtTransferAction taction = mtLoseReference_getAction (loseref);
352           int fromindex;
353           /* Losing reference is represented by transfer to nvalues */
354           int toindex = nvalues; 
355           int vindex = metaState_error;
356
357           llassert (mtTransferAction_isError (taction));
358
359           if (cstringList_contains (mvals, tfrom)) 
360             {
361               fromindex = cstringList_getIndex (mvals, tfrom);
362             }
363           else
364             {
365               voptgenerror
366                 (FLG_SYNTAX,
367                  message ("Lose reference uses unrecognized from value %s: %q",
368                           tfrom, mtLoseReference_unparse (loseref)),
369                  mtLoseReference_getLoc (loseref));
370               continue;
371             }
372
373           /*@-usedef@*/
374           stateCombinationTable_set 
375             (tsc, fromindex, toindex, vindex,
376              cstring_copy (mtTransferAction_getMessage (taction)));
377           /*@=usedef@*/
378         } end_mtLoseReferenceList_elements ;
379     }
380   
381   tmerge = stateCombinationTable_create (nvalues);
382
383   /* Default merge is to make all incompatible mergers errors. */
384   
385   for (i = 0; i < nvalues; i++) 
386     {
387       for (j = 0; j < nvalues; j++)
388         {
389           if (i != j) 
390             {
391               stateCombinationTable_set 
392                 (tmerge, i, j, metaState_error, cstring_copy (defaultMergeMessage));
393             }
394         }
395     }
396
397   mtp = mtDeclarationPieces_findPiece (pieces, MTP_MERGE);
398   
399   if (mtDeclarationPiece_isDefined (mtp))
400     {
401       mtMergeNode mtmerge = mtDeclarationPiece_getMerge (mtp);
402       mtMergeClauseList mclauses = mtMergeNode_getClauses (mtmerge);
403
404       DPRINTF (("Merge node: %s", mtMergeNode_unparse (mtmerge)));
405
406       mtMergeClauseList_elements (mclauses, merge)
407         {
408           mtMergeItem item1 = mtMergeClause_getItem1 (merge);
409           mtMergeItem item2 = mtMergeClause_getItem2 (merge);
410           mtTransferAction taction = mtMergeClause_getAction (merge);
411           int low1index, high1index;
412           int low2index, high2index;
413           int vindex;
414
415           DPRINTF (("Merge %s X %s => %s",
416                     mtMergeItem_unparse (item1),
417                     mtMergeItem_unparse (item2),
418                     mtTransferAction_unparse (taction)));
419           
420           if (!mtMergeItem_isStar (item1))
421             {
422               if (cstringList_contains (mvals, mtMergeItem_getValue (item1)))
423                 {
424                   low1index = cstringList_getIndex (mvals, mtMergeItem_getValue (item1));
425                   high1index = low1index;
426                 }
427               else
428                 {
429                   voptgenerror
430                     (FLG_SYNTAX,
431                      message ("Merge clause uses unrecognized first value %s: %q",
432                               mtMergeItem_getValue (item1), 
433                               mtMergeClause_unparse (merge)),
434                      mtMergeClause_getLoc (merge));
435                   continue;
436                 }
437             }
438           else
439             {
440               low1index = 0;
441               high1index = nvalues - 1;
442             }
443
444           if (!mtMergeItem_isStar (item2))
445             {
446               if (cstringList_contains (mvals, mtMergeItem_getValue (item2))) 
447                 {
448                   low2index = cstringList_getIndex (mvals, mtMergeItem_getValue (item2));
449                   high2index = low2index;
450                 }
451               else
452                 {
453                   voptgenerror
454                     (FLG_SYNTAX,
455                      message ("Merge clause uses unrecognized second value %s: %q",
456                               mtMergeItem_getValue (item2), 
457                               mtMergeClause_unparse (merge)),
458                      mtMergeItem_getLoc (item2));
459                   continue;
460                 }
461             }
462           else
463             {
464               low2index = 0;
465               high2index = nvalues - 1;
466             }
467           
468           if (mtTransferAction_isError (taction))
469             {
470               vindex = metaState_error;
471             }
472           else 
473             {
474               cstring vname = mtTransferAction_getValue (taction);
475
476               if (cstringList_contains (mvals, vname)) 
477                 {
478                   vindex = cstringList_getIndex (mvals, vname);
479                 }
480               else
481                 {
482                   voptgenerror
483                     (FLG_SYNTAX,
484                      message ("Merge clause uses unrecognized result state %s: %q",
485                               vname, mtMergeClause_unparse (merge)),
486                      mtTransferAction_getLoc (taction));
487                   continue;
488                 }
489             }
490
491           for (i = low1index; i <= high1index; i++)
492             {
493               for (j = low2index; j <= high2index; j++)
494                 {
495                   /* Need to add checks for multiple definitions! */
496                   
497                   if (mtTransferAction_isError (taction))
498                     {
499                       stateCombinationTable_update
500                         (tmerge, 
501                          i, j, 
502                          vindex,
503                          cstring_copy (mtTransferAction_getMessage (taction)));
504                     }
505                   else
506                     {
507                       stateCombinationTable_update
508                         (tmerge, 
509                          i, j, 
510                          vindex,
511                          cstring_undefined);
512                     }
513                 }
514             }
515
516           /*
517           ** Unless otherwise indicated, merging is symmetric:
518           */
519
520           for (i = low1index; i <= high1index; i++)
521             {
522               for (j = low2index; j <= high2index; j++)
523                 {
524                   cstring msg;
525
526                   if (stateCombinationTable_lookup (tmerge, j, i, &msg) == metaState_error)
527                     {
528                       if (cstring_equal (msg, defaultMergeMessage))
529                         {
530                           /* Override the default action */
531                           if (mtTransferAction_isError (taction))
532                             {
533                               stateCombinationTable_update
534                                 (tmerge, 
535                                  j, i,
536                                  vindex,
537                                  cstring_copy (mtTransferAction_getMessage (taction)));
538                             }
539                           else
540                             {
541                               stateCombinationTable_update
542                                 (tmerge, 
543                                  j, i, 
544                                  vindex,
545                                  cstring_undefined);
546                             }
547                         }
548                     }
549                 }
550             }
551         } end_mtMergeClauseList_elements ;  
552     }
553
554   msinfo = metaStateInfo_create (cstring_copy (mtDeclarationNode_getName (node)),
555                                  cstringList_copy (mvals),
556                                  mtcontext,
557                                  /*@-usedef@*/ tsc, /*@=usedef@*/
558                                  tmerge,
559                                  fileloc_copy (mtDeclarationNode_getLoc (node)));
560
561   mtp = mtDeclarationPieces_findPiece (pieces, MTP_ANNOTATIONS);
562
563   if (mtDeclarationPiece_isDefined (mtp))
564     {
565       mtAnnotationsNode mtannots = mtDeclarationPiece_getAnnotations (mtp);
566       mtAnnotationList mtalist = mtAnnotationsNode_getAnnotations (mtannots);
567
568       DPRINTF (("Has annotations: %s", mtAnnotationList_unparse (mtalist)));      
569
570       mtAnnotationList_elements (mtalist, annot) 
571         {
572           cstring aname = mtAnnotationDecl_getName (annot);
573           cstring avalue = mtAnnotationDecl_getValue (annot);
574
575           DPRINTF (("Process annotation: %s", mtAnnotationDecl_unparse (annot)));
576           
577           if (cstringList_contains (mvals, avalue)) 
578             {
579               int vindex = cstringList_getIndex (mvals, avalue);
580               mtContextNode acontext = mtAnnotationDecl_stealContext (annot);
581               
582               context_addAnnotation 
583                 (annotationInfo_create (cstring_copy (aname), msinfo, 
584                                         acontext, vindex,
585                                         fileloc_copy (mtAnnotationDecl_getLoc (annot))));
586             }
587           else
588             {
589               voptgenerror
590                 (FLG_SYNTAX,
591                  message ("Annotation declaration uses unrecognized value name %s: %q",
592                           avalue, mtAnnotationDecl_unparse (annot)),
593                  mtAnnotationDecl_getLoc (annot));
594             }
595
596         } end_mtAnnotationList_elements ;
597     }
598
599   mtp = mtDeclarationPieces_findPiece (pieces, MTP_DEFAULTS);
600
601   if (mtDeclarationPiece_isDefined (mtp))
602     {
603       mtDefaultsNode mdn = mtDeclarationPiece_getDefaults (mtp);
604       mtDefaultsDeclList mdecls = mtDefaultsNode_getDecls (mdn);
605       
606       llassert (!isglobal);
607
608       mtDefaultsDeclList_elements (mdecls, mdecl)
609         {
610           mtContextNode mcontext = mtDefaultsDecl_getContext (mdecl);
611           cstring mvalue = mtDefaultsDecl_getValue (mdecl);
612
613           if (cstringList_contains (mvals, mvalue)) 
614             {
615               int vindex = cstringList_getIndex (mvals, mvalue);
616               mtContextKind mkind;
617
618               if (mtContextNode_isReference (mcontext))
619                 {
620                   mkind = MTC_REFERENCE;
621                 }
622               else if (mtContextNode_isParameter (mcontext))
623                 {
624                   mkind = MTC_PARAM;
625                 }
626               else if (mtContextNode_isResult (mcontext))
627                 {
628                   mkind = MTC_RESULT;
629                 }
630               else if (mtContextNode_isLiteral (mcontext))
631                 {
632                   mkind = MTC_LITERAL;
633                 }
634               else if (mtContextNode_isNull (mcontext))
635                 {
636                   mkind = MTC_NULL;
637                 }
638               else
639                 {
640                   DPRINTF (("Bad: %s", mtContextNode_unparse (mcontext)));
641                   BADBRANCH;
642                 }
643
644               if (metaStateInfo_getDefaultValueContext (msinfo, mkind) != stateValue_error)
645                 {
646                   voptgenerror
647                     (FLG_SYNTAX,
648                      message ("Duplicate defaults declaration for context %q: %q",
649                               mtContextNode_unparse (mcontext), 
650                               mtDefaultsDecl_unparse (mdecl)),
651                      mtDefaultsDecl_getLoc (mdecl));
652                 }
653               else
654                 {
655                   metaStateInfo_setDefaultValueContext (msinfo, mkind, vindex);
656                 }
657             }
658           else
659             {
660               voptgenerror
661                 (FLG_SYNTAX,
662                  message ("Defaults declaration uses unrecognized value name %s: %q",
663                           mvalue, mtDefaultsDecl_unparse (mdecl)),
664                  mtDefaultsDecl_getLoc (mdecl));
665             }
666         } end_mtDefaultsDeclList_elements ;
667     }
668
669   mtp = mtDeclarationPieces_findPiece (pieces, MTP_DEFAULTVALUE);
670
671   if (mtDeclarationPiece_isDefined (mtp))
672     {
673       cstring mvalue = mtDeclarationPiece_getDefaultValue (mtp);
674       llassert (isglobal);
675       
676       if (cstringList_contains (mvals, mvalue)) 
677         {
678           int vindex = cstringList_getIndex (mvals, mvalue);
679           
680           if (metaStateInfo_getDefaultRefValue (msinfo) != stateValue_error)
681             {
682               voptgenerror
683                 (FLG_SYNTAX,
684                  message ("Duplicate default value declaration for global state: %s",
685                           mvalue),
686                  mtDeclarationNode_getLoc (node));
687             }
688           else
689             {
690               metaStateInfo_setDefaultRefValue (msinfo, vindex);
691             }
692         }
693       else
694         {
695           voptgenerror
696             (FLG_SYNTAX,
697              message ("Default value declaration uses unrecognized value name: %s",
698                       mvalue),
699              mtDeclarationNode_getLoc (node));
700         }
701     }
702   
703   context_addMetaState (cstring_copy (mtDeclarationNode_getName (node)),
704                         msinfo);
705 }
706
707 extern void mtDeclarationNode_free (/*@only@*/ mtDeclarationNode node)
708 {
709   mtDeclarationPieces_free (node->pieces);
710   cstring_free (node->name);
711   fileloc_free (node->loc);
712   sfree (node);
713 }
714
715 extern fileloc mtDeclarationNode_getLoc (mtDeclarationNode node) 
716 {
717   return node->loc;
718 }
719
720 extern /*@observer@*/ cstring mtDeclarationNode_getName (mtDeclarationNode node)
721 {
722   return node->name;
723 }
This page took 0.167343 seconds and 5 git commands to generate.