From: Ted Kremenek Date: Fri, 8 Jan 2010 18:54:04 +0000 (+0000) Subject: Fix handling in GRExprEngine of 'default' branch in switch statements X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=48569f9562740ac1f4b175cb17ce3d49035402c4;p=clang Fix handling in GRExprEngine of 'default' branch in switch statements when the default case is winnowed down to be infeasible. When all cases were ruled out (and the analysis state for the default case would be infeasible) we would still consider the default case possible. This fixes PR 5969. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@93017 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp index 3c2512215a..0336ae5ada 100644 --- a/lib/Analysis/GRExprEngine.cpp +++ b/lib/Analysis/GRExprEngine.cpp @@ -1221,7 +1221,8 @@ void GRExprEngine::ProcessSwitch(GRSwitchNodeBuilder& builder) { do { nonloc::ConcreteInt CaseVal(getBasicVals().getValue(V1.Val.getInt())); - DefinedOrUnknownSVal Res = SVator.EvalEQ(DefaultSt, CondV, CaseVal); + DefinedOrUnknownSVal Res = SVator.EvalEQ(DefaultSt ? DefaultSt : state, + CondV, CaseVal); // Now "assume" that the case matches. if (const GRState* stateNew = state->Assume(Res, true)) { @@ -1236,11 +1237,17 @@ void GRExprEngine::ProcessSwitch(GRSwitchNodeBuilder& builder) { // Now "assume" that the case doesn't match. Add this state // to the default state (if it is feasible). - if (const GRState *stateNew = DefaultSt->Assume(Res, false)) { - defaultIsFeasible = true; - DefaultSt = stateNew; + if (DefaultSt) { + if (const GRState *stateNew = DefaultSt->Assume(Res, false)) { + defaultIsFeasible = true; + DefaultSt = stateNew; + } + else { + defaultIsFeasible = false; + DefaultSt = NULL; + } } - + // Concretize the next value in the range. if (V1.Val.getInt() == V2.Val.getInt()) break; diff --git a/test/Analysis/misc-ps-ranges.m b/test/Analysis/misc-ps-ranges.m index 760b4d7433..df7e97c467 100644 --- a/test/Analysis/misc-ps-ranges.m +++ b/test/Analysis/misc-ps-ranges.m @@ -21,3 +21,40 @@ int main(int argc, char* argv[]) { return *p; // no-warning } + +// PR 5969: the comparison of argc < 3 || argc > 4 should constraint the switch +// statement from having the 'default' branch taken. This previously reported a false +// positive with the use of 'v'. + +int pr5969(int argc, char *argv[]) { + + int v; + + if ((argc < 3) || (argc > 4)) return 0; + + switch(argc) { + case 3: + v = 33; + break; + case 4: + v = 44; + break; + } + + return v; // no-warning +} + +int pr5969_positive(int argc, char *argv[]) { + + int v; + + if ((argc < 3) || (argc > 4)) return 0; + + switch(argc) { + case 3: + v = 33; + break; + } + + return v; // expected-warning{{Undefined or garbage value returned to caller}} +}