diff options
| author | Anna Zaks <ganna@apple.com> | 2013-07-04 02:38:06 +0000 |
|---|---|---|
| committer | Anna Zaks <ganna@apple.com> | 2013-07-04 02:38:06 +0000 |
| commit | 5673b6567ae881cd22280de94a958b45a9bbeffb (patch) | |
| tree | e8e7970fca5620150a12b44949719e4db5d0a47b | |
| parent | 6597b8fd227f09524874f5b475bebb76ff95b275 (diff) | |
| download | bcm5719-llvm-5673b6567ae881cd22280de94a958b45a9bbeffb.tar.gz bcm5719-llvm-5673b6567ae881cd22280de94a958b45a9bbeffb.zip | |
[analyzer] Make sure that inlined defensive checks work on div by zero.
This suppresses a false positive in std::hash_map.
Fixes radar://14255587.
llvm-svn: 185608
3 files changed, 46 insertions, 5 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index fe579a3fbf3..ffc8f09dcb8 100644 --- a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/clang/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<loc::ConcreteInt>()) { + if (V.isUndef() || + V.getAs<loc::ConcreteInt>() || V.getAs<nonloc::ConcreteInt>()) { 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<DefinedSVal>(), 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<DefinedSVal> DV = V.getAs<DefinedSVal>()) { + if (!DV->isZeroConstant() && + LVState->isNull(*DV).isConstrainedTrue() && + EnableNullFPSuppression) { BugReporterVisitor *IDCSuppressor = - new SuppressInlineDefensiveChecksVisitor(V.castAs<DefinedSVal>(), + new SuppressInlineDefensiveChecksVisitor(*DV, LVNode); report.addVisitor(IDCSuppressor); } diff --git a/clang/test/Analysis/inlining/false-positive-suppression.c b/clang/test/Analysis/inlining/false-positive-suppression.c index c5c6bb875ea..e1c8f67614e 100644 --- a/clang/test/Analysis/inlining/false-positive-suppression.c +++ b/clang/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/clang/test/Analysis/inlining/inline-defensive-checks.c b/clang/test/Analysis/inlining/inline-defensive-checks.c index aa7f70030c0..4ce783c852f 100644 --- a/clang/test/Analysis/inlining/inline-defensive-checks.c +++ b/clang/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); +} |

