diff options
Diffstat (limited to 'lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp | 76 |
1 files changed, 45 insertions, 31 deletions
diff --git a/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp b/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp index f474857a1bf43..07285d27ed9e1 100644 --- a/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp @@ -21,6 +21,7 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/Support/raw_ostream.h" using namespace clang; @@ -71,7 +72,7 @@ public: private: bool PreVisitProcessArg(CheckerContext &C, SVal V, SourceRange ArgRange, - const Expr *ArgEx, bool IsFirstArgument, + const Expr *ArgEx, int ArgumentNumber, bool CheckUninitFields, const CallEvent &Call, std::unique_ptr<BugType> &BT, const ParmVarDecl *ParamDecl) const; @@ -89,9 +90,10 @@ private: BT.reset(new BuiltinBug(this, desc)); } bool uninitRefOrPointer(CheckerContext &C, const SVal &V, - SourceRange ArgRange, - const Expr *ArgEx, std::unique_ptr<BugType> &BT, - const ParmVarDecl *ParamDecl, const char *BD) const; + SourceRange ArgRange, const Expr *ArgEx, + std::unique_ptr<BugType> &BT, + const ParmVarDecl *ParamDecl, const char *BD, + int ArgumentNumber) const; }; } // end anonymous namespace @@ -111,38 +113,45 @@ void CallAndMessageChecker::emitBadCall(BugType *BT, CheckerContext &C, C.emitReport(std::move(R)); } -static StringRef describeUninitializedArgumentInCall(const CallEvent &Call, - bool IsFirstArgument) { +static void describeUninitializedArgumentInCall(const CallEvent &Call, + int ArgumentNumber, + llvm::raw_svector_ostream &Os) { switch (Call.getKind()) { case CE_ObjCMessage: { const ObjCMethodCall &Msg = cast<ObjCMethodCall>(Call); switch (Msg.getMessageKind()) { case OCM_Message: - return "Argument in message expression is an uninitialized value"; + Os << (ArgumentNumber + 1) << llvm::getOrdinalSuffix(ArgumentNumber + 1) + << " argument in message expression is an uninitialized value"; + return; case OCM_PropertyAccess: assert(Msg.isSetter() && "Getters have no args"); - return "Argument for property setter is an uninitialized value"; + Os << "Argument for property setter is an uninitialized value"; + return; case OCM_Subscript: - if (Msg.isSetter() && IsFirstArgument) - return "Argument for subscript setter is an uninitialized value"; - return "Subscript index is an uninitialized value"; + if (Msg.isSetter() && (ArgumentNumber == 0)) + Os << "Argument for subscript setter is an uninitialized value"; + else + Os << "Subscript index is an uninitialized value"; + return; } llvm_unreachable("Unknown message kind."); } case CE_Block: - return "Block call argument is an uninitialized value"; + Os << (ArgumentNumber + 1) << llvm::getOrdinalSuffix(ArgumentNumber + 1) + << " block call argument is an uninitialized value"; + return; default: - return "Function call argument is an uninitialized value"; + Os << (ArgumentNumber + 1) << llvm::getOrdinalSuffix(ArgumentNumber + 1) + << " function call argument is an uninitialized value"; + return; } } -bool CallAndMessageChecker::uninitRefOrPointer(CheckerContext &C, - const SVal &V, - SourceRange ArgRange, - const Expr *ArgEx, - std::unique_ptr<BugType> &BT, - const ParmVarDecl *ParamDecl, - const char *BD) const { +bool CallAndMessageChecker::uninitRefOrPointer( + CheckerContext &C, const SVal &V, SourceRange ArgRange, const Expr *ArgEx, + std::unique_ptr<BugType> &BT, const ParmVarDecl *ParamDecl, const char *BD, + int ArgumentNumber) const { if (!Filter.Check_CallAndMessageUnInitRefArg) return false; @@ -153,12 +162,15 @@ bool CallAndMessageChecker::uninitRefOrPointer(CheckerContext &C, // If parameter is declared as pointer to const in function declaration, // then check if corresponding argument in function call is // pointing to undefined symbol value (uninitialized memory). - StringRef Message; + SmallString<200> Buf; + llvm::raw_svector_ostream Os(Buf); if (ParamDecl->getType()->isPointerType()) { - Message = "Function call argument is a pointer to uninitialized value"; + Os << (ArgumentNumber + 1) << llvm::getOrdinalSuffix(ArgumentNumber + 1) + << " function call argument is a pointer to uninitialized value"; } else if (ParamDecl->getType()->isReferenceType()) { - Message = "Function call argument is an uninitialized value"; + Os << (ArgumentNumber + 1) << llvm::getOrdinalSuffix(ArgumentNumber + 1) + << " function call argument is an uninitialized value"; } else return false; @@ -171,7 +183,7 @@ bool CallAndMessageChecker::uninitRefOrPointer(CheckerContext &C, if (PSV.isUndef()) { if (ExplodedNode *N = C.generateErrorNode()) { LazyInit_BT(BD, BT); - auto R = llvm::make_unique<BugReport>(*BT, Message, N); + auto R = llvm::make_unique<BugReport>(*BT, Os.str(), N); R->addRange(ArgRange); if (ArgEx) { bugreporter::trackNullOrUndefValue(N, ArgEx, *R); @@ -188,7 +200,7 @@ bool CallAndMessageChecker::PreVisitProcessArg(CheckerContext &C, SVal V, SourceRange ArgRange, const Expr *ArgEx, - bool IsFirstArgument, + int ArgumentNumber, bool CheckUninitFields, const CallEvent &Call, std::unique_ptr<BugType> &BT, @@ -196,17 +208,19 @@ bool CallAndMessageChecker::PreVisitProcessArg(CheckerContext &C, ) const { const char *BD = "Uninitialized argument value"; - if (uninitRefOrPointer(C, V, ArgRange, ArgEx, BT, ParamDecl, BD)) + if (uninitRefOrPointer(C, V, ArgRange, ArgEx, BT, ParamDecl, BD, + ArgumentNumber)) return true; if (V.isUndef()) { if (ExplodedNode *N = C.generateErrorNode()) { LazyInit_BT(BD, BT); - // Generate a report for this bug. - StringRef Desc = - describeUninitializedArgumentInCall(Call, IsFirstArgument); - auto R = llvm::make_unique<BugReport>(*BT, Desc, N); + SmallString<200> Buf; + llvm::raw_svector_ostream Os(Buf); + describeUninitializedArgumentInCall(Call, ArgumentNumber, Os); + auto R = llvm::make_unique<BugReport>(*BT, Os.str(), N); + R->addRange(ArgRange); if (ArgEx) bugreporter::trackNullOrUndefValue(N, ArgEx, *R); @@ -435,7 +449,7 @@ void CallAndMessageChecker::checkPreCall(const CallEvent &Call, if(FD && i < FD->getNumParams()) ParamDecl = FD->getParamDecl(i); if (PreVisitProcessArg(C, Call.getArgSVal(i), Call.getArgSourceRange(i), - Call.getArgExpr(i), /*IsFirstArgument=*/i == 0, + Call.getArgExpr(i), i, checkUninitFields, Call, *BT, ParamDecl)) return; } |