]> andersk Git - splint.git/blobdiff - src/exprChecks.c
Made allocations involving sizeof work correctly (test/malloc.c).
[splint.git] / src / exprChecks.c
index 70a33bee271cda6b65ce8ff245c413b7d63bdbbf..219387b99885217982adfa0e8a15c18611474f43 100644 (file)
@@ -1,6 +1,6 @@
 /*
-** LCLint - annotation-assisted static program checker
-** Copyright (C) 1994-2001 University of Virginia,
+** Splint - annotation-assisted static program checker
+** Copyright (C) 1994-2003 University of Virginia,
 **         Massachusetts Institute of Technology
 **
 ** This program is free software; you can redistribute it and/or modify it
 ** 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 more information: http://lclint.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
 */
 /*
 ** exprChecks.c
 */
 
-# include "lclintMacros.nf"
+# include "splintMacros.nf"
 # include "basic.h"
 # include "cgrammar.h"
 # include "cgrammar_tokens.h"
@@ -52,11 +52,36 @@ static void checkSafeReturnExpr (/*@notnull@*/ exprNode p_e);
 **
 */
 
+static int inCompoundStatementExpression = 0;
+
 void
-exprNode_checkStatement (exprNode e)
+exprChecks_inCompoundStatementExpression (void)
+{
+  inCompoundStatementExpression++;
+}
+
+void
+exprChecks_leaveCompoundStatementExpression (void)
+{
+  inCompoundStatementExpression--;
+  llassert (inCompoundStatementExpression >= 0);
+}
+
+void
+exprChecks_checkStatementEffect (exprNode e)
 {
   bool hasError = FALSE;
 
+  if (inCompoundStatementExpression > 0)
+    {
+      /*
+      ** Okay to have effectless statments in compound statement expression (should check
+      ** it is the last statement, but we don't for now).
+      */
+
+      return;
+    }
+
   if (!exprNode_isError (e))
     {
       exprKind ek = e->kind;
@@ -245,7 +270,7 @@ checkRefGlobParam (sRef base, /*@notnull@*/ exprNode e,
                {
                  uentry arg = uentryList_getN (params, paramno);
                  sRef ref = uentry_getSref (arg);
-
+                 
                  if (uentry_isReturned (arg) 
                      || sRef_isOnly (ref) 
                      || sRef_isExposed (ref)
@@ -385,13 +410,13 @@ exprChecks_checkNullReturn (fileloc loc)
              if (ctype_isUnknown (tr))
                {
                  voptgenerror
-                   (FLG_CONTROL,
+                   (FLG_EMPTYRETURN,
                     cstring_makeLiteral ("Empty return in function declared to implicitly return int"),
                     loc);
                }
              else
                {
-                 voptgenerror (FLG_CONTROL,
+                 voptgenerror (FLG_EMPTYRETURN,
                                message ("Empty return in function declared to return %t", tr),
                                loc);
                }
@@ -409,7 +434,7 @@ exprNode_checkReturn (exprNode e)
        {
          if (context_inMacro ())
            {
-             llerror (FLG_CONTROL,
+             llerror (FLG_MACRORETURN,
                       message ("Macro %s uses return (not functional)",
                                context_inFunctionName ()));
            }
@@ -638,7 +663,7 @@ void exprNode_checkMacroBody (/*@only@*/ exprNode e)
       uentry hdr;
 
       if (!(context_inFunctionLike () || context_inMacroConstant ()
-           || context_inMacroUnknown ()))
+           || context_inUnknownMacro ()))
        {
          llcontbug 
            (message 
@@ -732,7 +757,7 @@ void exprNode_checkMacroBody (/*@only@*/ exprNode e)
                }
            }
        }
-      else if (context_inMacroFunction () || context_inMacroUnknown ())
+      else if (context_inMacroFunction () || context_inUnknownMacro ())
        {
          ctype rettype = context_getRetType ();
 
@@ -822,7 +847,7 @@ void exprNode_checkMacroBody (/*@only@*/ exprNode e)
                case XPR_STRINGLITERAL: case XPR_NUMLIT:
                case XPR_FACCESS: case XPR_OFFSETOF:
 
-                 checkReturnTransfer (e, hdr);
+                 transferChecks_return (e, hdr);
                  break;
 
                  /* these expressions don't */
@@ -913,151 +938,181 @@ void exprNode_checkFunctionBody (exprNode body)
 /*drl modified */
 
 
-void exprNode_checkFunction (/*@unused@*/ uentry ue, /*@only@*/ exprNode fcnBody)
+void exprNode_checkFunction (/*@unused@*/ uentry ue, /*@only@*/ exprNode body)
 {
   constraintList c, t, post;
   constraintList c2, fix;
-  constraintList implicitFcnConstraints;
-
-  /*@owned@*/ exprNode body;
-
- //  return;
-
- //  context_setFlag(FLG_ORCONSTRAINT, TRUE);
   context_enterInnerContext ();
 
-  body = fcnBody;
+  llassert (exprNode_isDefined (body));
+
+  DPRINTF (("Checking body: %s", exprNode_unparse (body)));
+
+  /*
+    if we're not going to be printing any errors for buffer overflows
+    we can skip the checking to improve performance
+    
+    FLG_DEBUGFUNCTIONCONSTRAINT controls wheather we perform the check anyway
+    in order to find potential problems like assert failures and seg faults...
+  */
+
+  if (!(context_getFlag (FLG_DEBUGFUNCTIONCONSTRAINT) 
+       || context_getFlag (FLG_BOUNDSWRITE) 
+       || context_getFlag (FLG_BOUNDSREAD)  
+       || context_getFlag (FLG_LIKELYBOUNDSWRITE) 
+       || context_getFlag (FLG_LIKELYBOUNDSREAD)  
+       || context_getFlag (FLG_CHECKPOST)
+       || context_getFlag (FLG_ALLOCMISMATCH)))
+  {
+    exprNode_free (body);
+    context_exitInnerPlain();    
+    return;
+  }
   
-  exprNode_generateConstraints (body);
-
+  exprNode_generateConstraints (body); /* evans 2002-03-02: this should not be declared to take a
+                                         dependent... fix it! */
   
-  c =   uentry_getFcnPreconditions (ue);
-  DPRINTF(("function constraints\n"));
-  DPRINTF (("\n\n\n\n\n\n\n"));
-
+  c = uentry_getFcnPreconditions (ue);
   
-   if (constraintList_isDefined(c) )
-     {
+  if (constraintList_isDefined (c))
+    {
+      DPRINTF (("Function preconditions are %s", constraintList_unparseDetailed (c)));
+      
+      body->requiresConstraints = 
+       constraintList_reflectChangesFreePre (body->requiresConstraints, c);
+      
+      c2  =  constraintList_copy (c);
+      fix =  constraintList_makeFixedArrayConstraints (body->uses);
+      c2  =  constraintList_reflectChangesFreePre (c2, fix);
 
-       DPRINTF ( (message ("Function preconditions are %s \n\n\n\n\n", constraintList_printDetailed (c) ) ) );
-       
-       body->requiresConstraints = constraintList_reflectChangesFreePre (body->requiresConstraints, c);
-       
-       c2  =  constraintList_copy (c);
-       fix =  constraintList_makeFixedArrayConstraints (body->uses);
-       c2  =  constraintList_reflectChangesFreePre (c2, fix);
-       constraintList_free(fix);
-       if ( context_getFlag (FLG_ORCONSTRAINT) )
-        {
-          t = constraintList_reflectChangesOr (body->requiresConstraints, c2 );
-        }
-       else
-        {
-          t = constraintList_reflectChanges(body->requiresConstraints, c2);
-        }
-   
-       constraintList_free(body->requiresConstraints);
-       DPRINTF ( (message ("The body has the required constraints: %s", constraintList_printDetailed (t) ) ) );
-
-       body->requiresConstraints = t;
-       
-       t = constraintList_mergeEnsures (c, body->ensuresConstraints);
-       constraintList_free(body->ensuresConstraints);
-       
-       body->ensuresConstraints = t;
-       
-       DPRINTF ( (message ("The body has the ensures constraints: %s", constraintList_printDetailed (t) ) ) );
-       constraintList_free(c2);
-     }
-   
-   if (constraintList_isDefined(c) )
-     {
-       DPRINTF((message ("The Function %s has the preconditions %s", uentry_unparse(ue), constraintList_printDetailed(c) ) ) );
-     }
-   else
-     {
-       DPRINTF((message ("The Function %s has no preconditions", uentry_unparse(ue) ) ) );
-     }
+      constraintList_free (fix);
+      
+      if (context_getFlag (FLG_ORCONSTRAINT))
+       {
+         t = constraintList_reflectChangesOr (body->requiresConstraints, c2 );
+       }
+      else
+       {
+         t = constraintList_reflectChanges(body->requiresConstraints, c2);
+       }
+      
+      constraintList_free (body->requiresConstraints);
+      DPRINTF ((message ("The body has the required constraints: %s", constraintList_unparseDetailed (t) ) ) );
+      
+      body->requiresConstraints = t;
+      
+      t = constraintList_mergeEnsures (c, body->ensuresConstraints);
+      constraintList_free(body->ensuresConstraints);
+      
+      body->ensuresConstraints = t;
+     
+      DPRINTF ((message ("The body has the ensures constraints: %s", constraintList_unparseDetailed (t) ) ) );
+      constraintList_free(c2);
+    }
+  
+  if (constraintList_isDefined(c))
+    {
+      DPRINTF ((message ("The Function %s has the preconditions %s", 
+                        uentry_unparse(ue), constraintList_unparseDetailed(c))));
+    }
+  else
+    {
+      DPRINTF((message ("The Function %s has no preconditions", uentry_unparse(ue))));
+    }
+  
+  if (context_getFlag (FLG_IMPBOUNDSCONSTRAINTS))
+    {
+      constraintList implicitFcnConstraints = context_getImplicitFcnConstraints (ue);
+      
+      if (constraintList_isDefined (implicitFcnConstraints))
+       {
+         DPRINTF (("Implicit constraints: %s", constraintList_unparse (implicitFcnConstraints)));
+         
+         body->requiresConstraints = constraintList_reflectChangesFreePre (body->requiresConstraints, 
+                                                                           implicitFcnConstraints);
+         constraintList_free (implicitFcnConstraints);
+       }
+      else
+       {
+         DPRINTF (("No implicit constraints"));
+       }
+    }
+  
+  body->requiresConstraints = constraintList_sort (body->requiresConstraints);
+  
+  constraintList_printError(body->requiresConstraints, g_currentloc);
+  
+  post = uentry_getFcnPostconditions (ue);
+  
+  if (context_getFlag (FLG_CHECKPOST))
+    {
+      if (constraintList_isDefined (post))
+       {
+         constraintList post2;
+         
+         DPRINTF ((message ("The declared function postconditions are %s \n\n\n\n\n", 
+                            constraintList_unparseDetailed (post) ) ) );
+         
+         post = constraintList_reflectChangesFreePre (post, body->ensuresConstraints);
+         
+         post2  =  constraintList_copy (post);
+         fix =  constraintList_makeFixedArrayConstraints (body->uses);
+         post2  =  constraintList_reflectChangesFreePre (post2, fix);
+         constraintList_free(fix);
+         if ( context_getFlag (FLG_ORCONSTRAINT) )
+           {
+             t = constraintList_reflectChangesOr (post2, body->ensuresConstraints);
+           }
+         else
+           {
+             t = constraintList_reflectChanges(post2, body->ensuresConstraints);
+           }
+         
+         constraintList_free(post2);
+         constraintList_free(post);
+         post = t;
 
-   implicitFcnConstraints = getImplicitFcnConstraints();
-   
-   if (constraintList_isDefined(implicitFcnConstraints) )
-     {
-          if (context_getFlag (FLG_IMPLICTCONSTRAINT) )
-             {
-               body->requiresConstraints = constraintList_reflectChangesFreePre (body->requiresConstraints, implicitFcnConstraints );
-             }
-     }
-   
-   constraintList_printError(body->requiresConstraints, g_currentloc);
+         printf("Unresolved post conditions\n");
+         constraintList_printErrorPostConditions(post, g_currentloc);
+       }
+    }
+  
+  if (constraintList_isDefined (post))
+    {
+      constraintList_free (post);
+    }
    
-   post =   uentry_getFcnPostconditions (ue);
+   body->ensuresConstraints = constraintList_sort(body->ensuresConstraints);
 
-   if ( context_getFlag (FLG_CHECKPOST) )
+   if ( context_getFlag (FLG_FUNCTIONPOST) )
      {
-       if (constraintList_isDefined(post) )
-        {
-          
-          constraintList post2;
-          
-          DPRINTF ( (message ("The declared function postconditions are %s \n\n\n\n\n", constraintList_printDetailed (post) ) ) );
-          
-          post = constraintList_reflectChangesFreePre (post, body->ensuresConstraints);
-          
-          post2  =  constraintList_copy (post);
-          fix =  constraintList_makeFixedArrayConstraints (body->uses);
-          post2  =  constraintList_reflectChangesFreePre (post2, fix);
-          constraintList_free(fix);
-          if ( context_getFlag (FLG_ORCONSTRAINT) )
-            {
-              t = constraintList_reflectChangesOr (post2, body->ensuresConstraints);
-            }
-          else
-            {
-              t = constraintList_reflectChanges(post2, body->ensuresConstraints);
-            }
-          
-          constraintList_free(post2);
-          
-          constraintList_free(post);
-          post = t;
-          
-        
-
-       printf("Unresolved post conditions\n");
-       constraintList_printErrorPostConditions(post, g_currentloc);
-        }
+       constraintList_printError(body->ensuresConstraints, g_currentloc);
      }
    
-   if (constraintList_isDefined(post) )
-     constraintList_free(post);
-   
-   
-   constraintList_printError(body->ensuresConstraints, g_currentloc);
-   
-   
-   //   ConPrint (message ("Unable to resolve function constraints:\n%s", constraintList_printDetailed(body->requiresConstraints) ), g_currentloc);
+   /*   ConPrint (message ("Unable to resolve function constraints:\n%s", constraintList_printDetailed(body->requiresConstraints) ), g_currentloc);
 
-   //   ConPrint (message ("LCLint has found function post conditions:\n%s", constraintList_printDetailed(body->ensuresConstraints) ), g_currentloc);
+       ConPrint (message ("Splint has found function post conditions:\n%s", constraintList_printDetailed(body->ensuresConstraints) ), g_currentloc);
   
-     //  printf ("The required constraints are:\n%s", constraintList_printDetailed(body->requiresConstraints) );
-     //   printf ("The ensures constraints are:\n%s", constraintList_printDetailed(body->ensuresConstraints) );
+       printf ("The required constraints are:\n%s", constraintList_printDetailed(body->requiresConstraints) );
+       printf ("The ensures constraints are:\n%s", constraintList_unparseDetailed(body->ensuresConstraints) );
+   */
    
-   if (constraintList_isDefined(c) )
+   if (constraintList_isDefined (c))
      constraintList_free(c);
 
    context_exitInnerPlain();
-
-   /*is it okay not to free this?*/
-  exprNode_free (body);
-  }
+   
+   /* is it okay not to free this? */
+   DPRINTF (("Done checking constraints..."));
+   exprNode_free (body);
+}
 
 void exprChecks_checkEmptyMacroBody (void)
 {
   uentry hdr;
   
   if (!(context_inFunctionLike () || context_inMacroConstant ()
-       || context_inMacroUnknown ()))
+       || context_inUnknownMacro ()))
     {
       llcontbug 
        (message ("exprNode_checkEmptyMacroBody: not in macro function or constant: %q", 
@@ -1493,6 +1548,16 @@ static void checkSafeReturnExpr (/*@notnull@*/ exprNode e)
   ctype tr = ctype_getReturnType (context_currentFunctionType ());
   ctype te = exprNode_getType (e);
 
+  /* evans 2001-08-21: added test to warn about void returns from void functions */
+  if (ctype_isVoid (tr))
+    {
+      (void) gentypeerror
+       (te, e, tr, exprNode_undefined,
+        message ("Return expression from function declared void: %s", exprNode_unparse (e)),
+        e->loc);
+      return;
+    }
+
   if (!ctype_forceMatch (tr, te) && !exprNode_matchLiteral (tr, e))
     {
       (void) gentypeerror
@@ -1512,7 +1577,7 @@ static void checkSafeReturnExpr (/*@notnull@*/ exprNode e)
                sRef_unparseFull (e->sref),
                uentry_unparse (rval)));
 
-      checkReturnTransfer (e, rval);
+      transferChecks_return (e, rval);
 
       DPRINTF (("After return: %s / %s / %s",
                exprNode_unparse (e),
This page took 1.332336 seconds and 4 git commands to generate.