Files
clang-p2996/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
Artem Dergachev 44820630df [analyzer] NFC: Change evalCall() to provide a CallEvent.
This changes the checker callback signature to use the modern, easy to
use interface. Additionally, this unblocks future work on allowing
checkers to implement evalCall() for calls that don't correspond to any
call-expression or require additional information that's only available
as part of the CallEvent, such as C++ constructors and destructors.

Differential Revision: https://reviews.llvm.org/D62440

llvm-svn: 363893
2019-06-19 23:33:42 +00:00

73 lines
2.5 KiB
C++

// SmartPtrModeling.cpp - Model behavior of C++ smart pointers - C++ ------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines a checker that models various aspects of
// C++ smart pointer behavior.
//
//===----------------------------------------------------------------------===//
#include "Move.h"
#include "clang/AST/ExprCXX.h"
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
using namespace clang;
using namespace ento;
namespace {
class SmartPtrModeling : public Checker<eval::Call> {
bool isNullAfterMoveMethod(const CallEvent &Call) const;
public:
bool evalCall(const CallEvent &Call, CheckerContext &C) const;
};
} // end of anonymous namespace
bool SmartPtrModeling::isNullAfterMoveMethod(const CallEvent &Call) const {
// TODO: Update CallDescription to support anonymous calls?
// TODO: Handle other methods, such as .get() or .release().
// But once we do, we'd need a visitor to explain null dereferences
// that are found via such modeling.
const auto *CD = dyn_cast_or_null<CXXConversionDecl>(Call.getDecl());
return CD && CD->getConversionType()->isBooleanType();
}
bool SmartPtrModeling::evalCall(const CallEvent &Call,
CheckerContext &C) const {
if (!isNullAfterMoveMethod(Call))
return false;
ProgramStateRef State = C.getState();
const MemRegion *ThisR =
cast<CXXInstanceCall>(&Call)->getCXXThisVal().getAsRegion();
if (!move::isMovedFrom(State, ThisR)) {
// TODO: Model this case as well. At least, avoid invalidation of globals.
return false;
}
// TODO: Add a note to bug reports describing this decision.
C.addTransition(
State->BindExpr(Call.getOriginExpr(), C.getLocationContext(),
C.getSValBuilder().makeZeroVal(Call.getResultType())));
return true;
}
void ento::registerSmartPtrModeling(CheckerManager &Mgr) {
Mgr.registerChecker<SmartPtrModeling>();
}
bool ento::shouldRegisterSmartPtrModeling(const LangOptions &LO) {
return LO.CPlusPlus;
}