forked from OSchip/llvm-project
[analyzer] Add some convenience accessors to CallEvent, and use them.
These are CallEvent-equivalents of helpers already accessible in CheckerContext, as part of making it easier for new checkers to be written using CallEvent rather than raw CallExprs. llvm-svn: 167338
This commit is contained in:
parent
0da6747901
commit
829c383114
|
@ -249,6 +249,12 @@ public:
|
|||
/// \brief Returns the result type, adjusted for references.
|
||||
QualType getResultType() const;
|
||||
|
||||
/// \brief Returns the return value of the call.
|
||||
///
|
||||
/// This should only be called if the CallEvent was created using a state in
|
||||
/// which the return value has already been bound to the origin expression.
|
||||
SVal getReturnValue() const;
|
||||
|
||||
/// \brief Returns true if any of the arguments appear to represent callbacks.
|
||||
bool hasNonZeroCallbackArg() const;
|
||||
|
||||
|
@ -261,6 +267,38 @@ public:
|
|||
return hasNonZeroCallbackArg();
|
||||
}
|
||||
|
||||
/// \brief Returns true if the callee is an externally-visible function in the
|
||||
/// top-level namespace, such as \c malloc.
|
||||
///
|
||||
/// You can use this call to determine that a particular function really is
|
||||
/// a library function and not, say, a C++ member function with the same name.
|
||||
///
|
||||
/// If a name is provided, the function must additionally match the given
|
||||
/// name.
|
||||
///
|
||||
/// Note that this deliberately excludes C++ library functions in the \c std
|
||||
/// namespace, but will include C library functions accessed through the
|
||||
/// \c std namespace. This also does not check if the function is declared
|
||||
/// as 'extern "C"', or if it uses C++ name mangling.
|
||||
// FIXME: Add a helper for checking namespaces.
|
||||
// FIXME: Move this down to AnyFunctionCall once checkers have more
|
||||
// precise callbacks.
|
||||
bool isGlobalCFunction(StringRef SpecificName = StringRef()) const;
|
||||
|
||||
/// \brief Returns the name of the callee, if its name is a simple identifier.
|
||||
///
|
||||
/// Note that this will fail for Objective-C methods, blocks, and C++
|
||||
/// overloaded operators. The former is named by a Selector rather than a
|
||||
/// simple identifier, and the latter two do not have names.
|
||||
// FIXME: Move this down to AnyFunctionCall once checkers have more
|
||||
// precise callbacks.
|
||||
const IdentifierInfo *getCalleeIdentifier() const {
|
||||
const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(getDecl());
|
||||
if (!ND)
|
||||
return 0;
|
||||
return ND->getIdentifier();
|
||||
}
|
||||
|
||||
/// \brief Returns an appropriate ProgramPoint for this call.
|
||||
ProgramPoint getProgramPoint(bool IsPreVisit = false,
|
||||
const ProgramPointTag *Tag = 0) const;
|
||||
|
|
|
@ -212,9 +212,18 @@ public:
|
|||
return getCalleeName(FunDecl);
|
||||
}
|
||||
|
||||
/// \brief Returns true if the given function is the specified built-in or
|
||||
/// system library C function.
|
||||
static bool isCLibraryFunction(const FunctionDecl *FD, StringRef Name);
|
||||
/// \brief Returns true if the callee is an externally-visible function in the
|
||||
/// top-level namespace, such as \c malloc.
|
||||
///
|
||||
/// If a name is provided, the function must additionally match the given
|
||||
/// name.
|
||||
///
|
||||
/// Note that this deliberately excludes C++ library functions in the \c std
|
||||
/// namespace, but will include C library functions accessed through the
|
||||
/// \c std namespace. This also does not check if the function is declared
|
||||
/// as 'extern "C"', or if it uses C++ name mangling.
|
||||
static bool isCLibraryFunction(const FunctionDecl *FD,
|
||||
StringRef Name = StringRef());
|
||||
|
||||
/// \brief Depending on wither the location corresponds to a macro, return
|
||||
/// either the macro name or the token spelling.
|
||||
|
|
|
@ -105,8 +105,7 @@ void DynamicTypePropagation::checkPostCall(const CallEvent &Call,
|
|||
if (const ObjCMethodCall *Msg = dyn_cast<ObjCMethodCall>(&Call)) {
|
||||
|
||||
// Get the returned value if it's a region.
|
||||
SVal Result = C.getSVal(Call.getOriginExpr());
|
||||
const MemRegion *RetReg = Result.getAsRegion();
|
||||
const MemRegion *RetReg = Call.getReturnValue().getAsRegion();
|
||||
if (!RetReg)
|
||||
return;
|
||||
|
||||
|
|
|
@ -291,13 +291,12 @@ void ObjCSelfInitChecker::checkPostCall(const CallEvent &CE,
|
|||
// returns 'self'. So assign the flags, which were set on 'self' to the
|
||||
// return value.
|
||||
// EX: self = performMoreInitialization(self)
|
||||
const Expr *CallExpr = CE.getOriginExpr();
|
||||
if (CallExpr)
|
||||
addSelfFlag(state, state->getSVal(CallExpr, C.getLocationContext()),
|
||||
prevFlags, C);
|
||||
addSelfFlag(state, CE.getReturnValue(), prevFlags, C);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
C.addTransition(state);
|
||||
}
|
||||
|
||||
void ObjCSelfInitChecker::checkLocation(SVal location, bool isLoad,
|
||||
|
|
|
@ -2783,8 +2783,7 @@ void RetainCountChecker::processSummaryOfInlined(const RetainSummary &Summ,
|
|||
// Consult the summary for the return value.
|
||||
RetEffect RE = Summ.getRetEffect();
|
||||
if (RE.getKind() == RetEffect::NoRetHard) {
|
||||
SymbolRef Sym = state->getSVal(CallOrMsg.getOriginExpr(),
|
||||
C.getLocationContext()).getAsSymbol();
|
||||
SymbolRef Sym = CallOrMsg.getReturnValue().getAsSymbol();
|
||||
if (Sym)
|
||||
state = removeRefBinding(state, Sym);
|
||||
}
|
||||
|
@ -2863,8 +2862,7 @@ void RetainCountChecker::checkSummary(const RetainSummary &Summ,
|
|||
|
||||
case RetEffect::OwnedAllocatedSymbol:
|
||||
case RetEffect::OwnedSymbol: {
|
||||
SymbolRef Sym = state->getSVal(CallOrMsg.getOriginExpr(),
|
||||
C.getLocationContext()).getAsSymbol();
|
||||
SymbolRef Sym = CallOrMsg.getReturnValue().getAsSymbol();
|
||||
if (!Sym)
|
||||
break;
|
||||
|
||||
|
@ -2883,7 +2881,7 @@ void RetainCountChecker::checkSummary(const RetainSummary &Summ,
|
|||
case RetEffect::ARCNotOwnedSymbol:
|
||||
case RetEffect::NotOwnedSymbol: {
|
||||
const Expr *Ex = CallOrMsg.getOriginExpr();
|
||||
SymbolRef Sym = state->getSVal(Ex, C.getLocationContext()).getAsSymbol();
|
||||
SymbolRef Sym = CallOrMsg.getReturnValue().getAsSymbol();
|
||||
if (!Sym)
|
||||
break;
|
||||
assert(Ex);
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
|
||||
#include "clang/Analysis/ProgramPoint.h"
|
||||
#include "clang/AST/ParentMap.h"
|
||||
#include "llvm/ADT/SmallSet.h"
|
||||
|
@ -99,6 +100,14 @@ bool CallEvent::hasNonZeroCallbackArg() const {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool CallEvent::isGlobalCFunction(StringRef FunctionName) const {
|
||||
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(getDecl());
|
||||
if (!FD)
|
||||
return false;
|
||||
|
||||
return CheckerContext::isCLibraryFunction(FD, FunctionName);
|
||||
}
|
||||
|
||||
/// \brief Returns true if a type is a pointer-to-const or reference-to-const
|
||||
/// with no further indirection.
|
||||
static bool isPointerToConst(QualType Ty) {
|
||||
|
@ -223,6 +232,13 @@ SourceRange CallEvent::getArgSourceRange(unsigned Index) const {
|
|||
return ArgE->getSourceRange();
|
||||
}
|
||||
|
||||
SVal CallEvent::getReturnValue() const {
|
||||
const Expr *E = getOriginExpr();
|
||||
if (!E)
|
||||
return UndefinedVal();
|
||||
return getSVal(E);
|
||||
}
|
||||
|
||||
void CallEvent::dump() const {
|
||||
dump(llvm::errs());
|
||||
}
|
||||
|
|
|
@ -43,6 +43,8 @@ bool CheckerContext::isCLibraryFunction(const FunctionDecl *FD,
|
|||
// Using a string compare is slow, we might want to switch on BuiltinID here.
|
||||
unsigned BId = FD->getBuiltinID();
|
||||
if (BId != 0) {
|
||||
if (Name.empty())
|
||||
return true;
|
||||
StringRef BName = FD->getASTContext().BuiltinInfo.GetName(BId);
|
||||
if (BName.find(Name) != StringRef::npos)
|
||||
return true;
|
||||
|
@ -64,9 +66,14 @@ bool CheckerContext::isCLibraryFunction(const FunctionDecl *FD,
|
|||
return false;
|
||||
|
||||
// If this function is not externally visible, it is not a C library function.
|
||||
if (FD->getLinkage() != ExternalLinkage)
|
||||
// Note that we make an exception for inline functions, which may be
|
||||
// declared in header files without external linkage.
|
||||
if (!FD->isInlined() && FD->getLinkage() != ExternalLinkage)
|
||||
return false;
|
||||
|
||||
if (Name.empty())
|
||||
return true;
|
||||
|
||||
StringRef FName = II->getName();
|
||||
if (FName.equals(Name))
|
||||
return true;
|
||||
|
|
Loading…
Reference in New Issue