]> granicus.if.org Git - clang/commitdiff
[analyzer] Simplify logic for ExprEngine::VisitUnaryExprOrTypeTraitExpr to avoid...
authorTed Kremenek <kremenek@apple.com>
Sat, 6 Aug 2011 00:30:00 +0000 (00:30 +0000)
committerTed Kremenek <kremenek@apple.com>
Sat, 6 Aug 2011 00:30:00 +0000 (00:30 +0000)
This exposed bugs in the live variables analysis, and a latent analyzer bug in the SymbolReaper.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@137006 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Analysis/CFG.cpp
lib/Analysis/LiveVariables.cpp
lib/StaticAnalyzer/Core/ExprEngine.cpp

index be6ffee668d2b447a94571f83218b6ee1369c750..1edb328d013e76aad1953a88f44532e45173d09a 100644 (file)
@@ -2204,6 +2204,15 @@ CFGBlock *CFGBuilder::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E,
          VA != 0; VA = FindVA(VA->getElementType().getTypePtr()))
       lastBlock = addStmt(VA->getSizeExpr());
   }
+  else {
+    // For sizeof(x), where 'x' is a VLA, we should include the computation
+    // of the lvalue of 'x'.
+    Expr *subEx = E->getArgumentExpr();
+    if (subEx->getType()->isVariableArrayType()) {
+      assert(subEx->isLValue());
+      lastBlock = addStmt(subEx);
+    }
+  }
 
   return lastBlock;
 }
index c6c091e12959e61fe0023c5319150f7473469e75..71c1917c82f740e4e917cc4f999f8dc001a7da7c 100644 (file)
@@ -146,6 +146,19 @@ public:
 };
 }
 
+static const VariableArrayType *FindVA(QualType Ty) {
+  const Type *ty = Ty.getTypePtr();
+  while (const ArrayType *VT = dyn_cast<ArrayType>(ty)) {
+    if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(VT))
+      if (VAT->getSizeExpr())
+        return VAT;
+    
+    ty = VT->getElementType().getTypePtr();
+  }
+  
+  return 0;
+}
+
 void TransferFunctions::Visit(Stmt *S) {
   if (observer)
     observer->observeStmt(S, currentBlock, val);
@@ -174,6 +187,17 @@ void TransferFunctions::Visit(Stmt *S) {
                         CE->getImplicitObjectArgument()->IgnoreParens());
       break;
     }
+    case Stmt::DeclStmtClass: {
+      const DeclStmt *DS = cast<DeclStmt>(S);
+      if (const VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl())) {
+        for (const VariableArrayType* VA = FindVA(VD->getType());
+             VA != 0; VA = FindVA(VA->getElementType())) {
+          val.liveStmts = LV.SSetFact.add(val.liveStmts,
+                                          VA->getSizeExpr()->IgnoreParens());
+        }
+      }
+      break;
+    }
     // FIXME: These cases eventually shouldn't be needed.
     case Stmt::ExprWithCleanupsClass: {
       S = cast<ExprWithCleanups>(S)->getSubExpr();
@@ -187,6 +211,10 @@ void TransferFunctions::Visit(Stmt *S) {
       S = cast<MaterializeTemporaryExpr>(S)->GetTemporaryExpr();
       break;
     }
+    case Stmt::UnaryExprOrTypeTraitExprClass: {
+      // No need to unconditionally visit subexpressions.
+      return;
+    }
   }
   
   for (Stmt::child_iterator it = S->child_begin(), ei = S->child_end();
@@ -281,16 +309,11 @@ VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *UE)
   if (UE->getKind() != UETT_SizeOf || UE->isArgumentType())
     return;
 
-  const DeclRefExpr *DR =
-    dyn_cast<DeclRefExpr>(UE->getArgumentExpr()->IgnoreParens());
-  
-  if (!DR)
-    return;
-  
-  const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
-
-  if (VD && VD->getType()->isVariableArrayType())
-    val.liveDecls = LV.DSetFact.add(val.liveDecls, VD);
+  const Expr *subEx = UE->getArgumentExpr();
+  if (subEx->getType()->isVariableArrayType()) {
+    assert(subEx->isLValue());
+    val.liveStmts = LV.SSetFact.add(val.liveStmts, subEx->IgnoreParens());
+  }
 }
 
 void TransferFunctions::VisitUnaryOperator(UnaryOperator *UO) {
index 71f6f471fb89a94b7369ca487cef31f0680f34ea..765db99555781af7f57cc8c161de8cfa3f07a5e9 100644 (file)
@@ -2269,25 +2269,20 @@ void ExprEngine::VisitUnaryExprOrTypeTraitExpr(
       // Get the size by getting the extent of the sub-expression.
       // First, visit the sub-expression to find its region.
       const Expr *Arg = Ex->getArgumentExpr();
-      ExplodedNodeSet Tmp;
-      Visit(Arg, Pred, Tmp);
-
-      for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
-        const GRState* state = GetState(*I);
-        const MemRegion *MR = state->getSVal(Arg).getAsRegion();
-
-        // If the subexpression can't be resolved to a region, we don't know
-        // anything about its size. Just leave the state as is and continue.
-        if (!MR) {
-          Dst.Add(*I);
-          continue;
-        }
+      const GRState *state = GetState(Pred);
+      const MemRegion *MR = state->getSVal(Arg).getAsRegion();
 
-        // The result is the extent of the VLA.
-        SVal Extent = cast<SubRegion>(MR)->getExtent(svalBuilder);
-        MakeNode(Dst, Ex, *I, state->BindExpr(Ex, Extent));
+      // If the subexpression can't be resolved to a region, we don't know
+      // anything about its size. Just leave the state as is and continue.
+      if (!MR) {
+        Dst.Add(Pred);
+        return;
       }
 
+      // The result is the extent of the VLA.
+      SVal Extent = cast<SubRegion>(MR)->getExtent(svalBuilder);
+      MakeNode(Dst, Ex, Pred, state->BindExpr(Ex, Extent));
+
       return;
     }
     else if (T->getAs<ObjCObjectType>()) {