From: Anna Zaks Date: Thu, 4 Jul 2013 02:38:06 +0000 (+0000) Subject: [analyzer] Make sure that inlined defensive checks work on div by zero. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7f79b78351af03a392ee16d8ec557d47746c33c6;p=clang [analyzer] Make sure that inlined defensive checks work on div by zero. This suppresses a false positive in std::hash_map. Fixes radar://14255587. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@185608 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index fe579a3fbf..ffc8f09dcb 100644 --- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -532,7 +532,8 @@ PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ, // If we have an expression that provided the value, try to track where it // came from. if (InitE) { - if (V.isUndef() || V.getAs()) { + if (V.isUndef() || + V.getAs() || V.getAs()) { if (!IsParam) InitE = InitE->IgnoreParenCasts(); bugreporter::trackNullOrUndefValue(StoreSite, InitE, BR, IsParam, @@ -996,12 +997,15 @@ bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N, BugReporterVisitor *ConstraintTracker = new TrackConstraintBRVisitor(V.castAs(), false); report.addVisitor(ConstraintTracker); + } - // Add visitor, which will suppress inline defensive checks. - if (LVState->isNull(V).isConstrainedTrue() && - EnableNullFPSuppression) { + // Add visitor, which will suppress inline defensive checks. + if (Optional DV = V.getAs()) { + if (!DV->isZeroConstant() && + LVState->isNull(*DV).isConstrainedTrue() && + EnableNullFPSuppression) { BugReporterVisitor *IDCSuppressor = - new SuppressInlineDefensiveChecksVisitor(V.castAs(), + new SuppressInlineDefensiveChecksVisitor(*DV, LVNode); report.addVisitor(IDCSuppressor); } diff --git a/test/Analysis/inlining/false-positive-suppression.c b/test/Analysis/inlining/false-positive-suppression.c index c5c6bb875e..e1c8f67614 100644 --- a/test/Analysis/inlining/false-positive-suppression.c +++ b/test/Analysis/inlining/false-positive-suppression.c @@ -84,6 +84,14 @@ void testMultipleStore(void *p) { #endif } +// Test that div by zero does not get suppressed. This is a policy choice. +int retZero() { + return 0; +} +int triggerDivZero () { + int y = retZero(); + return 5/y; // expected-warning {{Division by zero}} +} // -------------------------- // "Suppression suppression" diff --git a/test/Analysis/inlining/inline-defensive-checks.c b/test/Analysis/inlining/inline-defensive-checks.c index aa7f70030c..4ce783c852 100644 --- a/test/Analysis/inlining/inline-defensive-checks.c +++ b/test/Analysis/inlining/inline-defensive-checks.c @@ -110,3 +110,32 @@ void testConstantOffset(char *value) { cursor++; } } + +// Ensure idc works for integer zero values (ex: suppressed div by zero). +void idcZero(int assume) { + if (assume) + ; +} + +int idcTriggerZeroValue(int m) { + idcZero(m); + return 5/m; // no-warning +} + +int idcTriggerZeroValueThroughCall(int i) { + return 5/i; // no-warning +} +void idcTrackZeroValueThroughCall(int x) { + idcZero(x); + idcTriggerZeroValueThroughCall(x); +} + +int idcTriggerZeroThroughDoubleAssignemnt(int i) { + return 5/i; // no-warning +} +void idcTrackZeroThroughDoubleAssignemnt(int x) { + idcZero(x); + int y = x; + int z = y; + idcTriggerZeroValueThroughCall(z); +}