]> andersk Git - splint.git/blobdiff - src/exprNode.c
Added realrelatecompare flag.
[splint.git] / src / exprNode.c
index 8940676c3ebe97021473eeb1262b7a5b6e6a9fb7..9ddccbee6ad38af9ed8181316dcdef88a62b2445 100644 (file)
@@ -1,6 +1,6 @@
 /*
 ** Splint - annotation-assisted static program checker
-** Copyright (C) 1994-2002 University of Virginia,
+** Copyright (C) 1994-2003 University of Virginia,
 **         Massachusetts Institute of Technology
 **
 ** This program is free software; you can redistribute it and/or modify it
@@ -29,6 +29,8 @@
 # include "splintMacros.nf"
 # include "basic.h"
 # include "cgrammar.h"
+# include "cscanner.h"
+# include "cscannerHelp.h"
 # include "cgrammar_tokens.h"
 
 # include "exprChecks.h"
@@ -50,9 +52,10 @@ static void checkUniqueParams (exprNode p_fcn,
                               /*@notnull@*/ exprNode p_current, exprNodeList p_args, 
                               int p_paramno, uentry p_ucurrent);
 static void updateAliases (/*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2);
-static void abstractOpError (ctype p_tr1, ctype p_tr2, lltok p_op, 
+static bool abstractOpError (ctype p_tr1, ctype p_tr2, lltok p_op, 
                             /*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2, 
-                            fileloc p_loc1, fileloc p_loc2);
+                            fileloc p_loc1, fileloc p_loc2) 
+   /*@modifies g_warningstream@*/ ;
 static ctype checkNumerics (ctype p_tr1, ctype p_tr2, ctype p_te1, ctype p_te2,
                            /*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2, lltok p_op);
 static void doAssign (/*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2, bool p_isInit);
@@ -218,13 +221,14 @@ exprNode_destroyMod (void)
 {
   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 (s_mustExitNode);
       initMod = FALSE;
-    /*@-branchstate@*/ 
+      /*@-branchstate@*/ 
     } 
   /*@=branchstate@*/
 }
@@ -858,7 +862,7 @@ exprNode_wideStringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc)
 /*@only@*/ exprNode
 exprNode_stringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc)
 {
-  size_t len = size_fromInt (cstring_length (t) - 2);
+  size_t len = size_fromInt (size_toInt (cstring_length (t)) - 2);
   char *ts = cstring_toCharsSafe (t);
   char *s = cstring_toCharsSafe (cstring_create (len + 1));
 
@@ -1007,6 +1011,7 @@ exprNode exprNode_createId (/*@observer@*/ uentry c)
        }
 
       e->guards = guardSet_new ();
+
       e->sets = sRefSet_new ();
       e->msets = sRefSet_new ();
       e->uses = sRefSet_new ();
@@ -1033,7 +1038,7 @@ exprNode_fromIdentifier (/*@observer@*/ uentry c)
 
   if (context_justPopped ()) /* watch out! c could be dead */
     { 
-      uentry ce = usymtab_lookupSafe (LastIdentifier ());
+      uentry ce = usymtab_lookupSafe (cscannerHelp_observeLastIdentifier ());
 
       if (uentry_isValid (ce)) 
         {
@@ -1078,7 +1083,7 @@ static void exprNode_checkStringLiteralLength (ctype t1, exprNode e2)
                (FLG_STRINGLITNOROOMFINALNULL,
                 message ("String literal with %d character%& "
                          "is assigned to %s (no room for final null terminator): %s",
-                         len + 1,
+                         size_toInt (len + 1),
                          ctype_unparse (t1),
                          exprNode_unparse (e2)),
                 e2->loc);
@@ -1089,7 +1094,7 @@ static void exprNode_checkStringLiteralLength (ctype t1, exprNode e2)
                (FLG_STRINGLITNOROOM,
                 message ("String literal with %d character%& "
                          "is assigned to %s (no room for null terminator): %s",
-                         len + 1,
+                         size_toInt (len + 1),
                          ctype_unparse (t1),
                          exprNode_unparse (e2)),
                 e2->loc);
@@ -1101,7 +1106,7 @@ static void exprNode_checkStringLiteralLength (ctype t1, exprNode e2)
            (FLG_STRINGLITTOOLONG,
             message ("String literal with %d character%& (counting null terminator) "
                      "is assigned to %s (insufficient storage available): %s",
-                     len + 1,
+                     size_toInt (len + 1),
                      ctype_unparse (t1),
                      exprNode_unparse (e2)),
             e2->loc);                        
@@ -1111,7 +1116,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",
-                     len + 1,
+                     size_toInt (len + 1),
                      ctype_unparse (t1),
                      exprNode_unparse (e2)),
             e2->loc);    
@@ -1243,18 +1248,21 @@ exprNode_arrayFetch (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
         {
           if (!usymtab_isGuarded (arr->sref))
             {
-              if (optgenerror (FLG_NULLDEREF,
-                              message ("Index of %s pointer %q: %s", 
-                                       sRef_nullMessage (arr->sref),
-                                       sRef_unparse (arr->sref),
-                                       exprNode_unparse (arr)),
-                              arr->loc))
-               {
-                 DPRINTF (("ref: %s", sRef_unparseFull (arr->sref)));
-                 sRef_showNullInfo (arr->sref);
-
-                 /* suppress future messages */
-                 sRef_setNullError (arr->sref); 
+             if (!context_inSizeof() )
+               {
+                 if (optgenerror (FLG_NULLDEREF,
+                                  message ("Index of %s pointer %q: %s", 
+                                           sRef_nullMessage (arr->sref),
+                                           sRef_unparse (arr->sref),
+                                           exprNode_unparse (arr)),
+                                  arr->loc))
+                   {
+                     DPRINTF (("ref: %s", sRef_unparseFull (arr->sref)));
+                     sRef_showNullInfo (arr->sref);
+                     
+                     /* suppress future messages */
+                     sRef_setNullError (arr->sref); 
+                   }
                }
             }
         }
@@ -1323,6 +1331,15 @@ exprNode_arrayFetch (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
                              exprNode_unparse (e1), exprNode_unparse (e2)),
                     arr->loc);
                }
+              else if (ctype_isNumAbstract (rt))
+               {
+                 vnoptgenerror 
+                   (FLG_NUMABSTRACTINDEX,
+                    message ("Array fetch using numabstract type, %t: %s[%s]",
+                             ind->typ, 
+                             exprNode_unparse (e1), exprNode_unparse (e2)),
+                    arr->loc);
+               }
               else
                {
                  voptgenerror 
@@ -1616,11 +1633,9 @@ checkPrintfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
                          expecttype = ctype_makeConj (ctype_int, 
                                                       ctype_makeConj (ctype_char,
                                                                       ctype_uchar));
-                         /*@i231@*/
                          /* evans 2001-10-05 - changed to reflect correct ISO spec:
                             int converted to char */
                          
-                         /* expecttype = ctype_makeConj (ctype_char, ctype_uchar); */
                          /*@switchbreak@*/ break;
                              
                        case 's': /* string */
@@ -1916,9 +1931,12 @@ checkScanfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
                              
                            case 'i': 
                            case 'd':
+                             expecttype = ctype_makePointer (ctype_combine (ctype_int, modtype));
+                             /*@switchbreak@*/ break;
+
                            case 'x':
                            case 'X': /* unsigned int */
-                             expecttype = ctype_makePointer (ctype_combine (ctype_int, modtype));
+                             expecttype = ctype_makePointer (ctype_combine (ctype_uint, modtype));
                              /*@switchbreak@*/ break;
                              
                            case 'e':
@@ -2229,7 +2247,7 @@ checkMessageArgs (/*@notnull@*/ /*@dependent@*/ exprNode f,
                                            codetext, expecttype,
                                            a->typ, exprNode_unparse (a)),
                                   a->loc))
-                                 {
+                               {
                                  if (fileloc_isDefined (formatloc)
                                      && context_getFlag (FLG_SHOWCOL))
                                    {
@@ -2577,7 +2595,7 @@ static int
                      f->guards = guardSet_union (f->guards, a->guards);
                      
                      DPRINTF (("match arg: %s / %s", ctype_unparse (ct), ctype_unparse (a->typ)));
-
+                     
                      if (!(exprNode_matchArgType (ct, a)))
                        {
                          DPRINTF (("Args mismatch!"));
@@ -2911,7 +2929,7 @@ checkGlobMods (/*@notnull@*/ /*@dependent@*/ exprNode f,
                      uentry_unparse (le)));
       
       params = ctype_argsFunction (ct);
-      return; /*@32 ! remove this? */
+      return; /* No checking for non-function */
     }
 
   /*
@@ -3694,7 +3712,7 @@ checkRequiresClause (uentry le, exprNode f, exprNodeList args)
                          
                          if (sRef_isResult (sRef_getRootBase (sel)))
                            {
-                             ; /*@i423 what do we do about results */
+                             ; /* what do we do about results? */
                            }
                          else
                            {
@@ -3777,7 +3795,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)));
@@ -3895,6 +3913,7 @@ functionCallSafe (/*@only@*/ /*@notnull@*/ exprNode f,
   reflectEnsuresClause (ret, le, f, args);
   setCodePoint ();
 
+  DPRINTF (("Here: %s", sRef_unparseFull (ret->sref)));
   return (ret);
 }
 
@@ -4382,11 +4401,15 @@ exprNode_postOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
     {
       if (ctype_isRealAbstract (t))
         {
-          voptgenerror 
-           (FLG_ABSTRACT,
-            message ("Operand of %s is abstract type (%t): %s",
-                     lltok_unparse (op), t, exprNode_unparse (e)),
-            e->loc);
+         if (ctype_isRealNumAbstract (t)) {
+           ; /* Allow operations on numabstract types */
+         } else {
+           voptgenerror 
+             (FLG_ABSTRACT,
+              message ("Operand of %s is abstract type (%t): %s",
+                       lltok_unparse (op), t, exprNode_unparse (e)),
+              e->loc);
+         }
         }
       else
         {
@@ -4404,12 +4427,6 @@ exprNode_postOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
   exprNode_checkModify (e, ret);
 
   /* added 7/11/2000 D.L */
-  /*@i223*/ 
-  /*DRL 6/8/01 I decided to disable all Splint warnings here since the code 
-    probably needs a rewrite any way */
-
-  /*@i65234@*/
-  /*@ignore@*/
 
   /* updateEnvironmentForPostOp (e); */
   
@@ -4443,6 +4460,8 @@ exprNode_postOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
          printf ("ret->sref is Possibly Null Terminated\n");
        else if (sRef_isNotNullTerminated (ret->sref))
          printf ("ret->sref is Not Null Terminated\n");
+       else
+         {}
       }
     }
     
@@ -4454,7 +4473,6 @@ exprNode_postOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
       }
     }
   }
-  /*@end@*/
   /* end modifications */
 
   return ret;
@@ -4493,15 +4511,22 @@ exprNode_preOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
       if (ctype_isRealAbstract (tr)
          && (!(ctype_isRealBool (te) && (opid == TEXCL))))
        {
-         if (optgenerror (FLG_ABSTRACT,
-                          message ("Operand of %s is abstract type (%t): %s",
-                                   lltok_unparse (op), tr,
-                                   exprNode_unparse (ret)),
-                          e->loc))
+         if (ctype_isRealNumAbstract (tr))
            {
-             tr = te = ctype_unknown;
-             ret->typ = ctype_unknown;
-             sRef_setNullError (e->sref);
+             ; /* no warning for numabstract types */
+           }
+         else
+           {
+             if (optgenerror (FLG_ABSTRACT,
+                              message ("Operand of %s is abstract type (%t): %s",
+                                       lltok_unparse (op), tr,
+                                       exprNode_unparse (ret)),
+                              e->loc))
+               {
+                 tr = te = ctype_unknown;
+                 ret->typ = ctype_unknown;
+                 sRef_setNullError (e->sref);
+               }
            }
        }
     }
@@ -4544,8 +4569,8 @@ exprNode_preOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
 
        /* Arithmetic operations on pointers wil modify the size/len/null terminated 
                 status */
-       if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
-
+       if ((sRef_isPossiblyNullTerminated (e->sref)) 
+           || (sRef_isNullTerminated(e->sref))) {
                ret->sref = sRef_copy (e->sref);
 
                /* Operator : ++ */
@@ -4988,12 +5013,15 @@ exprNode_cast (/*@only@*/ lltok tok, /*@only@*/ exprNode e, /*@only@*/ qtype q)
   ret->edata = exprData_makeCast (tok, e, q);
 
   ret->sref = sRef_copy (e->sref);
-  
+
+  DPRINTF (("Cast: -> %s", sRef_unparseFull (ret->sref)));
+
   if (!sRef_isConst (e->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)));
 
@@ -5007,7 +5035,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 */
     {
@@ -5127,16 +5166,38 @@ exprNode_cast (/*@only@*/ lltok tok, /*@only@*/ exprNode e, /*@only@*/ qtype q)
            }
          else
            {
-             DPRINTF (("No access to: %s / %d",
-                       ctype_unparse (bc), ctype_typeId (bc)));
-             DPRINTF (("Context %s %s",
-                       bool_unparse (context_inFunctionLike ()),
-                       context_unparse ()));
-             voptgenerror 
-               (FLG_ABSTRACT,
-                message ("Cast to abstract type %t: %s", bc, 
-                         exprNode_unparse (ret)),
-                e->loc);
+             if (ctype_isNumAbstract (bc)) 
+               {
+                 if (exprNode_isNumLiteral (e))
+                   {
+                     voptgenerror 
+                       (FLG_NUMABSTRACTCAST,
+                        message ("Cast from literal to numabstract type %t: %s", bc, 
+                                 exprNode_unparse (ret)),
+                        e->loc);
+                   }
+                 else
+                   {
+                     voptgenerror 
+                       (FLG_NUMABSTRACT,
+                        message ("Cast to numabstract type %t: %s", bc, 
+                                 exprNode_unparse (ret)),
+                        e->loc);
+                   }
+               }
+             else
+               {
+                 DPRINTF (("No access to: %s / %d",
+                           ctype_unparse (bc), ctype_typeId (bc)));
+                 DPRINTF (("Context %s %s",
+                           bool_unparse (context_inFunctionLike ()),
+                           context_unparse ()));
+                 voptgenerror 
+                   (FLG_ABSTRACT,
+                    message ("Cast to abstract type %t: %s", bc, 
+                             exprNode_unparse (ret)),
+                    e->loc);
+               }
            }
        }
     }
@@ -5309,10 +5370,14 @@ exprNode_makeOp (/*@keep@*/ exprNode e1, /*@keep@*/ exprNode e2,
 
   if (opid == OR_OP)
     {
+      exprNode_produceGuards (e2); 
       ret->guards = guardSet_or (ret->guards, e2->guards);
     }
   else if (opid == AND_OP)
     {
+      exprNode_produceGuards (e2); /* evans 2003-08-13: need to produce guards for expression */
+      /* Shouldn't this have already happened? */
+      DPRINTF (("Anding guards: %s / %s", guardSet_unparse (ret->guards), guardSet_unparse (e2->guards)));
       ret->guards = guardSet_and (ret->guards, e2->guards);
     }
   else
@@ -5350,191 +5415,195 @@ exprNode_makeOp (/*@keep@*/ exprNode e1, /*@keep@*/ exprNode e2,
         (opid == AND_OP || opid == OR_OP 
          || opid == EQ_OP || opid == NE_OP))))
     {
-      abstractOpError (tr1, tr2, op, e1, e2, e1->loc, e2->loc);
+      if (abstractOpError (tr1, tr2, op, e1, e2, e1->loc, e2->loc)) 
+       {
+         tret = ctype_unknown;
+         goto skiprest;
+       }
     }
-  else if (ctype_isUnknown (te1) || ctype_isUnknown (te2))
+  
+  if (ctype_isUnknown (te1) || ctype_isUnknown (te2))
     {
       /* unknown types, no comparisons possible */
+      goto skiprest;
     }
-  else
+  
+  switch (opid)
     {
-      switch (opid)
+    case TMULT:                /* multiplication and division:           */
+    case TDIV:         /*                                        */
+    case MUL_ASSIGN:   /*    numeric, numeric -> numeric         */
+    case DIV_ASSIGN:   /*                                        */
+      if (opid == TMULT || opid == MUL_ASSIGN)
        {
-       case TMULT:             /* multiplication and division:           */
-       case TDIV:              /*                                        */
-       case MUL_ASSIGN:        /*    numeric, numeric -> numeric         */
-       case DIV_ASSIGN:        /*                                        */
-
-         if (opid == TMULT || opid == MUL_ASSIGN)
-           {
-             ret->val = multiVal_multiply (exprNode_getValue (e1),
-                                           exprNode_getValue (e2));
-           }
-         else
+         ret->val = multiVal_multiply (exprNode_getValue (e1),
+                                       exprNode_getValue (e2));
+       }
+      else
+       {
+         ret->val = multiVal_divide (exprNode_getValue (e1),
+                                     exprNode_getValue (e2));
+       }
+      
+      tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
+      break;
+      
+    case TPLUS:                /* addition and subtraction:               */
+    case TMINUS:       /*    pointer, int     -> pointer          */
+    case SUB_ASSIGN:   /*    int, pointer     -> pointer          */
+    case ADD_ASSIGN:   /*    numeric, numeric -> numeric          */
+      if (opid == TPLUS || opid == ADD_ASSIGN)
+       {
+         ret->val = multiVal_add (exprNode_getValue (e1),
+                                  exprNode_getValue (e2));
+       }
+      else
+       {
+         ret->val = multiVal_subtract (exprNode_getValue (e1),
+                                       exprNode_getValue (e2));
+       }
+      
+      tr1 = ctype_fixArrayPtr (tr1);
+      
+      if ((ctype_isRealPointer (tr1) && !exprNode_isNullValue (e1))
+         && (!ctype_isRealPointer (tr2) && ctype_isRealInt (tr2)))
+       {
+         /* pointer + int */
+         
+         if (context_msgPointerArith ())
            {
-             ret->val = multiVal_divide (exprNode_getValue (e1),
-                                         exprNode_getValue (e2));
+             voptgenerror
+               (FLG_POINTERARITH,
+                message ("Pointer arithmetic (%t, %t): %s", 
+                         te1, te2, exprNode_unparse (ret)),
+                e1->loc);
            }
-                 
-         tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
-         break;
          
-       case TPLUS:             /* addition and subtraction:               */
-       case TMINUS:            /*    pointer, int     -> pointer          */
-       case SUB_ASSIGN:        /*    int, pointer     -> pointer          */
-       case ADD_ASSIGN:        /*    numeric, numeric -> numeric          */
-
-         if (opid == TPLUS || opid == ADD_ASSIGN)
+         /*
+         ** Swap terms so e1 is always the pointer
+         */
+         
+         if (ctype_isRealPointer (tr1))
            {
-             ret->val = multiVal_add (exprNode_getValue (e1),
-                                      exprNode_getValue (e2));
+             ;
            }
          else
            {
-             ret->val = multiVal_subtract (exprNode_getValue (e1),
-                                           exprNode_getValue (e2));
+             exprNode_swap (e1, e2);
            }
-
-         tr1 = ctype_fixArrayPtr (tr1);
-
-         if ((ctype_isRealPointer (tr1) && !exprNode_isNullValue (e1))
-             && (!ctype_isRealPointer (tr2) && ctype_isRealInt (tr2)))
+         
+         if (sRef_possiblyNull (e1->sref)
+             && !usymtab_isGuarded (e1->sref))
            {
-             /* pointer + int */
-
-             if (context_msgPointerArith ())
-               {
-                 voptgenerror
-                   (FLG_POINTERARITH,
-                    message ("Pointer arithmetic (%t, %t): %s", 
-                             te1, te2, exprNode_unparse (ret)),
-                    e1->loc);
-               }
-
-             /*
-             ** Swap terms so e1 is always the pointer
-             */
-
-             if (ctype_isRealPointer (tr1))
-               {
-                 ;
-               }
-             else
-               {
-                 exprNode_swap (e1, e2);
-               }
-
-
-             if (sRef_possiblyNull (e1->sref)
-                 && !usymtab_isGuarded (e1->sref))
-               {
-                 voptgenerror
-                   (FLG_NULLPOINTERARITH,
-                    message ("Pointer arithmetic involving possibly "
-                             "null pointer %s: %s", 
-                             exprNode_unparse (e1), 
-                             exprNode_unparse (ret)),
-                    e1->loc);
-               }
-
-             ret->sref = sRef_copy (e1->sref);
-
-             /* start modifications */
-             /* added by Seejo on 4/16/2000 */
-
-             /* Arithmetic operations on pointers wil modify the size/len/null terminated 
-                status */
-             if ((sRef_isPossiblyNullTerminated (e1->sref)) || (sRef_isNullTerminated(e1->sref))) {
-               int val;
-               /*drl 1-4-2002
-                 added ugly fixed to stop
-                 program from crashing on point + int +int
-                 one day I'll fix this or ask Seejo wtf the codes supposed to do. */
-               
-               if (!multiVal_isInt (e2->val) )
-                 break;
-               /*end drl*/
-               
-               val = (int) multiVal_forceInt (e2->val);
+             voptgenerror
+               (FLG_NULLPOINTERARITH,
+                message ("Pointer arithmetic involving possibly "
+                         "null pointer %s: %s", 
+                         exprNode_unparse (e1), 
+                         exprNode_unparse (ret)),
+                e1->loc);
+           }
+         
+         ret->sref = sRef_copy (e1->sref);
+         
+         /* start modifications */
+         /* added by Seejo on 4/16/2000 */
+         
+         /* Arithmetic operations on pointers wil modify the size/len/null terminated 
+            status */
+         if ((sRef_isPossiblyNullTerminated (e1->sref)) || (sRef_isNullTerminated(e1->sref))) {
+           int val;
+           /*drl 1-4-2002
+             added ugly fixed to stop
+             program from crashing on point + int +int
+             one day I'll fix this or ask Seejo wtf the codes supposed to do. */
+           
+           if (!multiVal_isInt (e2->val) )
+             break;
+           /*end drl*/
+           
+           val = (int) multiVal_forceInt (e2->val);
+           
+           /* Operator : + or += */
+           if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
+             if (sRef_getSize(e1->sref) >= val) {/* Incrementing the pointer by 
+                                                    val should not result in a 
+                                                    size < 0 (size = 0 is ok !) */
                
-               /* Operator : + or += */
-               if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
-                 if (sRef_getSize(e1->sref) >= val) {/* Incrementing the pointer by 
-                                                        val should not result in a 
-                                                        size < 0 (size = 0 is ok !) */
-                   
-                   sRef_setSize (ret->sref, sRef_getSize(e1->sref) - val);
-                   
-                   if (sRef_getLen(e1->sref) == val) { /* i.e. the character at posn val is \0 */
-                     sRef_setNotNullTerminatedState(ret->sref);
-                     sRef_resetLen (ret->sref);
-                   } else {
-                     sRef_setNullTerminatedState(ret->sref);
-                     sRef_setLen (ret->sref, sRef_getLen(e1->sref) - val);
-                   }
-                 }
-               }
+               sRef_setSize (ret->sref, sRef_getSize(e1->sref) - val);
                
-               /* Operator : - or -= */
-               if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
-                 if (sRef_getSize(e1->sref) >= 0) {
-                   sRef_setSize (ret->sref, sRef_getSize(e1->sref) + val);
-                   sRef_setLen (ret->sref, sRef_getLen(e1->sref) + val);
-                 }
+               if (sRef_getLen(e1->sref) == val) { /* i.e. the character at posn val is \0 */
+                 sRef_setNotNullTerminatedState(ret->sref);
+                 sRef_resetLen (ret->sref);
+               } else {
+                 sRef_setNullTerminatedState(ret->sref);
+                 sRef_setLen (ret->sref, sRef_getLen(e1->sref) - val);
                }
              }
-             
-             /* end modifications */  
-
-             sRef_setNullError (ret->sref);
-
-             /*
-             ** Fixed for 2.2c: the alias state of ptr + int is dependent,
-             ** since is points to storage that should not be deallocated
-             ** through this pointer.
-             */
-
-             if (sRef_isOnly (ret->sref) 
-                 || sRef_isFresh (ret->sref)) 
-               {
-                 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
-               }
-             
-             tret = e1->typ;
            }
-         else if ((!ctype_isRealPointer(tr1) && ctype_isRealInt (tr1)) 
-                  && (ctype_isRealPointer (tr2) && !exprNode_isNullValue (e2)))
+           
+           /* Operator : - or -= */
+           if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
+             if (sRef_getSize(e1->sref) >= 0) {
+               sRef_setSize (ret->sref, sRef_getSize(e1->sref) + val);
+               sRef_setLen (ret->sref, sRef_getLen(e1->sref) + val);
+             }
+           }
+         }
+         
+         /* end modifications */  
+         
+         sRef_setNullError (ret->sref);
+         
+         /*
+         ** Fixed for 2.2c: the alias state of ptr + int is dependent,
+         ** since is points to storage that should not be deallocated
+         ** through this pointer.
+         */
+         
+         if (sRef_isOnly (ret->sref) 
+             || sRef_isFresh (ret->sref)) 
            {
-             if (context_msgPointerArith ())
-               {
-                 voptgenerror 
-                   (FLG_POINTERARITH,
-                    message ("Pointer arithmetic (%t, %t): %s", 
-                             te1, te2, exprNode_unparse (ret)),
-                    e1->loc);
-               }
-
-             if (sRef_possiblyNull (e1->sref)
-                 && !usymtab_isGuarded (e1->sref))
-               {
-                 voptgenerror
-                   (FLG_NULLPOINTERARITH,
-                    message ("Pointer arithmetic involving possibly "
-                             "null pointer %s: %s", 
-                             exprNode_unparse (e2), 
-                             exprNode_unparse (ret)),
-                    e2->loc);
-               }
-
-             ret->sref = sRef_copy (e2->sref);
-
-             /* start modifications */
-             /* added by Seejo on 4/16/2000 */
-             
-             /* Arithmetic operations on pointers wil modify the size/len/null terminated 
-                status */
-             
-             if ((sRef_isPossiblyNullTerminated (e2->sref)) || (sRef_isNullTerminated(e2->sref))) {
+             sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
+           }
+         
+         tret = e1->typ;
+       }
+      else if ((!ctype_isRealPointer(tr1) && ctype_isRealInt (tr1)) 
+              && (ctype_isRealPointer (tr2) && !exprNode_isNullValue (e2)))
+       {
+         if (context_msgPointerArith ())
+           {
+             voptgenerror 
+               (FLG_POINTERARITH,
+                message ("Pointer arithmetic (%t, %t): %s", 
+                         te1, te2, exprNode_unparse (ret)),
+                e1->loc);
+           }
+         
+         if (sRef_possiblyNull (e1->sref)
+             && !usymtab_isGuarded (e1->sref))
+           {
+             voptgenerror
+               (FLG_NULLPOINTERARITH,
+                message ("Pointer arithmetic involving possibly "
+                         "null pointer %s: %s", 
+                         exprNode_unparse (e2), 
+                         exprNode_unparse (ret)),
+                e2->loc);
+           }
+         
+         ret->sref = sRef_copy (e2->sref);
+         
+         /* start modifications */
+         /* added by Seejo on 4/16/2000 */
+         
+         /* Arithmetic operations on pointers wil modify the size/len/null terminated 
+            status */
+         
+         if ((sRef_isPossiblyNullTerminated (e2->sref)) || (sRef_isNullTerminated(e2->sref))) {
+           if (multiVal_isDefined (e1->val)) 
+             {
                int val = (int) multiVal_forceInt (e1->val);
                
                /* Operator : + or += */
@@ -5563,375 +5632,387 @@ exprNode_makeOp (/*@keep@*/ exprNode e1, /*@keep@*/ exprNode e2,
                  }
                }
              }
-             /* end modifications */
-             
-             sRef_setNullError (ret->sref);
-             
-             /*
-             ** Fixed for 2.2c: the alias state of ptr + int is dependent,
-             ** since is points to storage that should not be deallocated
-             ** through this pointer.
-             */
-             
-             if (sRef_isOnly (ret->sref) 
-                 || sRef_isFresh (ret->sref)) {
-               sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
-             }
-             
-             tret = e2->typ;
-             ret->sref = e2->sref;
-           }
-         else
-           {
-             tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
-           }
-         
-         break;
+         }
 
-       case LEFT_ASSIGN:   
-       case RIGHT_ASSIGN:
-       case LEFT_OP:
-       case RIGHT_OP:
-       case TAMPERSAND:    /* bitwise & */
-       case AND_ASSIGN:       
-       case TCIRC:         /* ^ (XOR) */
-       case TBAR:
-       case XOR_ASSIGN:
-       case OR_ASSIGN:
+         /* end modifications */
+         
+         sRef_setNullError (ret->sref);
+         
+         /*
+         ** Fixed for 2.2c: the alias state of ptr + int is dependent,
+         ** since is points to storage that should not be deallocated
+         ** through this pointer.
+         */
+         
+         if (sRef_isOnly (ret->sref) 
+             || sRef_isFresh (ret->sref)) {
+           sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
+         }
+         
+         tret = e2->typ;
+         ret->sref = e2->sref;
+       }
+      else
+       {
+         tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
+       }
+      
+      break;
+      
+    case LEFT_ASSIGN:   
+    case RIGHT_ASSIGN:
+    case LEFT_OP:
+    case RIGHT_OP:
+    case TAMPERSAND:    /* bitwise & */
+    case AND_ASSIGN:       
+    case TCIRC:         /* ^ (XOR) */
+    case TBAR:
+    case XOR_ASSIGN:
+    case OR_ASSIGN:
+      {
+       bool reported = FALSE;
+       
+       /*
+       ** Shift Operator 
+       */
+       
+       if (opid == LEFT_OP || opid == LEFT_ASSIGN
+           || opid == RIGHT_OP || opid == RIGHT_ASSIGN) 
          {
-           bool reported = FALSE;
+           /*
+           ** evans 2002-01-01: fixed this to follow ISO 6.5.7.
+           */
+           
+           if (!ctype_isUnsigned (tr2)
+               && !exprNode_isNonNegative (e2))
+             {
+               reported = optgenerror 
+                 (FLG_SHIFTNEGATIVE,
+                  message ("Right operand of %s may be negative (%t): %s",
+                           lltok_unparse (op), te2,
+                           exprNode_unparse (ret)),
+                  e2->loc);
+             }
+           
+           if (!ctype_isUnsigned (tr1)
+               && !exprNode_isNonNegative (e1))
+             {
+               reported = optgenerror 
+                 (FLG_SHIFTIMPLEMENTATION,
+                  message ("Left operand of %s may be negative (%t): %s",
+                           lltok_unparse (op), te1,
+                           exprNode_unparse (ret)),
+                  e1->loc);
+             }
            
            /*
-           ** Shift Operator 
+           ** Should check size of right operand also...
            */
-
-           if (opid == LEFT_OP || opid == LEFT_ASSIGN
-               || opid == RIGHT_OP || opid == RIGHT_ASSIGN) 
+           
+         }
+       else
+         {
+           if (!ctype_isUnsigned (tr1)) 
              {
-               /*
-               ** evans 2002-01-01: fixed this to follow ISO 6.5.7.
-               */
-               
-               if (!ctype_isUnsigned (tr2)
-                   && !exprNode_isNonNegative (e2))
-                 {
-                   reported = optgenerror 
-                     (FLG_SHIFTNEGATIVE,
-                      message ("Right operand of %s may be negative (%t): %s",
-                               lltok_unparse (op), te2,
-                               exprNode_unparse (ret)),
-                      e2->loc);
-                 }
-               
-               if (!ctype_isUnsigned (tr1)
-                   && !exprNode_isNonNegative (e1))
-                 {
-                   reported = optgenerror 
-                     (FLG_SHIFTIMPLEMENTATION,
-                      message ("Left operand of %s may be negative (%t): %s",
-                               lltok_unparse (op), te1,
-                               exprNode_unparse (ret)),
-                      e1->loc);
+               if (exprNode_isNonNegative (e1)) {
+                 ;
+               } else {
+                 reported = optgenerror 
+                   (FLG_BITWISEOPS,
+                    message ("Left operand of %s is not unsigned value (%t): %s",
+                             lltok_unparse (op), te1,
+                             exprNode_unparse (ret)),
+                    e1->loc);
+                 
+                 if (reported) {
+                   te1 = ctype_uint;
                  }
-               
-               /*
-               ** Should check size of right operand also...
-               */
-               
+               }
              }
-           else
+           else 
              {
-               if (!ctype_isUnsigned (tr1)) 
+               if (!ctype_isUnsigned (tr2)) 
                  {
-                   if (exprNode_isNonNegative (e1)) {
-                     ;
-                   } else {
+                   if (!exprNode_isNonNegative (e2)) {
                      reported = optgenerror 
                        (FLG_BITWISEOPS,
-                        message ("Left operand of %s is not unsigned value (%t): %s",
-                                 lltok_unparse (op), te1,
+                        message ("Right operand of %s is not unsigned value (%t): %s",
+                                 lltok_unparse (op), te2,
                                  exprNode_unparse (ret)),
-                        e1->loc);
-                     
-                     if (reported) {
-                       te1 = ctype_uint;
-                     }
+                        e2->loc);
                    }
                  }
-               else 
-                 {
-                   if (!ctype_isUnsigned (tr2)) 
-                     {
-                       if (!exprNode_isNonNegative (e2)) {
-                         reported = optgenerror 
-                           (FLG_BITWISEOPS,
-                            message ("Right operand of %s is not unsigned value (%t): %s",
-                                     lltok_unparse (op), te2,
-                                     exprNode_unparse (ret)),
-                            e2->loc);
-                       }
-                     }
-                 }
              }
-
-           if (!reported) 
-             {
-               if (!checkIntegral (e1, e2, ret, op)) {
-                 te1 = ctype_unknown;
-               }
-             }
-           
-           DPRINTF (("Set: %s", ctype_unparse (te1)));     
-
-           /*
-           ** tret is the widest type of te1 and te2 
-           */
-
-           tret = ctype_widest (te1, te2);
-           break;
          }
-       case MOD_ASSIGN:
-       case TPERCENT:          
-         if (checkIntegral (e1, e2, ret, op)) {
-           tret = te1;
-         } else {
-           tret = ctype_unknown;
+       
+       if (!reported) 
+         {
+           if (!checkIntegral (e1, e2, ret, op)) {
+             te1 = ctype_unknown;
+           }
          }
-         break;
-       case EQ_OP: 
-       case NE_OP:
-       case TLT:               /* comparisons                           */
-       case TGT:               /*    numeric, numeric -> bool           */
-
-         DPRINTF (("Here we go: %s / %s",
-                   ctype_unparse (tr1), ctype_unparse (tr2)));
-
-         if ((ctype_isReal (tr1) && !ctype_isInt (tr1))
-             || (ctype_isReal (tr2) && !ctype_isInt (tr2)))
+       
+       DPRINTF (("Set: %s", ctype_unparse (te1)));         
+       
+       /*
+       ** tret is the widest type of te1 and te2 
+       */
+       
+       tret = ctype_widest (te1, te2);
+       break;
+      }
+    case MOD_ASSIGN:
+    case TPERCENT:             
+      if (checkIntegral (e1, e2, ret, op)) {
+       tret = te1;
+      } else {
+       tret = ctype_unknown;
+      }
+      break;
+    case EQ_OP: 
+    case NE_OP:
+    case TLT:          /* comparisons                           */
+    case TGT:          /*    numeric, numeric -> bool           */
+      
+      DPRINTF (("Here we go: %s / %s",
+               ctype_unparse (tr1), ctype_unparse (tr2)));
+      
+      if ((ctype_isReal (tr1) && !ctype_isInt (tr1))
+         || (ctype_isReal (tr2) && !ctype_isInt (tr2)))
+       {
+         ctype rtype = tr1;
+         bool fepsilon = FALSE;
+         
+         if (!ctype_isReal (rtype) || ctype_isInt (rtype))
            {
-             ctype rtype = tr1;
-             bool fepsilon = FALSE;
-
-             if (!ctype_isReal (rtype) || ctype_isInt (rtype))
-               {
-                 rtype = tr2;
-               }
+             rtype = tr2;
+           }
+         
+         if (opid == TLT || opid == TGT)
+           {
+             uentry ue1 = exprNode_getUentry (e1);
+             uentry ue2 = exprNode_getUentry (e2);
              
-             if (opid == TLT || opid == TGT)
+             /*
+             ** FLT_EPSILON, etc. really is a variable, not
+             ** a constant.
+             */
+             
+             if (uentry_isVariable (ue1))
                {
-                 uentry ue1 = exprNode_getUentry (e1);
-                 uentry ue2 = exprNode_getUentry (e2);
-
-                 /*
-                 ** FLT_EPSILON, etc. really is a variable, not
-                 ** a constant.
-                 */
-
-                 if (uentry_isVariable (ue1))
+                 cstring uname = uentry_rawName (ue1);
+                 
+                 if (cstring_equalLit (uname, "FLT_EPSILON")
+                     || cstring_equalLit (uname, "DBL_EPSILON")
+                     || cstring_equalLit (uname, "LDBL_EPSILON"))
                    {
-                     cstring uname = uentry_rawName (ue1);
-
-                     if (cstring_equalLit (uname, "FLT_EPSILON")
-                         || cstring_equalLit (uname, "DBL_EPSILON")
-                         || cstring_equalLit (uname, "LDBL_EPSILON"))
-                       {
-                         fepsilon = TRUE;
-                       }
+                     fepsilon = TRUE;
                    }
-
-                 if (uentry_isVariable (ue2))
+               }
+             
+             if (uentry_isVariable (ue2))
+               {
+                 cstring uname = uentry_rawName (ue2);
+                 
+                 if (cstring_equalLit (uname, "FLT_EPSILON")
+                     || cstring_equalLit (uname, "DBL_EPSILON")
+                     || cstring_equalLit (uname, "LDBL_EPSILON"))
                    {
-                     cstring uname = uentry_rawName (ue2);
-
-                     if (cstring_equalLit (uname, "FLT_EPSILON")
-                         || cstring_equalLit (uname, "DBL_EPSILON")
-                         || cstring_equalLit (uname, "LDBL_EPSILON"))
-                       {
-                         fepsilon = TRUE;
-                       }
+                     fepsilon = TRUE;
                    }
                }
-
-             if (fepsilon)
+           }
+         
+         if (fepsilon)
+           {
+             ; /* Don't complain. */
+           }
+         else
+           {
+             if (opid == EQ_OP || opid == NE_OP) 
                {
-                 ; /* Don't complain. */
+                 voptgenerror
+                   (FLG_REALCOMPARE,
+                    message ("Dangerous equality comparison involving %s types: %s",
+                             ctype_unparse (rtype),
+                             exprNode_unparse (ret)),
+                    ret->loc);
                }
              else
                {
                  voptgenerror
-                   (FLG_REALCOMPARE,
-                    message ("Dangerous comparison involving %s types: %s",
+                   (FLG_REALRELATECOMPARE,
+                    message ("Possibly dangerous relational comparison involving %s types: %s",
                              ctype_unparse (rtype),
                              exprNode_unparse (ret)),
                     ret->loc);
                }
            }
-         /*@fallthrough@*/
-       case LE_OP:
-       case GE_OP:
-
-         /*
-         ** Types should match.
-         */
-
-         DPRINTF (("Match types: %s / %s", exprNode_unparse (e1),
-                   exprNode_unparse (e2)));
-
-         if (!exprNode_matchTypes (e1, e2))
+       }
+      /*@fallthrough@*/
+    case LE_OP:
+    case GE_OP:
+      
+      /*
+      ** Types should match.
+      */
+      
+      DPRINTF (("Match types: %s / %s", exprNode_unparse (e1),
+               exprNode_unparse (e2)));
+      
+      if (!exprNode_matchTypes (e1, e2))
+       {
+         hasError = gentypeerror 
+           (te1, e1, te2, e2,
+            message ("Operands of %s have incompatible types (%t, %t): %s",
+                     lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
+            e1->loc);
+         
+       }
+      
+      if (hasError 
+         || (ctype_isForceRealNumeric (&tr1)
+             && ctype_isForceRealNumeric (&tr2)) ||
+         (ctype_isRealPointer (tr1) && ctype_isRealPointer (tr2)))
+       {
+         ; /* okay */
+       }
+      else
+       {
+         if ((ctype_isRealNumeric (tr1) && ctype_isRealPointer (tr2)) ||
+             (ctype_isRealPointer (tr1) && ctype_isRealNumeric (tr2)))
            {
-             hasError = gentypeerror 
-               (te1, e1, te2, e2,
-                message ("Operands of %s have incompatible types (%t, %t): %s",
-                         lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
+             voptgenerror 
+               (FLG_PTRNUMCOMPARE,
+                message ("Comparison of pointer and numeric (%t, %t): %s",
+                         te1, te2, exprNode_unparse (ret)),
                 e1->loc);
-             
-           }
-
-         if (hasError 
-             || (ctype_isForceRealNumeric (&tr1)
-                 && ctype_isForceRealNumeric (&tr2)) ||
-             (ctype_isRealPointer (tr1) && ctype_isRealPointer (tr2)))
-           {
-             ; /* okay */
            }
          else
            {
-             if ((ctype_isRealNumeric (tr1) && ctype_isRealPointer (tr2)) ||
-                 (ctype_isRealPointer (tr1) && ctype_isRealNumeric (tr2)))
-               {
-                 voptgenerror 
-                   (FLG_PTRNUMCOMPARE,
-                    message ("Comparison of pointer and numeric (%t, %t): %s",
-                             te1, te2, exprNode_unparse (ret)),
-                    e1->loc);
-               }
-             else
-               {
-                 (void) checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
-               }
-             tret = ctype_bool;
+             (void) checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
            }
-
-         /* certain comparisons on unsigned's and zero look suspicious */
-
-         if (opid == TLT || opid == LE_OP || opid == GE_OP)
+         tret = ctype_bool;
+       }
+      
+      /* certain comparisons on unsigned's and zero look suspicious */
+      
+      if (opid == TLT || opid == LE_OP || opid == GE_OP)
+       {
+         if ((ctype_isUnsigned (tr1) && exprNode_isZero (e2))
+             || (ctype_isUnsigned (tr2) && exprNode_isZero (e1)))
            {
-             if ((ctype_isUnsigned (tr1) && exprNode_isZero (e2))
-                 || (ctype_isUnsigned (tr2) && exprNode_isZero (e1)))
-               {
-                 voptgenerror 
-                   (FLG_UNSIGNEDCOMPARE,
-                    message ("Comparison of unsigned value involving zero: %s",
-                             exprNode_unparse (ret)),
-                    e1->loc);
-               }
+             voptgenerror 
+               (FLG_UNSIGNEDCOMPARE,
+                message ("Comparison of unsigned value involving zero: %s",
+                         exprNode_unparse (ret)),
+                e1->loc);
            }
-
-         /* EQ_OP should NOT be used with booleans (unless one is FALSE) */
+       }
+      
+      /* EQ_OP should NOT be used with booleans (unless one is FALSE) */
+      
+      if ((opid == EQ_OP || opid == NE_OP) && 
+         ctype_isDirectBool (tr1) && ctype_isDirectBool (tr2))
+       {
+         /*
+         ** is one a variable?
+         */
          
-         if ((opid == EQ_OP || opid == NE_OP) && 
-             ctype_isDirectBool (tr1) && ctype_isDirectBool (tr2))
+         if (uentry_isVariable (exprNode_getUentry (e1))
+             || uentry_isVariable (exprNode_getUentry (e2)))
            {
              /*
-             ** is one a variable?
+             ** comparisons with FALSE are okay
              */
-
-             if (uentry_isVariable (exprNode_getUentry (e1))
-                 || uentry_isVariable (exprNode_getUentry (e2)))
+             
+             if (exprNode_isFalseConstant (e1)
+                 || exprNode_isFalseConstant (e2))
                {
-                 /*
-                 ** comparisons with FALSE are okay
-                 */
-
-                 if (exprNode_isFalseConstant (e1)
-                     || exprNode_isFalseConstant (e2))
-                   {
-                     ;
-                   }
-                 else
-                   {
-                     voptgenerror
-                       (FLG_BOOLCOMPARE,
-                        message 
-                        ("Use of %q with %s variables (risks inconsistency because "
-                         "of multiple true values): %s",
-                         cstring_makeLiteral ((opid == EQ_OP) ? "==" : "!="),
-                         context_printBoolName (), exprNode_unparse (ret)),
-                        e1->loc);
-                   }
+                 ;
+               }
+             else
+               {
+                 voptgenerror
+                   (FLG_BOOLCOMPARE,
+                    message 
+                    ("Use of %q with %s variables (risks inconsistency because "
+                     "of multiple true values): %s",
+                     cstring_makeLiteral ((opid == EQ_OP) ? "==" : "!="),
+                     context_printBoolName (), exprNode_unparse (ret)),
+                    e1->loc);
                }
            }
-         break;
-         
-       case AND_OP:            /* bool, bool -> bool */
-       case OR_OP:
-
-         if (ctype_isForceRealBool (&tr1) && ctype_isForceRealBool (&tr2))
-           {
-             ; 
-           }
-         else
+       }
+      break;
+      
+    case AND_OP:               /* bool, bool -> bool */
+    case OR_OP:
+      if (ctype_isForceRealBool (&tr1) && ctype_isForceRealBool (&tr2))
+       {
+         ; 
+       }
+      else
+       {
+         if (context_maybeSet (FLG_BOOLOPS))
            {
-             if (context_maybeSet (FLG_BOOLOPS))
+             if (!ctype_isRealBool (te1) && !ctype_isRealBool (te2))
                {
-                 if (!ctype_isRealBool (te1) && !ctype_isRealBool (te2))
-                   {
-                     if (ctype_sameName (te1, te2))
-                       {
-                         voptgenerror 
-                           (FLG_BOOLOPS,
-                            message ("Operands of %s are non-boolean (%t): %s",
-                                     lltok_unparse (op), te1,
-                                     exprNode_unparse (ret)),
-                            e1->loc);
-                       }
-                     else
-                       {
-                         voptgenerror 
-                           (FLG_BOOLOPS,
-                            message
-                            ("Operands of %s are non-booleans (%t, %t): %s",
-                             lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
-                            e1->loc);
-                       }
-                   }
-                 else if (!ctype_isRealBool (te1))
+                 if (ctype_sameName (te1, te2))
                    {
                      voptgenerror 
                        (FLG_BOOLOPS,
-                        message ("Left operand of %s is non-boolean (%t): %s",
-                                 lltok_unparse (op), te1, exprNode_unparse (ret)),
+                        message ("Operands of %s are non-boolean (%t): %s",
+                                 lltok_unparse (op), te1,
+                                 exprNode_unparse (ret)),
                         e1->loc);
                    }
-                 else if (!ctype_isRealBool (te2))
-                   {
-                     voptgenerror
-                       (FLG_BOOLOPS,
-                        message ("Right operand of %s is non-boolean (%t): %s",
-                                 lltok_unparse (op), te2, exprNode_unparse (ret)),
-                        e2->loc);
-                   }
                  else
                    {
-                     ;
+                     voptgenerror 
+                       (FLG_BOOLOPS,
+                        message
+                        ("Operands of %s are non-booleans (%t, %t): %s",
+                         lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
+                        e1->loc);
                    }
                }
-             tret = ctype_bool;
+             else if (!ctype_isRealBool (te1))
+               {
+                 voptgenerror 
+                   (FLG_BOOLOPS,
+                    message ("Left operand of %s is non-boolean (%t): %s",
+                             lltok_unparse (op), te1, exprNode_unparse (ret)),
+                    e1->loc);
+               }
+             else if (!ctype_isRealBool (te2))
+               {
+                 voptgenerror
+                   (FLG_BOOLOPS,
+                    message ("Right operand of %s is non-boolean (%t): %s",
+                             lltok_unparse (op), te2, exprNode_unparse (ret)),
+                    e2->loc);
+               }
+             else
+               {
+                 ;
+               }
            }
-         break;
-       default: {
-           llfatalbug 
-             (cstring_makeLiteral 
-              ("There has been a problem in the parser. This is believed to result "
-               "from a problem with bison v. 1.25.  Please try rebuidling Splint "
-               "using the pre-compiled grammar files by commenting out the "
-               "BISON= line in the top-level Makefile."));
-         }
+         tret = ctype_bool;
        }
+      break;
+    default: 
+      llfatalbug 
+       (cstring_makeLiteral 
+        ("There has been a problem in the parser. This is believed to result "
+         "from a problem with bison v. 1.25.  Please try rebuidling Splint "
+         "using the pre-compiled grammar files by commenting out the "
+         "BISON= line in the top-level Makefile."));
     }
 
-  DPRINTF (("Return type: %s", ctype_unparse (tret)));
+skiprest:
   ret->typ = tret;
+  DPRINTF (("Return type %s: %s", exprNode_unparse (ret), ctype_unparse (tret)));
 
   exprNode_checkUse (ret, e1->sref, e1->loc);  
   exprNode_mergeUSs (ret, e2);
@@ -6140,7 +6221,23 @@ exprNode_assign (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2, /*@only@*/ llto
                {
                  if (exprNode_matchLiteral (te1, e2))
                    {
-                     ;
+                     DPRINTF (("Literals match: %s / %s", 
+                               ctype_unparse (te1), exprNode_unparse (e2)));
+                     if (ctype_isNumAbstract (te1)) {
+                       if (!context_flagOn (FLG_NUMABSTRACTLIT, e1->loc)) {
+                         (void) llgenhinterror
+                           (FLG_NUMABSTRACT,
+                            message 
+                            ("Assignment of %t literal to numabstract type %t: %s %s %s",
+                             te2, te1,
+                             exprNode_unparse (e1),
+                             lltok_unparse (op), 
+                             exprNode_unparse (e2)),
+                            cstring_makeLiteral 
+                            ("Use +numabstractlit to allow numeric literals to be used as numabstract values"),
+                            e1->loc);
+                       }
+                     }
                    }
                  else
                    {
@@ -6399,8 +6496,8 @@ exprNode_vaArg (/*@only@*/ lltok tok, /*@only@*/ exprNode arg, /*@only@*/ qtype
       */
 
       if (!ctype_isUA (targ) ||
-         (!usymId_equal (ctype_typeId (targ), 
-                        usymtab_getTypeId (cstring_makeLiteralTemp ("va_list")))))
+         (!typeId_equal (ctype_typeId (targ), 
+                         usymtab_getTypeId (cstring_makeLiteralTemp ("va_list")))))
        {
          voptgenerror
            (FLG_TYPE,
@@ -6711,8 +6808,7 @@ exprNode exprNode_concat (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
 
 exprNode exprNode_createTok (/*@only@*/ lltok t)
 {
-  exprNode ret; /*@i23 if on same line, bad things happen...!@*/
-  ret = exprNode_create (ctype_unknown);
+  exprNode ret = exprNode_create (ctype_unknown);
   ret->kind = XPR_TOK;
   ret->edata = exprData_makeTok (t);
   return ret;
@@ -6925,7 +7021,6 @@ exprNode exprNode_if (/*@only@*/ exprNode pred, /*@only@*/ exprNode tclause)
             exprNode_loc (pred));
        }
       
-      /*! exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred); */ /*@i523@*/
       exprNode_checkUse (pred, pred->sref, pred->loc);
       
       if (!exprNode_isError (tclause))
@@ -7054,9 +7149,7 @@ exprNode exprNode_ifelse (/*@only@*/ exprNode pred,
             exprNode_loc (pred));
        }
       
-      /*@i3423 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);*/
       exprNode_checkUse (ret, pred->sref, pred->loc);
-      
       exprNode_mergeCondUSs (ret, tclause, eclause);
     }
 
@@ -8430,37 +8523,6 @@ exprNode_makeInitializationAux (/*@temp@*/ idDecl t)
     {
       uentry ue = usymtab_lookup (idDecl_observeId (t));
       ret = exprNode_createId (ue);
-
-      /*@i723 don't do this...but why? */
-# if 0
-      ct = ctype_realishType (ret->typ);
-
-      DPRINTF (("Type: %s", ctype_unparse (ret->typ)));
-
-      if (ctype_isUnknown (ct)) 
-       {
-         if (uentry_isAnyTag (ue))
-           {
-             voptgenerror
-               (FLG_IMPTYPE,
-                message ("%s used but not previously declared: %s",
-                         uentry_ekindName (ue),
-                         idDecl_getName (t)),
-                g_currentloc);
-             
-           }
-         else
-           {
-             voptgenerror
-               (FLG_IMPTYPE,
-                message ("Variable has unknown (implicitly int) type: %s",
-                         idDecl_getName (t)),
-                g_currentloc);
-           }
-
-         ct = ctype_int;
-       }
-# endif
     }
   else
     {
@@ -8469,9 +8531,6 @@ exprNode_makeInitializationAux (/*@temp@*/ idDecl t)
       DPRINTF (("Unrecognized: %s", idDecl_unparse (t)));
 
       ue = uentry_makeUnrecognized (idDecl_observeId (t), fileloc_copy (g_currentloc));
-      /*!! fileloc_copy (g_currentloc)); */
-      /*@i32!!! should get error without this */
-
       ret = exprNode_fromIdentifierAux (ue);
 
       /*
@@ -8602,7 +8661,7 @@ exprNode exprNode_makeInitialization (/*@only@*/ idDecl t,
          if (multiVal_isDefined (e->val))
            {
              cstring slit = multiVal_forceString (e->val);
-             sRef_setLen (ret->sref, cstring_length (slit) + 1);
+             sRef_setLen (ret->sref, size_toInt (cstring_length (slit) + 1));
            }
 
          if (ctype_isFixedArray (ct))
@@ -9706,7 +9765,7 @@ exprNode_isInitializer (exprNode e)
 }
 
 bool 
-exprNode_isCharLit (exprNode e)
+exprNode_isCharLiteral (exprNode e)
 {
   if (exprNode_isDefined (e))
     {
@@ -9719,7 +9778,7 @@ exprNode_isCharLit (exprNode e)
 }
 
 bool
-exprNode_isNumLit (exprNode e)
+exprNode_isNumLiteral (exprNode e)
 {
   if (exprNode_isDefined (e))
     {
@@ -9760,6 +9819,12 @@ exprNode_matchLiteral (ctype expected, exprNode e)
            {
              long int val = multiVal_forceInt (m);
              
+             if (ctype_isNumAbstract (expected)  
+                 && context_flagOn (FLG_NUMABSTRACTLIT, exprNode_loc (e))) 
+               {
+                 return TRUE;
+               }
+
              if (ctype_isDirectBool (ctype_realishType (expected)))
                {
                  if (val == 0) 
@@ -9847,11 +9912,11 @@ exprNode_matchLiteral (ctype expected, exprNode e)
            }
          else if (multiVal_isChar (m))
            {
-             char val = multiVal_forceChar (m);          
+             /*signed? */ char val = multiVal_forceChar (m);      
              
              if (ctype_isChar (expected))
                {
-                 if (ctype_isUnsigned (expected) && ((int)val) < 0)
+                 if (ctype_isUnsigned (expected) && ((int) val) < 0)
                    {
                      return FALSE;
                    }
@@ -10119,16 +10184,20 @@ exprNode_checkUse (exprNode e, /*@exposed@*/ sRef s, fileloc loc)
                    {
                      lastRef = errorRef;
                      errorRef = s;
+                     DPRINTF (("Setting ERROR: %s", sRef_unparseFull (s)));
                      deadRef = sRef_isDead (errorRef);
                      unuseable = sRef_isUnuseable (errorRef);
                      errorMaybe = FALSE;
                    }
 
+                 /*
                  if (!sRef_isPartial (s))
                    {
                      DPRINTF (("Defining! %s", sRef_unparseFull (s)));
-                     sRef_setDefined (s, fileloc_undefined);
+                     sRef_setDefined (s, loc);
+                     DPRINTF (("Defining! %s", sRef_unparseFull (s)));
                    }
+                 */
                }
 
              s = sRef_getBaseSafe (s);
@@ -10140,6 +10209,7 @@ exprNode_checkUse (exprNode e, /*@exposed@*/ sRef s, fileloc loc)
                  && sRef_isPointer (errorRef))
                {
                  errorRef = lastRef;
+                 DPRINTF (("errorRef: %s", sRef_unparseFull (errorRef)));
                }
              
              if (deadRef)
@@ -10163,7 +10233,7 @@ exprNode_checkUse (exprNode e, /*@exposed@*/ sRef s, fileloc loc)
                    }
                  else
                    {
-                     DPRINTF (("HERE: %s", sRef_unparse (errorRef)));
+                     DPRINTF (("HERE: %s", sRef_unparseFull (errorRef)));
 
                      if (optgenerror
                          (FLG_USERELEASED,
@@ -10200,13 +10270,16 @@ exprNode_checkUse (exprNode e, /*@exposed@*/ sRef s, fileloc loc)
                {
                  DPRINTF (("HERE: %s", sRef_unparseFull (errorRef)));
 
-                 voptgenerror 
-                   (FLG_USEDEF,
-                    message ("%q %q%qused before definition", 
-                             sRef_unparseKindName (errorRef),
-                             sRef_unparseOpt (errorRef),
-                             cstring_makeLiteral (errorMaybe ? "may be " : "")),
-                    loc);
+                 if (optgenerror 
+                     (FLG_USEDEF,
+                      message ("%q %q%qused before definition", 
+                               sRef_unparseKindName (errorRef),
+                               sRef_unparseOpt (errorRef),
+                               cstring_makeLiteral (errorMaybe ? "may be " : "")),
+                      loc))
+                   {
+                     ;
+                   }
 
                  DPRINTF (("Error: %s", sRef_unparseFull (errorRef)));
                }
@@ -10630,30 +10703,70 @@ static ctype
          DPRINTF (("No error: [%s] %s / [%s]  %s",
                    exprNode_unparse (e1), ctype_unparse (tr1),
                    exprNode_unparse (e2), ctype_unparse (tr2)));
+         
+         /*
+         ** evans 2003-06-15: changed this so if either type is a literal,
+         **    the other type is used.
+         **    (Need to look at the ISO C99 rules on this...)
+         */
+
+         if (exprNode_isNumLiteral (e1)) {
+           ret = tr2;
+         } else if (exprNode_isNumLiteral (e2)) {
+           ret = tr1;
+         } else {
+           ret = ctype_biggerType (tr1, tr2);
+         }
        }
       else
        {
-         (void) gentypeerror 
-           (tr1, e1, tr2, e2,
-            message ("Incompatible types for %s (%s, %s): %s %s %s",
-                     lltok_unparse (op),
-                     ctype_unparse (te1),
-                     ctype_unparse (te2),
-                     exprNode_unparse (e1), lltok_unparse (op), 
-                     exprNode_unparse (e2)),
-            e1->loc);
+         if (ctype_isNumAbstract (tr1) 
+             && exprNode_isNumLiteral (e2)
+             && context_flagOn (FLG_NUMABSTRACTLIT, e1->loc))
+           {
+             ret = tr1; /* No error */
+           }
+         else if (ctype_isNumAbstract (tr2)
+                  && exprNode_isNumLiteral (e1)
+                  && context_flagOn (FLG_NUMABSTRACTLIT, e1->loc))
+           {
+             ret = tr2;
+           }
+         else 
+           {
+             if (gentypeerror 
+                 (tr1, e1, tr2, e2,
+                  message ("Incompatible types for %s (%s, %s): %s %s %s",
+                           lltok_unparse (op),
+                           ctype_unparse (te1),
+                           ctype_unparse (te2),
+                           exprNode_unparse (e1), lltok_unparse (op), 
+                           exprNode_unparse (e2)),
+                  e1->loc))
+               {
+                 ret = ctype_unknown;
+               }
+             else 
+               {
+                 ret = ctype_biggerType (tr1, tr2);
+               }
+           }
        }
-      ret = ctype_unknown;
     }
   else
     {
-      if (ctype_isForceRealNumeric (&tr1) && ctype_isForceRealNumeric (&tr2))
+      if (ctype_isNumAbstract (tr1))
+       {
+         ret = tr1;
+       }
+      else if (ctype_isForceRealNumeric (&tr1)
+              && ctype_isForceRealNumeric (&tr2))
        {
          ret = ctype_resolveNumerics (tr1, tr2);
        }
       else if (!context_msgStrictOps ()) 
        {
-                 if (ctype_isPointer (tr1))
+         if (ctype_isPointer (tr1))
            {
              if (ctype_isPointer (tr2) && !exprNode_isNullValue (e2))
                {
@@ -10759,7 +10872,7 @@ static ctype
   return ret;
 }
 
-static void
+static bool
 abstractOpError (ctype tr1, ctype tr2, lltok op, 
                 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2, 
                 fileloc loc1, fileloc loc2)
@@ -10768,26 +10881,60 @@ abstractOpError (ctype tr1, ctype tr2, lltok op,
     {
       if (ctype_match (tr1, tr2))
        {
-         voptgenerror
-           (FLG_ABSTRACT,
-            message ("Operands of %s are abstract type (%t): %s %s %s",
-                     lltok_unparse (op), tr1, 
-                     exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
-            loc1);
+         if (ctype_isRealNumAbstract (tr1)) 
+           {
+             ; /* No warning for numabstract types */
+           } 
+         else 
+           {
+             if (lltok_isEqOp (op) || lltok_isNotEqOp (op))
+               {
+                 return optgenerror
+                   (FLG_ABSTRACTCOMPARE,
+                    message ("Object equality comparison (%s) on objects of abstract type (%t): %s %s %s",
+                             lltok_unparse (op), tr1, 
+                             exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
+                    loc1);
+               }
+             else
+               {
+                 return optgenerror
+                   (FLG_ABSTRACT,
+                    message ("Operands of %s are abstract type (%t): %s %s %s",
+                             lltok_unparse (op), tr1, 
+                             exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
+                    loc1);
+               }
+           }
        }
       else
        {
-         voptgenerror 
-           (FLG_ABSTRACT,
-            message ("Operands of %s are abstract types (%t, %t): %s %s %s",
-                     lltok_unparse (op), tr1, tr2, 
-                     exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
-            loc1);
+         if (ctype_isRealNumAbstract (tr1) && ctype_isRealNumAbstract (tr2))  
+           {
+             return optgenerror 
+               (FLG_NUMABSTRACT,
+                message
+                ("Operands of %s are different numabstract types (%t, %t): %s %s %s",
+                 lltok_unparse (op), tr1, tr2, 
+                 exprNode_unparse (e1), 
+                 lltok_unparse (op), exprNode_unparse (e2)),
+                loc1);
+           }
+         else
+           {
+             return optgenerror 
+               (FLG_ABSTRACT,
+                message ("Operands of %s are abstract types (%t, %t): %s %s %s",
+                         lltok_unparse (op), tr1, tr2, 
+                         exprNode_unparse (e1), lltok_unparse (op), 
+                         exprNode_unparse (e2)),
+                loc1);
+           }
        }
     }
-  else if (ctype_isRealAbstract (tr1))
+  else if (ctype_isRealAbstract (tr1) && !ctype_isRealNumAbstract (tr1))
     {
-      voptgenerror
+      return optgenerror
        (FLG_ABSTRACT,
         message ("Left operand of %s is abstract type (%t): %s %s %s",
                  lltok_unparse (op), tr1, 
@@ -10796,9 +10943,9 @@ abstractOpError (ctype tr1, ctype tr2, lltok op,
     }
   else 
     {
-      if (ctype_isRealAbstract (tr2))
+      if (ctype_isRealAbstract (tr2) && !ctype_isRealNumAbstract (tr2))
        {
-         voptgenerror
+         return optgenerror
            (FLG_ABSTRACT,
             message ("Right operand of %s is abstract type (%t): %s %s %s",
                      lltok_unparse (op), tr2, 
@@ -10806,6 +10953,8 @@ abstractOpError (ctype tr1, ctype tr2, lltok op,
             loc2);
        }
     }
+
+  return FALSE;
 }
 
 /*
@@ -10963,6 +11112,7 @@ doAssign (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2, bool isInit)
       ctype ct = sRef_getType (sr);
 
       if (ctype_isAbstract (t2) 
+         && !ctype_isNumAbstract (t2)
          && !(uentry_isMutableDatatype (usymtab_getTypeEntry (ctype_typeId (t2)))))
        {
          /* it is immutable, okay to reference */
@@ -11324,31 +11474,22 @@ static void checkUniqueParams (exprNode fcn,
     } end_exprNodeList_elements;
 }
 
-long exprNode_getLongValue (exprNode e) {
+long exprNode_getLongValue (exprNode e) 
+{
   long value;
-
-  if (exprNode_hasValue (e) 
-      && multiVal_isInt (exprNode_getValue (e)))
+  
+  if (exprNode_hasValue (e) && multiVal_isInt (exprNode_getValue (e)))
     {
       value = multiVal_forceInt (exprNode_getValue (e));
     }
   else
     {
-      /*@!! BADBRANCH;*/
-      value = 0;
+      value = 0; /* Unknown value */
     }
   
   return value;
 }
 
-/*@observer@*/ fileloc exprNode_getfileloc (exprNode p_e)
-{
-  if (exprNode_isDefined (p_e) )
-    return ( p_e->loc );
-  else
-    return fileloc_undefined;
-}
-
 /*@only@*/ fileloc exprNode_getNextSequencePoint (exprNode e)
 {
   /*
@@ -11381,3 +11522,32 @@ bool exprNode_isInitBlock (exprNode e)
 {
   return (exprNode_isDefined(e) && e->kind == XPR_INITBLOCK);
 }
+
+/*drl 3/2/2003 moved this function out of constraint.c */
+exprNode exprNode_copyConstraints (/*@returned@*/ exprNode dst, exprNode src)
+{
+    
+  llassert (exprNode_isDefined (dst) );
+  llassert (exprNode_isDefined (src) ); 
+
+  constraintList_free (dst->ensuresConstraints);
+  constraintList_free (dst->requiresConstraints);
+  constraintList_free (dst->trueEnsuresConstraints);
+  constraintList_free (dst->falseEnsuresConstraints);
+  
+  dst->ensuresConstraints = constraintList_copy (src->ensuresConstraints);
+  dst->requiresConstraints = constraintList_copy (src->requiresConstraints);
+  dst->trueEnsuresConstraints = constraintList_copy (src->trueEnsuresConstraints);
+  dst->falseEnsuresConstraints = constraintList_copy (src->falseEnsuresConstraints);
+  return dst;
+}
+
+void exprNode_revealState (exprNode e)
+{
+  if (exprNode_isDefined (e)) {
+    llmsg (message ("%s: State of %s: %s", fileloc_unparse (exprNode_loc (e)), 
+                   exprNode_unparse (e), sRef_unparseFull (e->sref)));
+  } else {
+    llmsg (message ("%s: Reveal state undefined", fileloc_unparse (g_currentloc)));
+  }
+}
This page took 0.14694 seconds and 4 git commands to generate.