aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp')
-rw-r--r--lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp28
1 files changed, 18 insertions, 10 deletions
diff --git a/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp b/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
index 273a7a38824a..61d2b87cb0c0 100644
--- a/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
@@ -29,8 +29,9 @@ using namespace ento;
namespace {
class NonNullParamChecker
: public Checker< check::PreCall > {
- mutable OwningPtr<BugType> BTAttrNonNull;
- mutable OwningPtr<BugType> BTNullRefArg;
+ mutable std::unique_ptr<BugType> BTAttrNonNull;
+ mutable std::unique_ptr<BugType> BTNullRefArg;
+
public:
void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
@@ -43,7 +44,7 @@ public:
} // end anonymous namespace
void NonNullParamChecker::checkPreCall(const CallEvent &Call,
- CheckerContext &C) const {
+ CheckerContext &C) const {
const Decl *FD = Call.getDecl();
if (!FD)
return;
@@ -66,6 +67,12 @@ void NonNullParamChecker::checkPreCall(const CallEvent &Call,
}
bool haveAttrNonNull = Att && Att->isNonNull(idx);
+ if (!haveAttrNonNull) {
+ // Check if the parameter is also marked 'nonnull'.
+ ArrayRef<ParmVarDecl*> parms = Call.parameters();
+ if (idx < parms.size())
+ haveAttrNonNull = parms[idx]->hasAttr<NonNullAttr>();
+ }
if (!haveRefTypeParam && !haveAttrNonNull)
continue;
@@ -98,7 +105,9 @@ void NonNullParamChecker::checkPreCall(const CallEvent &Call,
V = *CSV_I;
DV = V.getAs<DefinedSVal>();
assert(++CSV_I == CSV->end());
- if (!DV)
+ // FIXME: Handle (some_union){ some_other_union_val }, which turns into
+ // a LazyCompoundVal inside a CompoundVal.
+ if (!V.getAs<Loc>())
continue;
// Retrieve the corresponding expression.
if (const CompoundLiteralExpr *CE = dyn_cast<CompoundLiteralExpr>(ArgE))
@@ -114,14 +123,14 @@ void NonNullParamChecker::checkPreCall(const CallEvent &Call,
ConstraintManager &CM = C.getConstraintManager();
ProgramStateRef stateNotNull, stateNull;
- llvm::tie(stateNotNull, stateNull) = CM.assumeDual(state, *DV);
+ std::tie(stateNotNull, stateNull) = CM.assumeDual(state, *DV);
if (stateNull && !stateNotNull) {
// Generate an error node. Check for a null node in case
// we cache out.
if (ExplodedNode *errorNode = C.generateSink(stateNull)) {
- BugReport *R = 0;
+ BugReport *R = nullptr;
if (haveAttrNonNull)
R = genReportNullAttrNonNull(errorNode, ArgE);
else if (haveRefTypeParam)
@@ -156,8 +165,7 @@ BugReport *NonNullParamChecker::genReportNullAttrNonNull(
// the BugReport is passed to 'EmitWarning'.
if (!BTAttrNonNull)
BTAttrNonNull.reset(new BugType(
- "Argument with 'nonnull' attribute passed null",
- "API"));
+ this, "Argument with 'nonnull' attribute passed null", "API"));
BugReport *R = new BugReport(*BTAttrNonNull,
"Null pointer passed as an argument to a 'nonnull' parameter",
@@ -171,14 +179,14 @@ BugReport *NonNullParamChecker::genReportNullAttrNonNull(
BugReport *NonNullParamChecker::genReportReferenceToNullPointer(
const ExplodedNode *ErrorNode, const Expr *ArgE) const {
if (!BTNullRefArg)
- BTNullRefArg.reset(new BuiltinBug("Dereference of null pointer"));
+ BTNullRefArg.reset(new BuiltinBug(this, "Dereference of null pointer"));
BugReport *R = new BugReport(*BTNullRefArg,
"Forming reference to null pointer",
ErrorNode);
if (ArgE) {
const Expr *ArgEDeref = bugreporter::getDerefExpr(ArgE);
- if (ArgEDeref == 0)
+ if (!ArgEDeref)
ArgEDeref = ArgE;
bugreporter::trackNullOrUndefValue(ErrorNode,
ArgEDeref,