//===- CallEvent.h - Wrapper for all function and method calls ----*- C++ -*--//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
/// \file This file defines CallEvent and its subclasses, which represent path-
/// sensitive instances of different kinds of function and method calls
/// (C, C++, and Objective-C).
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_STATICANALYZER_PATHSENSITIVE_CALL
#define LLVM_CLANG_STATICANALYZER_PATHSENSITIVE_CALL
#include "clang/AST/DeclCXX.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/Analysis/AnalysisContext.h"
#include "clang/Basic/SourceManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "llvm/ADT/PointerIntPair.h"
namespace clang {
class ProgramPoint;
class ProgramPointTag;
namespace ento {
enum CallEventKind {
CE_Function,
CE_Block,
CE_BEG_SIMPLE_CALLS = CE_Function,
CE_END_SIMPLE_CALLS = CE_Block,
CE_CXXMember,
CE_CXXMemberOperator,
CE_CXXDestructor,
CE_BEG_CXX_INSTANCE_CALLS = CE_CXXMember,
CE_END_CXX_INSTANCE_CALLS = CE_CXXDestructor,
CE_CXXConstructor,
CE_CXXAllocator,
CE_BEG_FUNCTION_CALLS = CE_Function,
CE_END_FUNCTION_CALLS = CE_CXXAllocator,
CE_ObjCMessage
};
class CallEvent;
class CallEventManager;
template<typename T = CallEvent>
class CallEventRef : public IntrusiveRefCntPtr<const T> {
public:
CallEventRef(const T *Call) : IntrusiveRefCntPtr<const T>(Call) {}
CallEventRef(const CallEventRef &Orig) : IntrusiveRefCntPtr<const T>(Orig) {}
CallEventRef<T> cloneWithState(ProgramStateRef State) const {
return this->getPtr()->template cloneWithState<T>(State);
}
// Allow implicit conversions to a superclass type, since CallEventRef
// behaves like a pointer-to-const.
template <typename SuperT>
operator CallEventRef<SuperT> () const {
return this->getPtr();
}
};
/// \class RuntimeDefinition
/// \brief Defines the runtime definition of the called function.
///
/// Encapsulates the information we have about which Decl will be used
/// when the call is executed on the given path. When dealing with dynamic
/// dispatch, the information is based on DynamicTypeInfo and might not be
/// precise.
class RuntimeDefinition {
/// The Declaration of the function which could be called at runtime.
/// NULL if not available.
const Decl *D;
/// The region representing an object (ObjC/C++) on which the method is
/// called. With dynamic dispatch, the method definition depends on the
/// runtime type of this object. NULL when the DynamicTypeInfo is
/// precise.
const MemRegion *R;
public:
RuntimeDefinition(): D(0), R(0) {}
RuntimeDefinition(const Decl *InD): D(InD), R(0) {}
RuntimeDefinition(const Decl *InD, const MemRegion *InR): D(InD), R(InR) {}
const Decl *getDecl() { return D; }
/// \brief Check if the definition we have is precise.
/// If not, it is possible that the call dispatches to another definition at
/// execution time.
bool mayHaveOtherDefinitions() { return R != 0; }
/// When other definitions are possible, returns the region whose runtime type
/// determines the method definition.
const MemRegion *getDispatchRegion() { return R; }
};
/// \brief Represents an abstract call to a function or method along a
/// particular path.
///
/// CallEvents are created through the factory methods of CallEventManager.
///
/// CallEvents should always be cheap to create and destroy. In order for
/// CallEventManager to be able to re-use CallEvent-sized memory blocks,
/// subclasses of CallEvent may not add any data members to the base class.
/// Use the "Data" and "Location" fields instead.
class CallEvent {
public:
typedef CallEventKind Kind;
private:
ProgramStateRef State;
const LocationContext *LCtx;
llvm::PointerUnion<const Expr *, const Decl *> Origin;
void operator=(const CallEvent &) LLVM_DELETED_FUNCTION;
protected:
// This is user data for subclasses.
const void *Data;
// This is user data for subclasses.
// This should come right before RefCount, so that the two fields can be
// packed together on LP64 platforms.
SourceLocation Location;
private:
mutable unsigned RefCount;
template <typename T> friend struct llvm::IntrusiveRefCntPtrInfo;
void Retain() const { ++RefCount; }
void Release() const;
protected:
friend class CallEventManager;
CallEvent(const Expr *E, ProgramStateRef state, const LocationContext *lctx)
: State(state), LCtx(lctx), Origin(E), RefCount(0) {}
CallEvent(const Decl *