]> andersk Git - splint.git/blobdiff - src/exprNode.c
Fixed parsing problem with multiple inclusions of alt typedefs.
[splint.git] / src / exprNode.c
index 748f8875d2f6b7105afa1c4823bff97a4c6e317f..648c062a76d94418863225241f1c263b7bf22bd5 100644 (file)
@@ -17,8 +17,8 @@
 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 ** MA 02111-1307, USA.
 **
-** For information on lclint: lclint-request@cs.virginia.edu
-** To report a bug: lclint-bug@cs.virginia.edu
+** For information on splint: info@splint.org
+** To report a bug: splint-bug@splint.org
 ** For more information: http://www.splint.org
 */
 /*
 */
 
 # include <ctype.h> /* for isdigit */
-# include "lclintMacros.nf"
+# include "splintMacros.nf"
 # include "basic.h"
 # include "cgrammar.h"
+# include "cscanner.h"
 # include "cgrammar_tokens.h"
 
 # include "exprChecks.h"
@@ -39,7 +40,7 @@ static bool exprNode_sameStorage (exprNode p_e1, exprNode p_e2) /*@*/ ;
 static bool exprNode_isEmptyStatement (exprNode p_e);
 static /*@exposed@*/ exprNode exprNode_firstStatement (/*@returned@*/ exprNode p_e);
 static bool exprNode_isFalseConstant (exprNode p_e) /*@*/ ;
-static bool exprNode_isBlock (exprNode p_e);
+static bool exprNode_isStatement (exprNode p_e);
 static void checkGlobUse (uentry p_glob, bool p_isCall, /*@notnull@*/ exprNode p_e);
 static void exprNode_addUse (exprNode p_e, /*@exposed@*/ sRef p_s);
 static bool exprNode_matchArgType (ctype p_ct, exprNode p_e);
@@ -82,8 +83,7 @@ static /*@observer@*/ cstring exprNode_rootVarName (exprNode p_e);
 static /*@exposed@*/ exprNode 
   exprNode_lastStatement (/*@returned@*/ exprNode p_e);
 
-static /*@null@*/ sRef defref = sRef_undefined;
-static /*@only@*/ exprNode mustExitNode = exprNode_undefined;
+static /*@only@*/ exprNode s_mustExitNode = exprNode_undefined;
 
 static int checkArgsReal (uentry p_fcn, /*@dependent@*/ exprNode p_f, 
                          uentryList p_cl, 
@@ -138,8 +138,6 @@ void exprNode_initMod (void)
   ctypeType = ctype_unknown;
   filelocType = ctype_unknown;
 
-  defref = sRef_undefined;
-  
   if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
     {
       cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
@@ -217,24 +215,25 @@ void exprNode_initMod (void)
 void
 exprNode_destroyMod (void) 
    /*@globals killed regArg, killed outArg, killed outStringArg,
-             killed mustExitNode, initMod @*/
+             killed s_mustExitNode, initMod @*/
 {
   if (initMod)
     {
-      uentry_free (regArg);
-      uentry_free (outArg);
-      uentry_free (outStringArg);
+      /* evans 2002-07-12: changed uentry_free to uentry_freeComplete */
+      uentry_freeComplete (regArg);
+      uentry_freeComplete (outArg);
+      uentry_freeComplete (outStringArg);
       
-      exprNode_free (mustExitNode);
+      exprNode_free (s_mustExitNode);
       initMod = FALSE;
-    /*@-branchstate@*/ 
+      /*@-branchstate@*/ 
     } 
   /*@=branchstate@*/
 }
 
 static void exprNode_resetSref (/*@notnull@*/ exprNode e)
 {
-  e->sref = defref;
+  e->sref = sRef_undefined;
 }
 
 exprNode exprNode_fakeCopy (exprNode e)
@@ -439,7 +438,7 @@ static /*@notnull@*/ /*@special@*/ exprNode
   e->typ = c;
   e->kind = XPR_EMPTY;
   e->val = multiVal_undefined;
-  e->sref = defref;
+  e->sref = sRef_undefined;
   e->etext = cstring_undefined;
   e->loc = fileloc_undefined;
   e->guards = guardSet_undefined;
@@ -459,13 +458,13 @@ static /*@notnull@*/ /*@special@*/ exprNode
 
 /*@observer@*/ exprNode exprNode_makeMustExit (void)
 {
-  if (exprNode_isUndefined (mustExitNode))
+  if (exprNode_isUndefined (s_mustExitNode))
     {
-      mustExitNode = exprNode_createPlain (ctype_unknown);
-      mustExitNode->exitCode = XK_MUSTEXIT;
+      s_mustExitNode = exprNode_createPlain (ctype_unknown);
+      s_mustExitNode->exitCode = XK_MUSTEXIT;
     }
 
-  return mustExitNode;
+  return s_mustExitNode;
 }
 
 
@@ -551,7 +550,7 @@ static /*@notnull@*/ /*@special@*/ exprNode
     }
 
   ret->kind = XPR_EMPTY;
-  ret->sref = defref;
+  ret->sref = sRef_undefined;
   ret->etext = cstring_undefined;
   ret->exitCode = XK_NEVERESCAPE;
   ret->canBreak = FALSE;
@@ -603,7 +602,7 @@ static /*@notnull@*/ /*@special@*/ exprNode
   
   ret->val = multiVal_undefined;
   ret->kind = XPR_EMPTY;
-  ret->sref = defref;
+  ret->sref = sRef_undefined;
   ret->etext = cstring_undefined;
   ret->exitCode = XK_NEVERESCAPE;
   ret->canBreak = FALSE;
@@ -640,7 +639,7 @@ static /*@notnull@*/ /*@special@*/ exprNode
       ret->msets = sRefSet_undefined;
 
       ret->kind = XPR_EMPTY;
-      ret->sref = defref;
+      ret->sref = sRef_undefined;
       ret->etext = cstring_undefined;
       ret->exitCode = XK_NEVERESCAPE;
       ret->canBreak = FALSE;
@@ -676,7 +675,13 @@ exprNode_isUnknownConstant (/*@notnull@*/ exprNode e)
   while (e->kind == XPR_PARENS)
     {
       e = exprData_getUopNode (e->edata);
-      llassert (exprNode_isDefined (e));
+      
+      if (!exprNode_isDefined (e))
+       {
+         return FALSE;
+       }
+
+      /* evans 2002-02-05: was llassert (exprNode_isDefined (e)); but this can fail */
     }
 
   if (e->kind == XPR_CONST)
@@ -809,17 +814,17 @@ exprNode_combineLiterals (exprNode e, exprNode rest)
 exprNode_rawStringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc)
 {
   exprNode e = exprNode_createLoc (ctype_string, loc);
-  int len = cstring_length (t);
+  size_t len = cstring_length (t);
 
   if (context_getFlag (FLG_STRINGLITERALLEN))
     {
-      if (len > context_getValue (FLG_STRINGLITERALLEN))
+      if (len > size_fromInt (context_getValue (FLG_STRINGLITERALLEN)))
        {
          voptgenerror (FLG_STRINGLITERALLEN,
                        message
                        ("String literal length (%d) exceeds maximum "
                         "length (%d): \"%s\"",
-                        len,
+                        size_toInt (len),
                         context_getValue (FLG_STRINGLITERALLEN),
                         t),
                        e->loc);
@@ -849,19 +854,18 @@ exprNode_wideStringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc)
 {
   exprNode res = exprNode_stringLiteral (t, loc);
   res->typ = ctype_makeWideString ();
-
   return res;
 }
 
 /*@only@*/ exprNode
 exprNode_stringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc)
 {
-  int len = cstring_length (t) - 2;
+  size_t len = size_fromInt (cstring_length (t) - 2);
   char *ts = cstring_toCharsSafe (t);
   char *s = cstring_toCharsSafe (cstring_create (len + 1));
 
   llassert (*ts == '\"' && *(ts + len + 1) == '\"');
-  strncpy (s, ts+1, size_fromInt (len));
+  strncpy (s, ts+1, len);
   *(s + len) = '\0';
   cstring_free (t);
   return exprNode_rawStringLiteral (cstring_fromCharsO (s), loc);
@@ -880,7 +884,7 @@ exprNode exprNode_fromUIO (cstring c)
     }
 
   e->loc = loc; /* save loc was mangled */
-  e->sref = defref;
+  e->sref = sRef_undefined;
 
   if (usymtab_exists (c))
     {
@@ -979,7 +983,7 @@ exprNode exprNode_createId (/*@observer@*/ uentry c)
       
       /*
       ** yoikes!  leaving this out was a heinous bug...that would have been
-      ** caught if i had lclint working first.  gag!
+      ** caught if i had splint working first.  gag!
       */
       
       e->etext = cstring_undefined;
@@ -1009,14 +1013,13 @@ exprNode exprNode_createId (/*@observer@*/ uentry c)
       e->msets = sRefSet_new ();
       e->uses = sRefSet_new ();
       
-      /*> missing fields, detected by lclint <*/
+      /*> missing fields, detected by splint <*/
       e->exitCode = XK_NEVERESCAPE;
       e->isJumpPoint = FALSE;
       e->canBreak = FALSE;
       e->mustBreak = FALSE;
       
-      exprNode_defineConstraints(e);
-
+      exprNode_defineConstraints (e);
       return e;
     }
   else
@@ -1032,7 +1035,7 @@ exprNode_fromIdentifier (/*@observer@*/ uentry c)
 
   if (context_justPopped ()) /* watch out! c could be dead */
     { 
-      uentry ce = usymtab_lookupSafe (LastIdentifier ());
+      uentry ce = usymtab_lookupSafe (cscanner_observeLastIdentifier ());
 
       if (uentry_isValid (ce)) 
         {
@@ -1048,39 +1051,59 @@ exprNode_fromIdentifier (/*@observer@*/ uentry c)
   return ret;
 }
 
-
 static void exprNode_checkStringLiteralLength (ctype t1, exprNode e2)
 {
   multiVal mval = exprNode_getValue (e2);
   cstring slit;
-  int len;
+  size_t len;
 
   if (ctype_isFixedArray (t1))
     {
-      int nelements = long_toInt (ctype_getArraySize (t1));
+      size_t nelements = ctype_getArraySize (t1);
       
       llassert (multiVal_isString (mval));
       slit = multiVal_forceString (mval);
-      len = cstring_length (slit);
       
+      len = cstring_lengthExpandEscapes (slit);
+      
+      llassert (exprNode_isDefined (e2));
+
       if (len == nelements)
        {
-         voptgenerror 
-           (FLG_STRINGLITNOROOM,
-            message ("String literal with %d character%& "
-                     "is assigned to %s (no room for null terminator): %s",
-                     cstring_length (slit),
-                     ctype_unparse (t1),
-                     exprNode_unparse (e2)),
-            e2->loc);                        
+         mstring temp;
+
+         temp = cstring_expandEscapes (slit);
+
+         if (temp[len-1] == '\0')
+           {
+             voptgenerror 
+               (FLG_STRINGLITNOROOMFINALNULL,
+                message ("String literal with %d character%& "
+                         "is assigned to %s (no room for final null terminator): %s",
+                         len + 1,
+                         ctype_unparse (t1),
+                         exprNode_unparse (e2)),
+                e2->loc);
+           }
+         else
+           {
+             voptgenerror 
+               (FLG_STRINGLITNOROOM,
+                message ("String literal with %d character%& "
+                         "is assigned to %s (no room for null terminator): %s",
+                         len + 1,
+                         ctype_unparse (t1),
+                         exprNode_unparse (e2)),
+                e2->loc);
+           }
        }
       else if (len > nelements) 
        {
          voptgenerror 
            (FLG_STRINGLITTOOLONG,
-            message ("Stirng literal with %d character%& (counting null terminator) "
+            message ("String literal with %d character%& (counting null terminator) "
                      "is assigned to %s (insufficient storage available): %s",
-                     cstring_length (slit),
+                     len + 1,
                      ctype_unparse (t1),
                      exprNode_unparse (e2)),
             e2->loc);                        
@@ -1090,7 +1113,7 @@ static void exprNode_checkStringLiteralLength (ctype t1, exprNode e2)
          voptgenerror 
            (FLG_STRINGLITSMALLER,
             message ("String literal with %d character%& is assigned to %s (possible waste of storage): %s",
-                     cstring_length (slit),
+                     len + 1,
                      ctype_unparse (t1),
                      exprNode_unparse (e2)),
             e2->loc);    
@@ -1194,7 +1217,7 @@ exprNode_arrayFetch (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
  
       /*
       ** this sets up funny aliasing, that leads to spurious
-      ** lclint errors.  Hence, the i2 comments.
+      ** splint errors.  Hence, the i2 comments.
       */
 
       /* evans 2001-09-09 added ctype_isKnown so there is no swap when e1 type is unknown */
@@ -1626,8 +1649,11 @@ checkPrintfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
                          
                        case 'p': /* pointer */
                          expecttype = ctype_makePointer (ctype_void);
-                         uentry_setDefState (regArg, SS_RELDEF); /* need not be defined */
-                         sRef_setPosNull (uentry_getSref (regArg), fileloc_undefined); /* could be null */
+                         /* need not be defined */
+                         uentry_setDefState (regArg, SS_RELDEF); 
+                         sRef_setPosNull (uentry_getSref (regArg), 
+                                          fileloc_undefined); 
+                         /* could be null */
                          /*@switchbreak@*/ break;
                          
                        case 'n': /* pointer to int, modified by call! */
@@ -2020,7 +2046,7 @@ checkScanfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
                        }
                      else
                        {
-                                                 /* a->sref = defref; */
+                                                 /* a->sref = sRef_undefined; */
                        }
                    }
                }
@@ -2160,6 +2186,14 @@ checkMessageArgs (/*@notnull@*/ /*@dependent@*/ exprNode f,
                        case 'f': expecttype = ctype_float; break;
                        case 'b': expecttype = ctype_bool; break;
                        case 't': expecttype = ctypeType; break;
+                       case 'p': 
+                         expecttype = ctype_makePointer (ctype_void);
+                         /* need not be defined */
+                         uentry_setDefState (regArg, SS_RELDEF); 
+                         sRef_setPosNull (uentry_getSref (regArg), 
+                                          fileloc_undefined); 
+                         /* could be null */
+                         /*@switchbreak@*/ break;
                        case 'l': expecttype = filelocType; break;
                        case '&':  /* a wee bit of a hack methinks */
                          expecttype = ctype_int;
@@ -3142,7 +3176,7 @@ checkGlobMods (/*@notnull@*/ /*@dependent@*/ exprNode f,
   if (freshMods)
     {
       /*
-      ** Spurious errors reported, because lclint can't tell
+      ** Spurious errors reported, because splint can't tell
       ** mods must be fresh if freshMods is true.
       */
 
@@ -3270,7 +3304,9 @@ reflectEnsuresClause (exprNode ret, uentry le, exprNode f, exprNodeList args)
                      sRefSet srs = stateClause_getRefs (cl);
                      sRefModVal modf = stateClause_getEnsuresFunction (cl);
                      int eparam = stateClause_getStateParameter (cl);
-                     
+
+                     llassert (modf != NULL);
+
                      DPRINTF (("Reflect after clause: %s / %s", 
                                stateClause_unparse (cl),
                                sRefSet_unparse (srs)));
@@ -3644,6 +3680,8 @@ checkRequiresClause (uentry le, exprNode f, exprNodeList args)
                                stateClause_unparse (cl),
                                sRefSet_unparse (srs)));
                      
+                     llassert (modf != NULL);
+
                      sRefSet_elements (srs, sel)
                        {
                          sRef s;
@@ -3741,7 +3779,7 @@ functionCallSafe (/*@only@*/ /*@notnull@*/ exprNode f,
       /* f->typ is already set to the return type */
 
       DPRINTF (("Function: %s", uentry_unparseFull (le)));
-      ret->sref = uentry_returnedRef (le, args);
+      ret->sref = uentry_returnedRef (le, args, exprNode_loc (f));
       DPRINTF (("Returned: %s / %s",
                uentry_unparseFull (le),
                sRef_unparseFull (ret->sref)));
@@ -3850,7 +3888,7 @@ functionCallSafe (/*@only@*/ /*@notnull@*/ exprNode f,
     }
   else
     {
-      ret->sref = defref;
+      ret->sref = sRef_undefined;
       exprNode_checkSetAny (ret, uentry_rawName (le));
     }
 
@@ -3859,6 +3897,7 @@ functionCallSafe (/*@only@*/ /*@notnull@*/ exprNode f,
   reflectEnsuresClause (ret, le, f, args);
   setCodePoint ();
 
+  DPRINTF (("Here: %s", sRef_unparseFull (ret->sref)));
   return (ret);
 }
 
@@ -3911,7 +3950,9 @@ exprNode_functionCall (/*@only@*/ exprNode f, /*@only@*/ exprNodeList args)
 {
   ctype t;
 
-  setCodePoint ();
+# ifdef DEBUGSPLINT
+  usymtab_checkAllValid ();
+# endif
 
   if (exprNode_isUndefined (f))
     {
@@ -4090,7 +4131,7 @@ exprNode_fieldAccess (/*@only@*/ exprNode s, /*@only@*/ lltok dot,
                      /*@only@*/ cstring f)
 {
   exprNode res = exprNode_fieldAccessAux (s, lltok_getLoc (dot), f);
-  lltok_release (dot);
+  lltok_free (dot);
   return res;
 }
 
@@ -4294,7 +4335,7 @@ exprNode_arrowAccess (/*@only@*/ exprNode s,
                      /*@only@*/ cstring f)
 {
   exprNode res = exprNode_arrowAccessAux (s, lltok_getLoc (arrow), f);
-  lltok_release (arrow);
+  lltok_free (arrow);
   return res;
 }
 
@@ -4933,7 +4974,7 @@ exprNode_cast (/*@only@*/ lltok tok, /*@only@*/ exprNode e, /*@only@*/ qtype q)
   if (exprNode_isError (e))
     {
       qtype_free (q);
-      lltok_release (tok);
+      lltok_free (tok);
       return exprNode_undefined;
     }
 
@@ -4949,28 +4990,18 @@ exprNode_cast (/*@only@*/ lltok tok, /*@only@*/ exprNode e, /*@only@*/ qtype q)
   ret->kind = XPR_CAST;
   ret->edata = exprData_makeCast (tok, e, q);
 
-  if (ctype_isRealSU (ctype_getBaseType (sRef_getType (e->sref))))
-    {
-      /* 
-      ** This is a bit of a hack to avoid a problem
-      ** when the code does,
-      **          (some other struct) x
-      **          ...
-      **          x->field
-      */
+  ret->sref = sRef_copy (e->sref);
+  
+  DPRINTF (("Cast 2: -> %s", sRef_unparseFull (ret->sref)));
 
-      ret->sref = sRef_copy (e->sref);
-      usymtab_addForceMustAlias (ret->sref, e->sref);
-      sRef_setTypeFull (ret->sref, c);
-      DPRINTF (("Cast: %s -> %s", sRef_unparseFull (e->sref),
-               sRef_unparseFull (ret->sref)));
-    }
-  else
+  if (!sRef_isConst (e->sref))
     {
-      ret->sref = e->sref;
-      sRef_setTypeFull (ret->sref, c);
-      DPRINTF (("Cast 2: -> %s", sRef_unparseFull (ret->sref)));
+      usymtab_addForceMustAlias (ret->sref, e->sref);
     }
+  
+  DPRINTF (("Cast 2: -> %s", sRef_unparseFull (ret->sref)));
+  sRef_setTypeFull (ret->sref, c);
+  DPRINTF (("Cast 2: -> %s", sRef_unparseFull (ret->sref)));
 
   /*
   ** we allow
@@ -4982,7 +5013,18 @@ exprNode_cast (/*@only@*/ lltok tok, /*@only@*/ exprNode e, /*@only@*/ qtype q)
 
   if (ctype_isVoid (c)) /* cast to void is always okay --- discard value */
     {
-      ;
+      /* evans 2002-07-19: added this warning */
+      DPRINTF (("Checking: %s / %s", exprNode_unparse (ret), sRef_unparseFull (ret->sref)));
+      if (sRef_isFresh (ret->sref))
+       {
+         voptgenerror 
+           (FLG_MUSTFREEFRESH,
+            message ("New fresh storage %q(type %s) cast to void (not released): %s",
+                     sRef_unparseOpt (ret->sref),
+                     ctype_unparse (exprNode_getType (ret)),
+                     exprNode_unparse (ret)),
+            exprNode_loc (ret));
+       }
     }
   else if (ctype_isRealAP (c)) /* casting to array or pointer */
     {
@@ -5970,8 +6012,7 @@ void exprNode_checkAssignMod (exprNode e1, exprNode ret)
 }
 
 exprNode
-exprNode_assign (/*@only@*/ exprNode e1,
-                /*@only@*/ exprNode e2, /*@only@*/ lltok op)
+exprNode_assign (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2, /*@only@*/ lltok op)
 {
   bool isalloc = FALSE;
   bool isjustalloc = FALSE;
@@ -5992,13 +6033,17 @@ exprNode_assign (/*@only@*/ exprNode e1,
                ctype_unparse (e1->typ),
                ctype_unparse (e2->typ)));
 
-      if (ctype_isNumeric (e2->typ)
-         || ctype_isNumeric (e1->typ))
+      if (exprNode_isDefined (e1)
+         && exprNode_isDefined (e2))
        {
-         /* Its a pointer arithmetic expression like ptr += i */
-         noalias = TRUE;
-       }
-    } 
+         if (ctype_isNumeric (e2->typ)
+             || ctype_isNumeric (e1->typ))
+           {
+             /* Its a pointer arithmetic expression like ptr += i */
+             noalias = TRUE;
+           }
+       } 
+    }
   else 
     {
       ret = exprNode_createPartialCopy (e1);
@@ -6098,7 +6143,17 @@ exprNode_assign (/*@only@*/ exprNode e1,
              ctype te1 = exprNode_getType (e1);
              ctype te2 = exprNode_getType (e2);
              
-             if (!ctype_forceMatch (te1, te2))
+             if (ctype_isVoid (te2))
+               {
+                 (void) gentypeerror 
+                   (te2, e2, te1, e1,
+                    message ("Assignment of void value to %t: %s %s %s", 
+                             te1, exprNode_unparse (e1),
+                             lltok_unparse (op), 
+                             exprNode_unparse (e2)),
+                    e1->loc);
+               }
+             else if (!ctype_forceMatch (te1, te2))
                {
                  if (exprNode_matchLiteral (te1, e2))
                    {
@@ -6115,6 +6170,10 @@ exprNode_assign (/*@only@*/ exprNode e1,
                         e1->loc);
                    }
                }
+             else
+               {
+                 /* Type checks okay */
+               }
            }
         
          exprNode_mergeUSs (ret, e2);
@@ -6663,6 +6722,7 @@ exprNode exprNode_concat (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
       usymtab_setMustBreak ();
     }
 
+  DPRINTF (("==> %s", exprNode_unparse (ret)));
   return ret;
 }
 
@@ -6679,7 +6739,7 @@ exprNode exprNode_statement (/*@only@*/ exprNode e, /*@only@*/ lltok t)
 {
   if (!exprNode_isError (e))
     {
-      exprNode_checkStatement(e);
+      exprChecks_checkStatementEffect(e);
     }
 
   return (exprNode_statementError (e, t));
@@ -6734,6 +6794,36 @@ void exprNode_produceGuards (exprNode pred)
     }
 }
 
+exprNode exprNode_compoundStatementExpression (/*@only@*/ lltok tlparen, /*@only@*/ exprNode e)
+{
+  exprNode laststmt;
+
+  DPRINTF (("Compound: %s", exprNode_unparse (e)));
+
+  if (!context_flagOn (FLG_GNUEXTENSIONS, exprNode_loc (e)))
+    {
+      (void) llgenhinterror 
+       (FLG_SYNTAX,
+        message ("Compound statement expressions is not supported by ISO C99"),
+        message ("Use +gnuextensions to allow compound statement expressions (and other GNU language extensions) "
+                 "without this warning"),
+        exprNode_loc (e));
+    }
+
+  /*
+  ** The type of a compoundStatementExpression is the type of the last statement 
+  */
+  
+  llassert (exprNode_isBlock (e));
+  laststmt = exprNode_lastStatement (e);
+
+  DPRINTF (("Last statement: %s / %s", exprNode_unparse (laststmt), ctype_unparse (exprNode_getType (laststmt))));
+  DPRINTF (("e: %s", exprNode_unparse (e)));
+  e->typ = exprNode_getType (laststmt);
+  return exprNode_addParens (tlparen, e);
+}
+
+
 exprNode exprNode_makeBlock (/*@only@*/ exprNode e)
 {
   exprNode ret = exprNode_createPartialCopy (e);
@@ -6745,8 +6835,10 @@ exprNode exprNode_makeBlock (/*@only@*/ exprNode e)
       ret->mustBreak = e->mustBreak;
     }
   
+  DPRINTF (("Block e: %s", exprNode_unparse (e)));
   ret->edata = exprData_makeSingle (e);
   ret->kind = XPR_BLOCK;
+  DPRINTF (("Block: %s", exprNode_unparse (ret)));
   return ret;
 }
 
@@ -6755,6 +6847,12 @@ bool exprNode_isBlock (exprNode e)
   return (exprNode_isDefined (e) 
          && ((e)->kind == XPR_BLOCK));
 }
+
+bool exprNode_isStatement (exprNode e)
+{
+  return (exprNode_isDefined (e) 
+         && ((e)->kind == XPR_STMT));
+}
  
 bool exprNode_isAssign (exprNode e)
 {
@@ -6773,6 +6871,22 @@ bool exprNode_isEmptyStatement (exprNode e)
          && (lltok_isSemi (exprData_getTok (e->edata))));
 }
 
+bool exprNode_isMultiStatement (exprNode e)
+{
+  return (exprNode_isDefined (e)
+         && ((e->kind == XPR_FOR)
+             || (e->kind == XPR_FORPRED)
+             || (e->kind == XPR_IF)
+             || (e->kind == XPR_IFELSE)
+             || (e->kind == XPR_WHILE)
+             || (e->kind == XPR_WHILEPRED)
+             || (e->kind == XPR_DOWHILE)
+             || (e->kind == XPR_BLOCK)
+             || (e->kind == XPR_STMT)
+             || (e->kind == XPR_STMTLIST)
+             || (e->kind == XPR_SWITCH)));
+}
+
 void exprNode_checkIfPred (exprNode pred)
 {
   exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
@@ -7012,6 +7126,9 @@ checkSwitchExpr (exprNode test, /*@dependent@*/ exprNode e, /*@out@*/ bool *allp
 
   exprNodeSList_elements (el, current)
     {
+      
+      DPRINTF ((message("checkSwitchExpr current = %s ", exprNode_unparse(current) ) ));
+      
       if (exprNode_isDefined (current))
        {
          switch (current->kind)
@@ -8095,7 +8212,7 @@ static bool exprNode_checkOneInit (/*@notnull@*/ exprNode el, exprNode val)
   if (exprNode_isDefined (val) && val->kind == XPR_INITBLOCK)
     {
       exprNodeList vals = exprData_getArgs (val->edata);
-
+      
       DPRINTF (("Check one init: %s", exprNodeList_unparse (vals)));
       DPRINTF (("Type: %s", ctype_unparse (t1)));
 
@@ -8106,18 +8223,22 @@ static bool exprNode_checkOneInit (/*@notnull@*/ exprNode el, exprNode val)
 
          if (ctype_isFixedArray (t1))
            {
-             int nelements = long_toInt (ctype_getArraySize (t1));
+             size_t nelements = ctype_getArraySize (t1);
              
+             DPRINTF (("Checked array: %s / %d",
+                       ctype_unparse (t1), nelements));
+
              if (exprNode_isStringLiteral (val))
                {
                  exprNode_checkStringLiteralLength (t1, val);
                }
              else
                {
-                 if (exprNodeList_size (vals) != nelements) 
+                 if (exprNodeList_size (vals) != size_toInt (nelements))
                    {
                      hasError = optgenerror 
-                       (exprNodeList_size (vals) > nelements ? FLG_INITSIZE : FLG_INITALLELEMENTS,
+                       (exprNodeList_size (vals) > size_toInt (nelements) 
+                        ? FLG_INITSIZE : FLG_INITALLELEMENTS,
                         message ("Initializer block for "
                                  "%s has %d element%&, but declared as %s: %q",
                                  exprNode_unparse (el),
@@ -8315,7 +8436,7 @@ static bool exprNode_checkOneInit (/*@notnull@*/ exprNode el, exprNode val)
   return hasError;
 }
 
-static exprNode 
+static /*@notnull@*/ exprNode 
 exprNode_makeInitializationAux (/*@temp@*/ idDecl t)
 {
   exprNode ret;
@@ -8384,7 +8505,6 @@ exprNode_makeInitializationAux (/*@temp@*/ idDecl t)
 
   exprData_free (ret->edata, ret->kind); 
   ret->edata = exprData_undefined;
-
   ret->exitCode = XK_NEVERESCAPE;
   ret->mustBreak = FALSE;
   ret->kind = XPR_INIT;
@@ -8405,14 +8525,15 @@ exprNode exprNode_makeInitialization (/*@only@*/ idDecl t,
   uentry ue = usymtab_lookup (idDecl_observeId (t));
   exprNode ret = exprNode_makeInitializationAux (t);
   fileloc loc = exprNode_loc (e);
-  
+
+  DPRINTF (("initialization: %s = %s", idDecl_unparse (t), exprNode_unparse (e)));
+
   if (exprNode_isError (e)) 
     {
       e = exprNode_createUnknown ();
-      idDecl_free (t);
-
       /* error: assume initializer is defined */
       sRef_setDefined (ret->sref, g_currentloc); 
+      ret->edata = exprData_makeInit (t, e);
     }
   else
     {
@@ -8428,6 +8549,7 @@ exprNode exprNode_makeInitialization (/*@only@*/ idDecl t,
 
       exprData_free (ret->edata, ret->kind);
       ret->edata = exprData_makeInit (t, e);
+      DPRINTF (("ret: %s", exprNode_unparse (ret)));
 
       exprNode_checkUse (ret, e->sref, e->loc);
       
@@ -8480,14 +8602,42 @@ exprNode exprNode_makeInitialization (/*@only@*/ idDecl t,
          sRef_setDefState (ret->sref, SS_PARTIAL, fileloc_undefined);
        }
 
-      doAssign (ret, e, TRUE);
+      if (exprNode_isStringLiteral (e)
+         && (ctype_isArray (ct))
+         && (ctype_isChar (ctype_realType (ctype_baseArrayPtr (ct)))))
+       {
+         /*
+         ** If t is a char [], the literal is copied.
+         */
+
+         exprNode_checkStringLiteralLength (ct, e);
+         sRef_setDefState (ret->sref, SS_DEFINED, e->loc);
+         ret->val = multiVal_copy (e->val);
+
+         sRef_setNullTerminatedState (ret->sref);
+         
+         if (multiVal_isDefined (e->val))
+           {
+             cstring slit = multiVal_forceString (e->val);
+             sRef_setLen (ret->sref, cstring_length (slit) + 1);
+           }
+
+         if (ctype_isFixedArray (ct))
+           {
+             sRef_setSize (ret->sref, size_toInt (ctype_getArraySize (ct)));
+           }
+       }
+      else
+       {
+         doAssign (ret, e, TRUE);
+       }
 
       if (uentry_isStatic (ue))
        {
          sRef_setDefState (ret->sref, SS_DEFINED, fileloc_undefined);
        }
     }
-
+  
   if (context_inIterDef ())
     {
       /* should check if it is yield */
@@ -8499,6 +8649,15 @@ exprNode exprNode_makeInitialization (/*@only@*/ idDecl t,
     }
 
   exprNode_mergeUSs (ret, e);
+  DPRINTF (("Ret: %s %p %p",
+           exprNode_unparse (ret),
+           ret->requiresConstraints,
+           ret->ensuresConstraints));
+
+  DPRINTF (("Ret: %s %s %s",
+           exprNode_unparse (ret),
+           constraintList_unparse (ret->requiresConstraints),
+           constraintList_unparse (ret->ensuresConstraints)));
   return ret;
 }
   
@@ -8582,11 +8741,11 @@ exprNode_iterNewId (/*@only@*/ cstring s)
   e->kind = XPR_VAR;
   e->val = multiVal_unknown ();
   e->guards = guardSet_new ();
-  e->sref = defref;
+  e->sref = sRef_undefined;
   e->isJumpPoint = FALSE;
   e->exitCode = XK_NEVERESCAPE;
 
-  /*> missing fields, detected by lclint <*/
+  /*> missing fields, detected by splint <*/
   e->canBreak = FALSE;
   e->mustBreak = FALSE;
   e->etext = cstring_undefined;
@@ -8773,8 +8932,7 @@ exprNode exprNode_iterStart (/*@observer@*/ uentry name, /*@only@*/ exprNodeList
 {
   if (exprNode_isDefined (e))
     {
-      /*@access sRef@*/
-      if (e->sref == defref) /*@noaccess sRef@*/
+      if (sRef_isInvalid (e->sref))
        {
          /*@-mods@*/
          e->sref = sRef_makeUnknown (); 
@@ -8955,9 +9113,47 @@ static /*@only@*/ exprNode exprNode_effect (exprNode e)
                                     exprNode_effect (exprData_getPairB (data)));
          break;
        case XPR_OP:
-         ret = exprNode_op (exprNode_effect (exprData_getOpA (data)), 
-                            exprNode_effect (exprData_getOpB (data)), 
-                            exprData_getOpTok (data));
+         /*
+         ** evans 2002-03-15: for && and ||, need to do the guards also
+         **                   this is what cgrammar.y does - should be
+         **                   able to avoid duplication, but need to
+         **                   time with grammar productions.
+         */
+
+         DPRINTF (("Effect: %s", exprNode_unparse (e)));
+
+         if (lltok_getTok (exprData_getOpTok (data)) == AND_OP)
+           {
+             exprNode e1 = exprNode_effect (exprData_getOpA (data));
+             exprNode e2;
+             exprNode_produceGuards (e1);
+             context_enterAndClause (e1);
+             e2 = exprNode_effect (exprData_getOpB (data));
+
+             ret = exprNode_op (e1, e2,
+                                exprData_getOpTok (data));
+
+             context_exitAndClause (ret, e2);
+           }
+         else if (lltok_getTok (exprData_getOpTok (data)) == OR_OP)
+           {
+             exprNode e1 = exprNode_effect (exprData_getOpA (data));
+             exprNode e2;
+             exprNode_produceGuards (e1);
+             context_enterOrClause (e1);
+             e2 = exprNode_effect (exprData_getOpB (data));
+
+             ret = exprNode_op (e1, e2,
+                                exprData_getOpTok (data));
+
+             context_exitOrClause (ret, e2);
+           }
+         else
+           {
+             ret = exprNode_op (exprNode_effect (exprData_getOpA (data)), 
+                                exprNode_effect (exprData_getOpB (data)), 
+                                exprData_getOpTok (data));
+           }
          break;
          
        case XPR_POSTOP:
@@ -9427,17 +9623,31 @@ static /*@only@*/ cstring exprNode_doUnparse (exprNode e)
       break;
       
     case XPR_BLOCK:
-      ret = message ("{ %s }", exprNode_unparseFirst (exprData_getSingle (data)));
+      ret = message ("{ %s }", exprNode_unparse (exprData_getSingle (data)));
+      /* evans 2002-02-20 was unparseFirst! */
       break;
 
     case XPR_STMT:
-      ret = cstring_copy (exprNode_unparse (exprData_getUopNode (data)));
+      ret = message ("%s;", exprNode_unparse (exprData_getUopNode (data)));
       break;
 
     case XPR_STMTLIST:
-      ret = message ("%s; %s", 
-                    exprNode_unparse (exprData_getPairA (data)),
-                    exprNode_unparse (exprData_getPairB (data)));
+      if (exprNode_isStatement (exprData_getPairA (data)))
+       {
+         /*
+         ** statement expressions already print the ;
+         */
+
+         ret = message ("%s %s", 
+                        exprNode_unparse (exprData_getPairA (data)),
+                        exprNode_unparse (exprData_getPairB (data)));
+       }
+      else
+       {
+         ret = message ("%s; %s", 
+                        exprNode_unparse (exprData_getPairA (data)),
+                        exprNode_unparse (exprData_getPairB (data)));
+       }
       break;
       
     case XPR_FTDEFAULT:
This page took 0.132778 seconds and 4 git commands to generate.