From cabc3fddae63f5eb3bd44bdecce7a3fbd69421a9 Mon Sep 17 00:00:00 2001 From: Anna Zaks Date: Wed, 3 Apr 2013 19:28:15 +0000 Subject: [PATCH] [analyzer] make peelOffOuterExpr in BugReporterVisitors recursively peel off select Exprs git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178685 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Core/BugReporterVisitors.cpp | 57 ++++++++++--------- .../inlining/false-positive-suppression.c | 25 ++++++++ 2 files changed, 54 insertions(+), 28 deletions(-) diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index 7f71b8e81e..60a7e65254 100644 --- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -789,36 +789,33 @@ static const MemRegion *getLocationRegionIfReference(const Expr *E, return 0; } -static const Expr *peelOffOuterExpr(const Stmt *S, +static const Expr *peelOffOuterExpr(const Expr *Ex, const ExplodedNode *N) { - if (const Expr *Ex = dyn_cast(S)) { - Ex = Ex->IgnoreParenCasts(); - if (const ExprWithCleanups *EWC = dyn_cast(Ex)) - return EWC->getSubExpr(); - if (const OpaqueValueExpr *OVE = dyn_cast(Ex)) - return OVE->getSourceExpr(); + Ex = Ex->IgnoreParenCasts(); + if (const ExprWithCleanups *EWC = dyn_cast(Ex)) + return peelOffOuterExpr(EWC->getSubExpr(), N); + if (const OpaqueValueExpr *OVE = dyn_cast(Ex)) + return peelOffOuterExpr(OVE->getSourceExpr(), N); - // Peel off the ternary operator. - if (const ConditionalOperator *CO = dyn_cast(Ex)) { - const Expr *CondEx = CO->getCond(); + // Peel off the ternary operator. + if (const ConditionalOperator *CO = dyn_cast(Ex)) { + const Expr *CondEx = CO->getCond(); - // Find a node where the value of the condition is known. - do { - ProgramStateRef State = N->getState(); - SVal CondVal = State->getSVal(CondEx, N->getLocationContext()); - ConditionTruthVal CondEvaluated = State->isNull(CondVal); - if (CondEvaluated.isConstrained()) { - if (CondEvaluated.isConstrainedTrue()) - return CO->getFalseExpr(); - else - return CO->getTrueExpr(); - } - N = N->getFirstPred(); - } while (N); - - } + // Find a node where the value of the condition is known. + do { + ProgramStateRef State = N->getState(); + SVal CondVal = State->getSVal(CondEx, N->getLocationContext()); + ConditionTruthVal CondEvaluated = State->isNull(CondVal); + if (CondEvaluated.isConstrained()) { + if (CondEvaluated.isConstrainedTrue()) + return peelOffOuterExpr(CO->getFalseExpr(), N); + else + return peelOffOuterExpr(CO->getTrueExpr(), N); + } + N = N->getFirstPred(); + } while (N); } - return 0; + return Ex; } bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N, @@ -828,8 +825,12 @@ bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N, if (!S || !N) return false; - if (const Expr *Ex = peelOffOuterExpr(S, N)) - S = Ex; + if (const Expr *Ex = dyn_cast(S)) { + Ex = Ex->IgnoreParenCasts(); + const Expr *PeeledEx = peelOffOuterExpr(Ex, N); + if (Ex != PeeledEx) + S = PeeledEx; + } const Expr *Inner = 0; if (const Expr *Ex = dyn_cast(S)) { diff --git a/test/Analysis/inlining/false-positive-suppression.c b/test/Analysis/inlining/false-positive-suppression.c index e12612d8c4..248d854dbc 100644 --- a/test/Analysis/inlining/false-positive-suppression.c +++ b/test/Analysis/inlining/false-positive-suppression.c @@ -240,4 +240,29 @@ int ternaryRetNull(char cond) { #endif } +// Test suppression of nested conditional operators. +int testConditionalOperatorSuppress(int x) { + return *(x ? getNull() : getPtr()); +#ifndef SUPPRESSED + // expected-warning@-2 {{Dereference of null pointer}} +#endif +} +int testNestedConditionalOperatorSuppress(int x) { + return *(x ? (x ? getNull() : getPtr()) : getPtr()); +#ifndef SUPPRESSED + // expected-warning@-2 {{Dereference of null pointer}} +#endif +} +int testConditionalOperator(int x) { + return *(x ? 0 : getPtr()); // expected-warning {{Dereference of null pointer}} +} +int testNestedConditionalOperator(int x) { + return *(x ? (x ? 0 : getPtr()) : getPtr()); // expected-warning {{Dereference of null pointer}} +} + +// False Positve - we are unable to suppress this case because the condition is +// float. +int testConditionalOperatorSuppressFloatCond(float x) { + return *(x ? getNull() : getPtr()); // expected-warning {{Dereference of null pointer}} +}