diff options
18 files changed, 328 insertions, 218 deletions
diff --git a/clang/include/clang/Analysis/PathSensitive/ConstraintManager.h b/clang/include/clang/Analysis/PathSensitive/ConstraintManager.h index 1e758d8cb87..37a14083ac5 100644 --- a/clang/include/clang/Analysis/PathSensitive/ConstraintManager.h +++ b/clang/include/clang/Analysis/PathSensitive/ConstraintManager.h @@ -30,11 +30,11 @@ class SVal; class ConstraintManager { public: virtual ~ConstraintManager(); - virtual const GRState *Assume(const GRState *state, SVal Cond, + virtual const GRState *Assume(const GRState *state, DefinedSVal Cond, bool Assumption) = 0; - virtual const GRState *AssumeInBound(const GRState *state, SVal Idx, - SVal UpperBound, bool Assumption) = 0; + virtual const GRState *AssumeInBound(const GRState *state, DefinedSVal Idx, + DefinedSVal UpperBound, bool Assumption) = 0; std::pair<const GRState*, const GRState*> AssumeDual(const GRState *state, DefinedSVal Cond) { diff --git a/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h b/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h index bd8f714a639..1e016797284 100644 --- a/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h +++ b/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h @@ -134,7 +134,7 @@ public: /// taking a dereference on a symbolic pointer that MUST be NULL. ErrorNodes ExplicitNullDeref; - /// UnitDeref - Nodes in the ExplodedGraph that result from + /// UndefDeref - Nodes in the ExplodedGraph that result from /// taking a dereference on an undefined value. ErrorNodes UndefDeref; @@ -596,9 +596,8 @@ public: SVal LHS, SVal RHS, QualType T) { return SVator.EvalBinOp(ST, Op, LHS, RHS, T); } - + protected: - void EvalCall(ExplodedNodeSet& Dst, CallExpr* CE, SVal L, ExplodedNode* Pred); void EvalObjCMessageExpr(ExplodedNodeSet& Dst, ObjCMessageExpr* ME, ExplodedNode* Pred) { diff --git a/clang/include/clang/Analysis/PathSensitive/GRState.h b/clang/include/clang/Analysis/PathSensitive/GRState.h index 3924084015c..b9d444540d4 100644 --- a/clang/include/clang/Analysis/PathSensitive/GRState.h +++ b/clang/include/clang/Analysis/PathSensitive/GRState.h @@ -194,9 +194,10 @@ public: // (i.e., (b) could just be set to NULL). // - const GRState *assume(SVal condition, bool assumption) const; + const GRState *Assume(DefinedOrUnknownSVal cond, bool assumption) const; - const GRState *assumeInBound(SVal idx, SVal upperBound, + const GRState *AssumeInBound(DefinedOrUnknownSVal idx, + DefinedOrUnknownSVal upperBound, bool assumption) const; //==---------------------------------------------------------------------==// @@ -570,13 +571,24 @@ inline const VarRegion* GRState::getRegion(const VarDecl *D, return getStateManager().getRegionManager().getVarRegion(D, LC); } -inline const GRState *GRState::assume(SVal Cond, bool Assumption) const { - return getStateManager().ConstraintMgr->Assume(this, Cond, Assumption); +inline const GRState *GRState::Assume(DefinedOrUnknownSVal Cond, + bool Assumption) const { + if (Cond.isUnknown()) + return this; + + return getStateManager().ConstraintMgr->Assume(this, cast<DefinedSVal>(Cond), + Assumption); } -inline const GRState *GRState::assumeInBound(SVal Idx, SVal UpperBound, +inline const GRState *GRState::AssumeInBound(DefinedOrUnknownSVal Idx, + DefinedOrUnknownSVal UpperBound, bool Assumption) const { - return getStateManager().ConstraintMgr->AssumeInBound(this, Idx, UpperBound, Assumption); + if (Idx.isUnknown() || UpperBound.isUnknown()) + return this; + + ConstraintManager &CM = *getStateManager().ConstraintMgr; + return CM.AssumeInBound(this, cast<DefinedSVal>(Idx), + cast<DefinedSVal>(UpperBound), Assumption); } inline const GRState *GRState::bindCompoundLiteral(const CompoundLiteralExpr* CL, diff --git a/clang/include/clang/Analysis/PathSensitive/SVals.h b/clang/include/clang/Analysis/PathSensitive/SVals.h index 608364af5ec..4ba3c739682 100644 --- a/clang/include/clang/Analysis/PathSensitive/SVals.h +++ b/clang/include/clang/Analysis/PathSensitive/SVals.h @@ -152,14 +152,6 @@ public: static inline bool classof(const SVal*) { return true; } }; -class UnknownVal : public SVal { -public: - UnknownVal() : SVal(UnknownKind) {} - - static inline bool classof(const SVal* V) { - return V->getBaseKind() == UnknownKind; - } -}; class UndefinedVal : public SVal { public: @@ -173,10 +165,46 @@ public: void* getData() const { return Data; } }; -class DefinedSVal : public SVal { +class DefinedOrUnknownSVal : public SVal { +private: + // Do not implement. We want calling these methods to be a compiler + // error since they are tautologically false. + bool isUndef() const; + bool isValid() const; + protected: - DefinedSVal(const void* d, bool isLoc, unsigned ValKind) + explicit DefinedOrUnknownSVal(const void* d, bool isLoc, unsigned ValKind) : SVal(d, isLoc, ValKind) {} + + explicit DefinedOrUnknownSVal(BaseKind k, void *D = NULL) + : SVal(k, D) {} + +public: + // Implement isa<T> support. + static inline bool classof(const SVal *V) { + return !V->isUndef(); + } +}; + +class UnknownVal : public DefinedOrUnknownSVal { +public: + UnknownVal() : DefinedOrUnknownSVal(UnknownKind) {} + + static inline bool classof(const SVal *V) { + return V->getBaseKind() == UnknownKind; + } +}; + +class DefinedSVal : public DefinedOrUnknownSVal { +private: + // Do not implement. We want calling these methods to be a compiler + // error since they are tautologically true/false. + bool isUnknown() const; + bool isUnknownOrUndef() const; + bool isValid() const; +protected: + DefinedSVal(const void* d, bool isLoc, unsigned ValKind) + : DefinedOrUnknownSVal(d, isLoc, ValKind) {} public: // Implement isa<T> support. static inline bool classof(const SVal *V) { diff --git a/clang/include/clang/Analysis/PathSensitive/SValuator.h b/clang/include/clang/Analysis/PathSensitive/SValuator.h index b08d7ca6423..729aba78ad5 100644 --- a/clang/include/clang/Analysis/PathSensitive/SValuator.h +++ b/clang/include/clang/Analysis/PathSensitive/SValuator.h @@ -36,16 +36,32 @@ public: SValuator(ValueManager &valMgr) : ValMgr(valMgr) {} virtual ~SValuator() {} - class CastResult : public std::pair<const GRState *, SVal> { + template <typename T> + class GenericCastResult : public std::pair<const GRState *, T> { public: - const GRState *getState() const { return first; } - SVal getSVal() const { return second; } - CastResult(const GRState *s, SVal v) - : std::pair<const GRState*, SVal>(s, v) {} + const GRState *getState() const { return this->first; } + T getSVal() const { return this->second; } + GenericCastResult(const GRState *s, T v) + : std::pair<const GRState*,T>(s, v) {} + }; + + class CastResult : public GenericCastResult<SVal> { + public: + CastResult(const GRState *s, SVal v) : GenericCastResult<SVal>(s, v) {} + }; + + class DefinedOrUnknownCastResult : + public GenericCastResult<DefinedOrUnknownSVal> { + public: + DefinedOrUnknownCastResult(const GRState *s, DefinedOrUnknownSVal v) + : GenericCastResult<DefinedOrUnknownSVal>(s, v) {} }; - CastResult EvalCast(SVal val, const GRState *state, + CastResult EvalCast(SVal V, const GRState *ST, QualType castTy, QualType originalType); + + DefinedOrUnknownCastResult EvalCast(DefinedOrUnknownSVal V, const GRState *ST, + QualType castTy, QualType originalType); virtual SVal EvalMinus(NonLoc val) = 0; @@ -59,9 +75,12 @@ public: virtual SVal EvalBinOpLN(const GRState *state, BinaryOperator::Opcode Op, Loc lhs, NonLoc rhs, QualType resultTy) = 0; - + SVal EvalBinOp(const GRState *ST, BinaryOperator::Opcode Op, SVal L, SVal R, QualType T); + + DefinedOrUnknownSVal EvalEQ(const GRState *ST, DefinedOrUnknownSVal L, + DefinedOrUnknownSVal R); }; SValuator* CreateSimpleSValuator(ValueManager &valMgr); diff --git a/clang/include/clang/Analysis/PathSensitive/ValueManager.h b/clang/include/clang/Analysis/PathSensitive/ValueManager.h index 0d9c5f78116..4dd936bb7d6 100644 --- a/clang/include/clang/Analysis/PathSensitive/ValueManager.h +++ b/clang/include/clang/Analysis/PathSensitive/ValueManager.h @@ -91,23 +91,27 @@ public: } /// makeZeroVal - Construct an SVal representing '0' for the specified type. - SVal makeZeroVal(QualType T); + DefinedOrUnknownSVal makeZeroVal(QualType T); /// getRegionValueSymbolVal - make a unique symbol for value of R. - SVal getRegionValueSymbolVal(const MemRegion *R, QualType T = QualType()); + DefinedOrUnknownSVal getRegionValueSymbolVal(const MemRegion *R, + QualType T = QualType()); - SVal getRegionValueSymbolValOrUnknown(const MemRegion *R, QualType T) { - return SymMgr.canSymbolicate(T) ? getRegionValueSymbolVal(R, T) - : UnknownVal(); + DefinedOrUnknownSVal getRegionValueSymbolValOrUnknown(const MemRegion *R, + QualType T) { + if (SymMgr.canSymbolicate(T)) + return getRegionValueSymbolVal(R, T); + return UnknownVal(); } - SVal getConjuredSymbolVal(const Expr *E, unsigned Count); - SVal getConjuredSymbolVal(const Expr* E, QualType T, unsigned Count); + DefinedOrUnknownSVal getConjuredSymbolVal(const Expr *E, unsigned Count); + DefinedOrUnknownSVal getConjuredSymbolVal(const Expr *E, QualType T, + unsigned Count); - SVal getDerivedRegionValueSymbolVal(SymbolRef parentSymbol, - const TypedRegion *R); + DefinedOrUnknownSVal getDerivedRegionValueSymbolVal(SymbolRef parentSymbol, + const TypedRegion *R); - SVal getFunctionPointer(const FunctionDecl* FD); + DefinedSVal getFunctionPointer(const FunctionDecl *FD); NonLoc makeCompoundVal(QualType T, llvm::ImmutableList<SVal> Vals) { return nonloc::CompoundVal(BasicVals.getCompoundValData(T, Vals)); @@ -144,7 +148,7 @@ public: return nonloc::ConcreteInt(BasicVals.getValue(V, isUnsigned)); } - SVal makeIntVal(uint64_t X, QualType T) { + DefinedSVal makeIntVal(uint64_t X, QualType T) { if (Loc::IsLocType(T)) return loc::ConcreteInt(BasicVals.getValue(X, T)); diff --git a/clang/lib/Analysis/BasicStore.cpp b/clang/lib/Analysis/BasicStore.cpp index 388b2e9144d..017399f4fbd 100644 --- a/clang/lib/Analysis/BasicStore.cpp +++ b/clang/lib/Analysis/BasicStore.cpp @@ -530,9 +530,9 @@ Store BasicStoreManager::getInitialStore(const LocationContext *InitLoc) { // Initialize globals and parameters to symbolic values. // Initialize local variables to undefined. const MemRegion *R = ValMgr.getRegionManager().getVarRegion(VD, InitLoc); - SVal X = R->hasGlobalsOrParametersStorage() - ? ValMgr.getRegionValueSymbolVal(R) - : UndefinedVal(); + SVal X = UndefinedVal(); + if (R->hasGlobalsOrParametersStorage()) + X = ValMgr.getRegionValueSymbolVal(R); St = BindInternal(St, ValMgr.makeLoc(R), X); } diff --git a/clang/lib/Analysis/BugReporter.cpp b/clang/lib/Analysis/BugReporter.cpp index c15161c7088..3a3a51a42c8 100644 --- a/clang/lib/Analysis/BugReporter.cpp +++ b/clang/lib/Analysis/BugReporter.cpp @@ -1259,8 +1259,11 @@ SourceLocation BugReport::getLocation() const { if (EndNode) if (const Stmt* S = GetCurrentOrPreviousStmt(EndNode)) { // For member expressions, return the location of the '.' or '->'. - if (const MemberExpr* ME = dyn_cast<MemberExpr>(S)) + if (const MemberExpr *ME = dyn_cast<MemberExpr>(S)) return ME->getMemberLoc(); + // For binary operators, return the location of the operator. + if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S)) + return B->getOperatorLoc(); return S->getLocStart(); } diff --git a/clang/lib/Analysis/BugReporterVisitors.cpp b/clang/lib/Analysis/BugReporterVisitors.cpp index b76ffb18a61..89c9ca10ec5 100644 --- a/clang/lib/Analysis/BugReporterVisitors.cpp +++ b/clang/lib/Analysis/BugReporterVisitors.cpp @@ -232,11 +232,11 @@ static void registerFindLastStore(BugReporterContext& BRC, const MemRegion *R, } class VISIBILITY_HIDDEN TrackConstraintBRVisitor : public BugReporterVisitor { - SVal Constraint; + DefinedSVal Constraint; const bool Assumption; bool isSatisfied; public: - TrackConstraintBRVisitor(SVal constraint, bool assumption) + TrackConstraintBRVisitor(DefinedSVal constraint, bool assumption) : Constraint(constraint), Assumption(assumption), isSatisfied(false) {} PathDiagnosticPiece* VisitNode(const ExplodedNode *N, @@ -247,14 +247,14 @@ public: // Check if in the previous state it was feasible for this constraint // to *not* be true. - if (PrevN->getState()->assume(Constraint, !Assumption)) { + if (PrevN->getState()->Assume(Constraint, !Assumption)) { isSatisfied = true; // As a sanity check, make sure that the negation of the constraint // was infeasible in the current state. If it is feasible, we somehow // missed the transition point. - if (N->getState()->assume(Constraint, !Assumption)) + if (N->getState()->Assume(Constraint, !Assumption)) return NULL; // We found the transition point for the constraint. We now need to @@ -295,7 +295,8 @@ public: }; } // end anonymous namespace -static void registerTrackConstraint(BugReporterContext& BRC, SVal Constraint, +static void registerTrackConstraint(BugReporterContext& BRC, + DefinedSVal Constraint, bool Assumption) { BRC.addVisitor(new TrackConstraintBRVisitor(Constraint, Assumption)); } diff --git a/clang/lib/Analysis/GRExprEngine.cpp b/clang/lib/Analysis/GRExprEngine.cpp index 986af1023b6..c4ca0ea9c13 100644 --- a/clang/lib/Analysis/GRExprEngine.cpp +++ b/clang/lib/Analysis/GRExprEngine.cpp @@ -214,12 +214,15 @@ const GRState* GRExprEngine::getInitialState(const LocationContext *InitLoc) { if (T->isIntegerType()) if (const MemRegion *R = state->getRegion(PD, InitLoc)) { SVal V = state->getSVal(loc::MemRegionVal(R)); - SVal Constraint = EvalBinOp(state, BinaryOperator::GT, V, - ValMgr.makeZeroVal(T), - getContext().IntTy); - - if (const GRState *newState = state->assume(Constraint, true)) - state = newState; + SVal Constraint_untested = EvalBinOp(state, BinaryOperator::GT, V, + ValMgr.makeZeroVal(T), + getContext().IntTy); + + if (DefinedOrUnknownSVal *Constraint = + dyn_cast<DefinedOrUnknownSVal>(&Constraint_untested)) { + if (const GRState *newState = state->Assume(*Constraint, true)) + state = newState; + } } } } @@ -232,7 +235,7 @@ const GRState* GRExprEngine::getInitialState(const LocationContext *InitLoc) { if (const Loc *LV = dyn_cast<Loc>(&V)) { // Assume that the pointer value in 'self' is non-null. - state = state->assume(*LV, true); + state = state->Assume(*LV, true); assert(state && "'self' cannot be null"); } } @@ -710,37 +713,38 @@ void GRExprEngine::ProcessBranch(Stmt* Condition, Stmt* Term, "Error evaluating branch"); const GRState* PrevState = builder.getState(); - SVal V = PrevState->getSVal(Condition); - - switch (V.getBaseKind()) { - default: - break; + SVal X = PrevState->getSVal(Condition); + DefinedSVal *V = NULL; + + while (true) { + V = dyn_cast<DefinedSVal>(&X); - case SVal::UnknownKind: { - if (Expr *Ex = dyn_cast<Expr>(Condition)) { + if (!V) { + if (X.isUnknown()) { + if (const Expr *Ex = dyn_cast<Expr>(Condition)) { if (Ex->getType()->isIntegerType()) { - // Try to recover some path-sensitivity. Right now casts of symbolic - // integers that promote their values are currently not tracked well. - // If 'Condition' is such an expression, try and recover the - // underlying value and use that instead. - SVal recovered = RecoverCastedSymbol(getStateManager(), - builder.getState(), Condition, - getContext()); - - if (!recovered.isUnknown()) { - V = recovered; - break; + // Try to recover some path-sensitivity. Right now casts of symbolic + // integers that promote their values are currently not tracked well. + // If 'Condition' is such an expression, try and recover the + // underlying value and use that instead. + SVal recovered = RecoverCastedSymbol(getStateManager(), + builder.getState(), Condition, + getContext()); + + if (!recovered.isUnknown()) { + X = recovered; + continue; + } } - } - } + } - builder.generateNode(MarkBranch(PrevState, Term, true), true); - builder.generateNode(MarkBranch(PrevState, Term, false), false); - return; - } + builder.generateNode(MarkBranch(PrevState, Term, true), true); + builder.generateNode(MarkBranch(PrevState, Term, false), false); + return; + } - case SVal::UndefinedKind: { - ExplodedNode* N = builder.generateNode(PrevState, true); + assert(X.isUndef()); + ExplodedNode *N = builder.generateNode(PrevState, true); if (N) { N->markAsSink(); @@ -750,11 +754,13 @@ void GRExprEngine::ProcessBranch(Stmt* Condition, Stmt* Term, builder.markInfeasible(false); return; } + + break; } // Process the true branch. if (builder.isFeasible(true)) { - if (const GRState *state = PrevState->assume(V, true)) + if (const GRState *state = PrevState->Assume(*V, true)) builder.generateNode(MarkBranch(state, Term, true), true); else builder.markInfeasible(true); @@ -762,7 +768,7 @@ void GRExprEngine::ProcessBranch(Stmt* Condition, Stmt* Term, // Process the false branch. if (builder.isFeasible(false)) { - if (const GRState *state = PrevState->assume(V, false)) + if (const GRState *state = PrevState->Assume(*V, false)) builder.generateNode(MarkBranch(state, Term, false), false); else builder.markInfeasible(false); @@ -838,15 +844,16 @@ void GRExprEngine::ProcessSwitch(GRSwitchNodeBuilder& builder) { typedef GRSwitchNodeBuilder::iterator iterator; const GRState* state = builder.getState(); Expr* CondE = builder.getCondition(); - SVal CondV = state->getSVal(CondE); + SVal CondV_untested = state->getSVal(CondE); - if (CondV.isUndef()) { + if (CondV_untested.isUndef()) { ExplodedNode* N = builder.generateDefaultCaseNode(state, true); UndefBranches.insert(N); return; } + DefinedOrUnknownSVal CondV = cast<DefinedOrUnknownSVal>(CondV_untested); - const GRState* DefaultSt = state; + const GRState *DefaultSt = state; bool defaultIsFeasible = false; for (iterator I = builder.begin(), EI = builder.end(); I != EI; ++I) { @@ -881,11 +888,10 @@ void GRExprEngine::ProcessSwitch(GRSwitchNodeBuilder& builder) { do { nonloc::ConcreteInt CaseVal(getBasicVals().getValue(V1.Val.getInt())); - SVal Res = EvalBinOp(DefaultSt, BinaryOperator::EQ, CondV, CaseVal, - getContext().IntTy); - + DefinedOrUnknownSVal Res = SVator.EvalEQ(DefaultSt, CondV, CaseVal); + // Now "assume" that the case matches. - if (const GRState* stateNew = state->assume(Res, true)) { + if (const GRState* stateNew = state->Assume(Res, true)) { builder.generateCaseStmtNode(I, stateNew); // If CondV evaluates to a constant, then we know that this @@ -897,7 +903,7 @@ 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)) { + if (const GRState *stateNew = DefaultSt->Assume(Res, false)) { defaultIsFeasible = true; DefaultSt = stateNew; } @@ -933,20 +939,19 @@ void GRExprEngine::VisitLogicalExpr(BinaryOperator* B, ExplodedNode* Pred, SVal X = state->getSVal(B); assert(X.isUndef()); - Expr* Ex = (Expr*) cast<UndefinedVal>(X).getData(); - + const Expr *Ex = (const Expr*) cast<UndefinedVal>(X).getData(); assert(Ex); if (Ex == B->getRHS()) { - X = state->getSVal(Ex); // Handle undefined values. - if (X.isUndef()) { MakeNode(Dst, B, Pred, state->BindExpr(B, X)); return; } + + DefinedOrUnknownSVal XD = cast<DefinedOrUnknownSVal>(X); // We took the RHS. Because the value of the '&&' or '||' expression must // evaluate to 0 or 1, we must assume the value of the RHS evaluates to 0 @@ -954,11 +959,11 @@ void GRExprEngine::VisitLogicalExpr(BinaryOperator* B, ExplodedNode* Pred, // value later when necessary. We don't have the machinery in place for // this right now, and since most logical expressions are used for branches, // the payoff is not likely to be large. Instead, we do eager evaluation. - if (const GRState *newState = state->assume(X, true)) + if (const GRState *newState = state->Assume(XD, true)) MakeNode(Dst, B, Pred, newState->BindExpr(B, ValMgr.makeIntVal(1U, B->getType()))); - if (const GRState *newState = state->assume(X, false)) + if (const GRState *newState = state->Assume(XD, false)) MakeNode(Dst, B, Pred, newState->BindExpr(B, ValMgr.makeIntVal(0U, B->getType()))); } @@ -979,9 +984,8 @@ void GRExprEngine::VisitLogicalExpr(BinaryOperator* B, ExplodedNode* Pred, void GRExprEngine::VisitDeclRefExpr(DeclRefExpr *Ex, ExplodedNode *Pred, ExplodedNodeSet &Dst, bool asLValue) { - const GRState* state = GetState(Pred); - - const NamedDecl* D = Ex->getDecl(); + const GRState *state = GetState(Pred); + const NamedDecl *D = Ex->getDecl(); if (const VarDecl* VD = dyn_cast<VarDecl>(D)) { @@ -1225,10 +1229,10 @@ ExplodedNode* GRExprEngine::EvalLocation(Stmt* Ex, ExplodedNode* Pred, Loc LV = cast<Loc>(location); // "Assume" that the pointer is not NULL. - const GRState *StNotNull = state->assume(LV, true); + const GRState *StNotNull = state->Assume(LV, true); // "Assume" that the pointer is NULL. - const GRState *StNull = state->assume(LV, false); + const GRState *StNull = state->Assume(LV, false); if (StNull) { // Use the Generic Data Map to mark in the state what lval was null. @@ -1264,9 +1268,9 @@ ExplodedNode* GRExprEngine::EvalLocation(Stmt* Ex, ExplodedNode* Pred, SVal NumElements = getStoreManager().getSizeInElements(StNotNull, ER->getSuperRegion()); - const GRState * StInBound = StNotNull->assumeInBound(Idx, NumElements, + const GRState * StInBound = StNotNull->AssumeInBound(Idx, NumElements, true); - const GRState* StOutBound = StNotNull->assumeInBound(Idx, NumElements, + const GRState* StOutBound = StNotNull->AssumeInBound(Idx, NumElements, false); if (StOutBound) { @@ -1361,21 +1365,26 @@ static bool EvalOSAtomicCompareAndSwap(ExplodedNodeSet& Dst, ExplodedNode *N = *I; const GRState *stateLoad = N->getState(); - SVal theValueVal = stateLoad->getSVal(theValueExpr); - SVal oldValueVal = stateLoad->getSVal(oldValueExpr); + SVal theValueVal_untested = stateLoad->getSVal(theValueExpr); + SVal oldValueVal_untested = stateLoad->getSVal(oldValueExpr); // FIXME: Issue an error. - if (theValueVal.isUndef() || oldValueVal.isUndef()) { + if (theValueVal_untested.isUndef() || oldValueVal_untested.isUndef()) { return false; } + + DefinedOrUnknownSVal theValueVal = + cast<DefinedOrUnknownSVal>(theValueVal_untested); + DefinedOrUnknownSVal oldValueVal = + cast<DefinedOrUnknownSVal>(oldValueVal_untested); SValuator &SVator = Engine.getSValuator(); // Perform the comparison. - SVal Cmp = SVator.EvalBinOp(stateLoad, BinaryOperator::EQ, theValueVal, - oldValueVal, Engine.getContext().IntTy); + DefinedOrUnknownSVal Cmp = SVator.EvalEQ(stateLoad, theValueVal, + oldValueVal); - const GRState *stateEqual = stateLoad->assume(Cmp, true); + const GRState *stateEqual = stateLoad->Assume(Cmp, true); // Were they equal? if (stateEqual) { @@ -1404,7 +1413,7 @@ static bool EvalOSAtomicCompareAndSwap(ExplodedNodeSet& Dst, } // Were they not equal? - if (const GRState *stateNotEqual = stateLoad->assume(Cmp, false)) { + if (const GRState *stateNotEqual = stateLoad->Assume(Cmp, false)) { SVal Res = Engine.getValueManager().makeTruthVal(false, CE->getType()); Engine.MakeNode(Dst, CE, N, stateNotEqual->BindExpr(CE, Res)); } @@ -1687,9 +1696,9 @@ void GRExprEngine::EvalEagerlyAssume(ExplodedNodeSet &Dst, ExplodedNodeSet &Src, const GRState* state = Pred->getState(); SVal V = state->getSVal(Ex); - if (isa<nonloc::SymExprVal>(V)) { + if (nonloc::SymExprVal *SEV = dyn_cast<nonloc::SymExprVal>(&V)) { // First assume that the condition is true. - if (const GRState *stateTrue = state->assume(V, true)) { + if (const GRState *stateTrue = state->Assume(*SEV, true)) { stateTrue = stateTrue->BindExpr(Ex, ValMgr.makeIntVal(1U, Ex->getType())); Dst.Add(Builder->generateNode(PostStmtCustom(Ex, @@ -1698,7 +1707,7 @@ void GRExprEngine::EvalEagerlyAssume(ExplodedNodeSet &Dst, ExplodedNodeSet &Src, } // Next, assume that the condition is false. - if (const GRState *stateFalse = state->assume(V, false)) { + if (const GRState *stateFalse = state->Assume(*SEV, false)) { stateFalse = stateFalse->BindExpr(Ex, ValMgr.makeIntVal(0U, Ex->getType())); Dst.Add(Builder->generateNode(PostStmtCustom(Ex, &EagerlyAssumeTag, @@ -1887,10 +1896,10 @@ void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME, if (Expr* Receiver = ME->getReceiver()) { - SVal L = state->getSVal(Receiver); + SVal L_untested = state->getSVal(Receiver); // Check for undefined control-flow. - if (L.isUndef()) { + if (L_untested.isUndef()) { ExplodedNode* N = Builder->generateNode(ME, state, Pred); if (N) { @@ -1902,10 +1911,11 @@ void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME, } // "Assume" that the receiver is not NULL. - const GRState *StNotNull = state->assume(L, true); + DefinedOrUnknownSVal L = cast<DefinedOrUnknownSVal>(L_untested); + const GRState *StNotNull = state->Assume(L, true); // "Assume" that the receiver is NULL. - const GRState *StNull = state->assume(L, false); + const GRState *StNull = state->Assume(L, false); if (StNull) { QualType RetTy = ME->getType(); @@ -2154,9 +2164,9 @@ void GRExprEngine::VisitDeclStmt(DeclStmt *DS, ExplodedNode *Pred, // FIXME: Handle multi-dimensional VLAs. Expr* SE = VLA->getSizeExpr(); - SVal Size = state->getSVal(SE); + SVal Size_untested = state->getSVal(SE); - if (Size.isUndef()) { + if (Size_untested.isUndef()) { if (ExplodedNode* N = Builder->generateNode(DS, state, Pred)) { N->markAsSink(); ExplicitBadSizedVLA.insert(N); @@ -2164,8 +2174,9 @@ void GRExprEngine::VisitDeclStmt(DeclStmt *DS, ExplodedNode *Pred, continue; } - const GRState* zeroState = state->assume(Size, false); - state = state->assume(Size, true); + DefinedOrUnknownSVal Size = cast<DefinedOrUnknownSVal>(Size_untested); + const GRState *zeroState = state->Assume(Size, false); + state = state->Assume(Size, true); if (zeroState) { if (ExplodedNode* N = Builder->generateNode(DS, zeroState, Pred)) { @@ -2557,13 +2568,14 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred, for (ExplodedNodeSet::iterator I2 = Tmp2.begin(), E2 = Tmp2.end(); I2!=E2; ++I2) { state = GetState(*I2); - SVal V2 = state->getSVal(Ex); + SVal V2_untested = state->getSVal(Ex); // Propagate unknown and undefined values. - if (V2.isUnknownOrUndef()) { - MakeNode(Dst, U, *I2, state->BindExpr(U, V2)); + if (V2_untested.isUnknownOrUndef()) { + MakeNode(Dst, U, *I2, state->BindExpr(U, V2_untested)); continue; - } + } + DefinedSVal V2 = cast<DefinedSVal>(V2_untested); // Handle all other values. BinaryOperator::Opcode Op = U->isIncrementOp() ? BinaryOperator::Add @@ -2583,25 +2595,25 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred, // Conjure a new symbol if necessary to recover precision. if (Result.isUnknown() || !getConstraintManager().canReasonAbout(Result)){ - Result = ValMgr.getConjuredSymbolVal(Ex, - Builder->getCurrentBlockCount()); + DefinedOrUnknownSVal SymVal = + ValMgr.getConjuredSymbolVal(Ex, Builder->getCurrentBlockCount()); + Result = SymVal; // If the value is a location, ++/-- should always preserve // non-nullness. Check if the original value was non-null, and if so // propagate that constraint. if (Loc::IsLocType(U->getType())) { - SVal Constraint = EvalBinOp(state, BinaryOperator::EQ, V2, - ValMgr.makeZeroVal(U->getType()), - getContext().IntTy); + DefinedOrUnknownSVal Constraint = + SVator.EvalEQ(state, V2, ValMgr.makeZeroVal(U->getType())); - if (!state->assume(Constraint, true)) { + if (!state->Assume(Constraint, true)) { // It isn't feasible for the original value to be null. // Propagate this constraint. - Constraint = EvalBinOp(state, BinaryOperator::EQ, Result, - ValMgr.makeZeroVal(U->getType()), - getContext().IntTy); + Constraint = SVator.EvalEQ(state, SymVal, + ValMgr.makeZeroVal(U->getType())); + - state = state->assume(Constraint, false); + state = state->Assume(Constraint, false); assert(state); } } @@ -2759,11 +2771,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, Visit(LHS, Pred, Tmp1); for (ExplodedNodeSet::iterator I1=Tmp1.begin(), E1=Tmp1.end(); I1!=E1; ++I1) { - SVal LeftV = (*I1)->getState()->getSVal(LHS); - - // Process the RHS. - ExplodedNodeSet Tmp2; Visit(RHS, *I1, Tmp2); @@ -2775,14 +2783,12 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, for (ExplodedNodeSet::iterator I2=CheckedSet.begin(), E2=CheckedSet.end(); I2 != E2; ++I2) { - const GRState* state = GetState(*I2); - const GRState* OldSt = state; - + const GRState *state = GetState(*I2); + const GRState *OldSt = state; SVal RightV = state->getSVal(RHS); - BinaryOperator::Opcode Op = B->getOpcode(); + BinaryOperator::Opcode Op = B->getOpcode(); switch (Op) { - case BinaryOperator::Assign: { // EXPERIMENTAL: "Conjured" symbols. @@ -2826,22 +2832,20 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, continue; } - if (Result.isUndef() && !LeftV.isUndef() && !RightV.isUndef()) { + state = state->BindExpr(B, Result); + if (Result.isUndef()) { // The operands were *not* undefined, but the result is undefined. // This is a special node that should be flagged as an error. - - if (ExplodedNode* UndefNode = Builder->generateNode(B, state, *I2)){ + if (ExplodedNode *UndefNode = Builder->generateNode(B, state, *I2)){ UndefNode->markAsSink(); UndefResults.insert(UndefNode); } - continue; } // Otherwise, create a new node. - - MakeNode(Dst, B, *I2, state->BindExpr(B, Result)); + MakeNode(Dst, B, *I2, state); continue; } } @@ -2875,25 +2879,6 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, state = GetState(*I3); SVal V = state->getSVal(LHS); - // Propagate undefined values (left-side). - if (V.isUndef()) { - EvalStore(Dst, B, LHS, *I3, state->BindExpr(B, V), - location, V); - continue; - } - - // Propagate unknown values (left and right-side). - if (RightV.isUnknown() || V.isUnknown()) { - EvalStore(Dst, B, LHS, *I3, state->BindExpr(B, UnknownVal()), - location, UnknownVal()); - continue; - } - - // At this point: - // - // The LHS is not Undef/Unknown. - // The RHS is not Unknown. - // Get the computation type. QualType CTy = cast<CompoundAssignOperator>(B)->getComputationResultType(); @@ -2909,14 +2894,6 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, // Promote LHS. llvm::tie(state, V) = SVator.EvalCast(V, state, CLHSTy, LTy); - // Evaluate operands and promote to result type. - if (RightV.isUndef()) { - // Propagate undefined values (right-side). - EvalStore(Dst, B, LHS, *I3, state->BindExpr(B, RightV), location, - RightV); - continue; - } - // Compute the result of the operation. SVal Result; llvm::tie(state, Result) = SVator.EvalCast(EvalBinOp(state, Op, V, diff --git a/clang/lib/Analysis/GRExprEngineInternalChecks.cpp b/clang/lib/Analysis/GRExprEngineInternalChecks.cpp index ab6874ad60d..fcc2db467fe 100644 --- a/clang/lib/Analysis/GRExprEngineInternalChecks.cpp +++ b/clang/lib/Analysis/GRExprEngineInternalChecks.cpp @@ -126,7 +126,7 @@ public: os << "The receiver in the message expression is 'nil' and results in the" " returned value (of type '" << ME->getType().getAsString() - << "') to be garbage or otherwise undefined."; + << "') to be garbage or otherwise undefined"; BuiltinBugReport *R = new BuiltinBugReport(*this, os.str().c_str(), *I); R->addRange(ME->getReceiver()->getSourceRange()); @@ -161,7 +161,7 @@ public: << ME->getType().getAsString() << "' and of size " << Eng.getContext().getTypeSize(ME->getType()) / 8 - << " bytes) to be garbage or otherwise undefined."; + << " bytes) to be garbage or otherwise undefined"; BuiltinBugReport *R = new BuiltinBugReport(*this, os.str().c_str(), *I); R->addRange(ME->getReceiver()->getSourceRange()); @@ -206,11 +206,66 @@ public: class VISIBILITY_HIDDEN UndefResult : public BuiltinBug { public: - UndefResult(GRExprEngine* eng) : BuiltinBug(eng,"Undefined result", - "Result of operation is undefined.") {} + UndefResult(GRExprEngine* eng) + : BuiltinBug(eng,"Undefined or garbage result", + "Result of operation is garbage or undefined") {} void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) { - Emit(BR, Eng.undef_results_begin(), Eng.undef_results_end()); + for (GRExprEngine::undef_result_iterator I=Eng.undef_results_begin(), + E = Eng.undef_results_end(); I!=E; ++I) { + + ExplodedNode *N = *I; + const Stmt *S = N->getLocationAs<PostStmt>()->getStmt(); + BuiltinBugReport *report = NULL; + + if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S)) { + llvm::SmallString<256> sbuf; + llvm::raw_svector_ostream OS(sbuf); + const GRState *ST = N->getState(); + const Expr *Ex; + + if (ST->getSVal(B->getLHS()).isUndef()) { + Ex = B->getLHS()->IgnoreParenCasts(); + OS << "The left operand of the '"; + } + else { + assert(ST->getSVal(B->getRHS()).isUndef()); + Ex = B->getRHS()->IgnoreParenCasts(); + OS << "The right operand of the '"; + } + + OS << BinaryOperator::getOpcodeStr(B->getOpcode()) + << "' expression is an undefined " + "or otherwise garbage value"; + + // FIXME: Use StringRefs to pass string information. + report = new BuiltinBugReport(*this, OS.str().str().c_str(), N); + report->addRange(Ex->getSourceRange()); + } + else { + report = new BuiltinBugReport(*this, + "Expression evaluates to an uninitialized" + " or undefined value", N); + } + + BR.EmitReport(report); + } + } + + void registerInitialVisitors(BugReporterContext& BRC, + const ExplodedNode* N, + BuiltinBugReport *R) { + + const Stmt *S = N->getLocationAs<StmtPoint>()->getStmt(); + const Stmt *X = S; + + if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S)) { + const GRState *ST = N->getState(); + X = ST->getSVal(B->getLHS()).isUndef() + ? B->getLHS()->IgnoreParenCasts() : B->getRHS()->IgnoreParenCasts(); + } + + registerTrackNullOrUndefValue(BRC, X, N); } }; @@ -245,7 +300,7 @@ public: class VISIBILITY_HIDDEN BadArg : public BuiltinBug { public: BadArg(GRExprEngine* eng=0) : BuiltinBug(eng,"Uninitialized argument", - "Pass-by-value argument in function call is undefined.") {} + "Pass-by-value argument in function call is undefined") {} BadArg(GRExprEngine* eng, const char* d) : BuiltinBug(eng,"Uninitialized argument", d) {} @@ -362,8 +417,8 @@ public: class VISIBILITY_HIDDEN RetUndef : public BuiltinBug { public: - RetUndef(GRExprEngine* eng) : BuiltinBug(eng, "Uninitialized return value", - "Uninitialized or undefined value returned to caller.") {} + RetUndef(GRExprEngine* eng) : BuiltinBug(eng, "Garbage return value", + "Undefined or garbage value returned to caller") {} void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) { Emit(BR, Eng.ret_undef_begin(), Eng.ret_undef_end()); @@ -401,8 +456,9 @@ class VISIBILITY_HIDDEN UndefBranch : public BuiltinBug { public: UndefBranch(GRExprEngine *eng) - : BuiltinBug(eng,"Use of uninitialized value", - "Branch condition evaluates to an uninitialized value.") {} + : BuiltinBug(eng,"Use of garbage value", + "Branch condition evaluates to an undefined or garbage value") + {} void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) { for (GRExprEngine::undef_branch_iterator I=Eng.undef_branches_begin(), diff --git a/clang/lib/Analysis/SValuator.cpp b/clang/lib/Analysis/SValuator.cpp index 383fe45c1d8..0551c7cdbaa 100644 --- a/clang/lib/Analysis/SValuator.cpp +++ b/clang/lib/Analysis/SValuator.cpp @@ -46,6 +46,13 @@ SVal SValuator::EvalBinOp(const GRState *ST, BinaryOperator::Opcode Op, return EvalBinOpNN(Op, cast<NonLoc>(L), cast<NonLoc>(R), T); } +DefinedOrUnknownSVal SValuator::EvalEQ(const GRState *ST, + DefinedOrUnknownSVal L, + DefinedOrUnknownSVal R) { + return cast<DefinedOrUnknownSVal>(EvalBinOp(ST, BinaryOperator::EQ, L, R, + ValMgr.getContext().IntTy)); +} + SValuator::CastResult SValuator::EvalCast(SVal val, const GRState *state, QualType castTy, QualType originalTy){ @@ -146,3 +153,11 @@ DispatchCast: isa<Loc>(val) ? EvalCastL(cast<Loc>(val), castTy) : EvalCastNL(cast<NonLoc>(val), castTy)); } + +SValuator::DefinedOrUnknownCastResult +SValuator::EvalCast(DefinedOrUnknownSVal V, const GRState *ST, + QualType castTy, QualType originalType) { + SValuator::CastResult X = EvalCast((SVal) V, ST, castTy, originalType); + return DefinedOrUnknownCastResult(X.getState(), + cast<DefinedOrUnknownSVal>(X.getSVal())); +} diff --git a/clang/lib/Analysis/SimpleConstraintManager.cpp b/clang/lib/Analysis/SimpleConstraintManager.cpp index db3d68a2c7d..e4ad85aa836 100644 --- a/clang/lib/Analysis/SimpleConstraintManager.cpp +++ b/clang/lib/Analysis/SimpleConstraintManager.cpp @@ -56,11 +56,8 @@ bool SimpleConstraintManager::canReasonAbout(SVal X) const { } const GRState *SimpleConstraintManager::Assume(const GRState *state, - SVal Cond, bool Assumption) { - if (Cond.isUnknown()) { - return state; - } - + DefinedSVal Cond, + bool Assumption) { if (isa<NonLoc>(Cond)) return Assume(state, cast<NonLoc>(Cond), Assumption); else @@ -226,8 +223,8 @@ const GRState *SimpleConstraintManager::AssumeSymInt(const GRState *state, } const GRState *SimpleConstraintManager::AssumeInBound(const GRState *state, - SVal Idx, - SVal UpperBound, + DefinedSVal Idx, + DefinedSVal UpperBound, bool Assumption) { // Only support ConcreteInt for now. diff --git a/clang/lib/Analysis/SimpleConstraintManager.h b/clang/lib/Analysis/SimpleConstraintManager.h index d626dfec8cb..0c58440ac0b 100644 --- a/clang/lib/Analysis/SimpleConstraintManager.h +++ b/clang/lib/Analysis/SimpleConstraintManager.h @@ -30,7 +30,8 @@ public: bool canReasonAbout(SVal X) const; - const GRState *Assume(const GRState *state, SVal Cond, bool Assumption); + const GRState *Assume(const GRState *state, DefinedSVal Cond, + bool Assumption); const GRState *Assume(const GRState *state, Loc Cond, bool Assumption); @@ -39,7 +40,8 @@ public: const GRState *AssumeSymInt(const GRState *state, bool Assumption, const SymIntExpr *SE); - const GRState *AssumeInBound(const GRState *state, SVal Idx, SVal UpperBound, + const GRState *AssumeInBound(const GRState *state, DefinedSVal Idx, + DefinedSVal UpperBound, bool Assumption); protected: diff --git a/clang/lib/Analysis/SimpleSValuator.cpp b/clang/lib/Analysis/SimpleSValuator.cpp index 442845a7c50..6d944da45b0 100644 --- a/clang/lib/Analysis/SimpleSValuator.cpp +++ b/clang/lib/Analysis/SimpleSValuator.cpp @@ -97,8 +97,6 @@ SVal SimpleSValuator::EvalCastL(Loc val, QualType castTy) { // can be introduced by the frontend for corner cases, e.g // casting from va_list* to __builtin_va_list&. // - assert(!val.isUnknownOrUndef()); - if (Loc::IsLocType(castTy) || castTy->isReferenceType()) return val; @@ -202,10 +200,6 @@ static SVal EvalEquality(ValueManager &ValMgr, Loc lhs, Loc rhs, bool isEqual, SVal SimpleSValuator::EvalBinOpNN(BinaryOperator::Opcode op, NonLoc lhs, NonLoc rhs, QualType resultTy) { - - assert(!lhs.isUnknownOrUndef()); - assert(!rhs.isUnknownOrUndef()); - // Handle trivial case where left-side and right-side are the same. if (lhs == rhs) switch (op) { diff --git a/clang/lib/Analysis/ValueManager.cpp b/clang/lib/Analysis/ValueManager.cpp index 9fe16af6c9f..9c3dbdd24e5 100644 --- a/clang/lib/Analysis/ValueManager.cpp +++ b/clang/lib/Analysis/ValueManager.cpp @@ -22,7 +22,7 @@ using namespace llvm; // Utility methods for constructing SVals. //===----------------------------------------------------------------------===// -SVal ValueManager::makeZeroVal(QualType T) { +DefinedOrUnknownSVal ValueManager::makeZeroVal(QualType T) { if (Loc::IsLocType(T)) return makeNull(); @@ -69,7 +69,8 @@ SVal ValueManager::convertToArrayIndex(SVal V) { return SVator->EvalCastNL(cast<NonLoc>(V), ArrayIndexTy); } -SVal ValueManager::getRegionValueSymbolVal(const MemRegion* R, QualType T) { +DefinedOrUnknownSVal ValueManager::getRegionValueSymbolVal(const MemRegion* R, + QualType T) { if (T.isNull()) { const TypedRegion* TR = cast<TypedRegion>(R); @@ -87,7 +88,7 @@ SVal ValueManager::getRegionValueSymbolVal(const MemRegion* R, QualType T) { return nonloc::SymbolVal(sym); } -SVal ValueManager::getConjuredSymbolVal(const Expr *E, unsigned Count) { +DefinedOrUnknownSVal ValueManager::getConjuredSymbolVal(const Expr *E, unsigned Count) { QualType T = E->getType(); if (!SymbolManager::canSymbolicate(T)) @@ -101,9 +102,10 @@ SVal ValueManager::getConjuredSymbolVal(const Expr *E, unsigned Count) { return nonloc::SymbolVal(sym); } -SVal ValueManager::getConjuredSymbolVal(const Expr *E, QualType T, - unsigned Count) { - +DefinedOrUnknownSVal ValueManager::getConjuredSymbolVal(const Expr *E, + QualType T, + unsigned Count) { + if (!SymbolManager::canSymbolicate(T)) return UnknownVal(); @@ -116,8 +118,9 @@ SVal ValueManager::getConjuredSymbolVal(const Expr *E, QualType T, } -SVal ValueManager::getDerivedRegionValueSymbolVal(SymbolRef parentSymbol, - const TypedRegion *R) { +DefinedOrUnknownSVal +ValueManager::getDerivedRegionValueSymbolVal(SymbolRef parentSymbol, + const TypedRegion *R) { QualType T = R->getValueType(R->getContext()); if (!SymbolManager::canSymbolicate(T)) @@ -131,7 +134,7 @@ SVal ValueManager::getDerivedRegionValueSymbolVal(SymbolRef parentSymbol, return nonloc::SymbolVal(sym); } -SVal ValueManager::getFunctionPointer(const FunctionDecl* FD) { +DefinedSVal ValueManager::getFunctionPointer(const FunctionDecl* FD) { CodeTextRegion *R = MemMgr.getCodeTextRegion(FD); return loc::MemRegionVal(R); } diff --git a/clang/test/Analysis/uninit-vals-ps-region.c b/clang/test/Analysis/uninit-vals-ps-region.c index 95928ea5526..d16200743c4 100644 --- a/clang/test/Analysis/uninit-vals-ps-region.c +++ b/clang/test/Analysis/uninit-vals-ps-region.c @@ -25,7 +25,7 @@ void test_uninit_pos() { struct TestUninit v2 = test_uninit_aux(); int z; v1.y = z; - test_unit_aux2(v2.x + v1.y); // expected-warning{{Pass-by-value argument in function call is undefined}} + test_unit_aux2(v2.x + v1.y); // expected-warning{{The right operand of the '+' expression is an undefined or otherwise garbage value}} } void test_uninit_neg() { struct TestUninit v1 = { 0, 0 }; diff --git a/clang/test/Analysis/uninit-vals-ps.c b/clang/test/Analysis/uninit-vals-ps.c index bf19d6b9c0d..ac0e7b2f327 100644 --- a/clang/test/Analysis/uninit-vals-ps.c +++ b/clang/test/Analysis/uninit-vals-ps.c @@ -22,7 +22,7 @@ int f2() { int x; - if (x+1) // expected-warning{{Branch}} + if (x+1) // expected-warning{{The left operand of the '+' expression is an undefined or otherwise garbage value}} return 1; return 2; @@ -31,13 +31,13 @@ int f2() { int f2_b() { int x; - return ((x+1)+2+((x))) + 1 ? 1 : 2; // expected-warning{{Branch}} + return ((1+x)+2+((x))) + 1 ? 1 : 2; // expected-warning{{The right operand of the '+' expression is an undefined or otherwise garbage value}} } int f3(void) { int i; int *p = &i; - if (*p > 0) // expected-warning{{Branch condition evaluates to an uninitialized value}} + if (*p > 0) // expected-warning{{The left operand of the '>' expression is an undefined or otherwise garbage value}} return 0; else return 1; @@ -61,7 +61,7 @@ int f5(void) { int ret_uninit() { int i; int *p = &i; - return *p; // expected-warning{{Uninitialized or undefined value returned to caller.}} + return *p; // expected-warning{{Undefined or garbage value returned to caller}} } // <rdar://problem/6451816> |