summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h')
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h167
1 files changed, 117 insertions, 50 deletions
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
index f6c5830..a6a91e2 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
@@ -20,6 +20,7 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
+#include "clang/Analysis/AnalysisContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "llvm/ADT/PointerIntPair.h"
@@ -68,15 +69,22 @@ public:
}
};
+/// \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 will be called at runtime.
- /// 0 if not available.
+ /// 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. 0 when there is no dynamic dispatch.
+ /// runtime type of this object. NULL when the DynamicTypeInfo is
+ /// precise.
const MemRegion *R;
public:
@@ -84,8 +92,15 @@ public:
RuntimeDefinition(const Decl *InD): D(InD), R(0) {}
RuntimeDefinition(const Decl *InD, const MemRegion *InR): D(InD), R(InR) {}
const Decl *getDecl() { return D; }
- const MemRegion *getDispatchRegion() { return R; }
+
+ /// \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
@@ -106,8 +121,7 @@ private:
const LocationContext *LCtx;
llvm::PointerUnion<const Expr *, const Decl *> Origin;
- // DO NOT IMPLEMENT
- CallEvent &operator=(const CallEvent &);
+ void operator=(const CallEvent &) LLVM_DELETED_FUNCTION;
protected:
// This is user data for subclasses.
@@ -139,16 +153,6 @@ protected:
: State(Original.State), LCtx(Original.LCtx), Origin(Original.Origin),
Data(Original.Data), Location(Original.Location), RefCount(0) {}
-
- ProgramStateRef getState() const {
- return State;
- }
-
- const LocationContext *getLocationContext() const {
- return LCtx;
- }
-
-
/// Copies this CallEvent, with vtable intact, into a new block of memory.
virtual void cloneTo(void *Dest) const = 0;
@@ -164,8 +168,6 @@ protected:
/// result of this call.
virtual void getExtraInvalidatedRegions(RegionList &Regions) const {}
- virtual QualType getDeclaredResultType() const = 0;
-
public:
virtual ~CallEvent() {}
@@ -178,6 +180,16 @@ public:
return Origin.dyn_cast<const Decl *>();
}
+ /// \brief The state in which the call is being evaluated.
+ ProgramStateRef getState() const {
+ return State;
+ }
+
+ /// \brief The context in which the call is being evaluated.
+ const LocationContext *getLocationContext() const {
+ return LCtx;
+ }
+
/// \brief Returns the definition of the function or method that will be
/// called.
virtual RuntimeDefinition getRuntimeDefinition() const = 0;
@@ -237,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;
@@ -249,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;
@@ -277,12 +327,12 @@ public:
return cloneWithState<CallEvent>(NewState);
}
- /// \brief Returns true if this is a statement that can be considered for
- /// inlining.
- ///
- /// FIXME: This should go away once CallEvents are cheap and easy to
- /// construct from ExplodedNodes.
- static bool mayBeInlined(const Stmt *S);
+ /// \brief Returns true if this is a statement is a function or method call
+ /// of some kind.
+ static bool isCallStmt(const Stmt *S);
+
+ /// \brief Returns the result type of a function, method declaration.
+ static QualType getDeclaredResultType(const Decl *D);
// Iterator access to formal parameters and their types.
private:
@@ -329,8 +379,6 @@ public:
// For debugging purposes only
void dump(raw_ostream &Out) const;
LLVM_ATTRIBUTE_USED void dump() const;
-
- static bool classof(const CallEvent *) { return true; }
};
@@ -346,8 +394,6 @@ protected:
: CallEvent(D, St, LCtx) {}
AnyFunctionCall(const AnyFunctionCall &Other) : CallEvent(Other) {}
- virtual QualType getDeclaredResultType() const;
-
public:
// This function is overridden by subclasses, but they must return
// a FunctionDecl.
@@ -357,9 +403,16 @@ public:
virtual RuntimeDefinition getRuntimeDefinition() const {
const FunctionDecl *FD = getDecl();
- // Note that hasBody() will fill FD with the definition FunctionDecl.
- if (FD && FD->hasBody(FD))
- return RuntimeDefinition(FD);
+ // Note that the AnalysisDeclContext will have the FunctionDecl with
+ // the definition (if one exists).
+ if (FD) {
+ AnalysisDeclContext *AD =
+ getLocationContext()->getAnalysisDeclContext()->
+ getManager()->getContext(FD);
+ if (AD->getBody())
+ return RuntimeDefinition(AD->getDecl());
+ }
+
return RuntimeDefinition();
}
@@ -442,8 +495,6 @@ protected:
virtual void getExtraInvalidatedRegions(RegionList &Regions) const;
- virtual QualType getDeclaredResultType() const;
-
public:
/// \brief Returns the region associated with this instance of the block.
///
@@ -499,13 +550,7 @@ public:
virtual const Expr *getCXXThisExpr() const { return 0; }
/// \brief Returns the value of the implicit 'this' object.
- virtual SVal getCXXThisVal() const {
- const Expr *Base = getCXXThisExpr();
- // FIXME: This doesn't handle an overloaded ->* operator.
- if (!Base)
- return UnknownVal();
- return getSVal(Base);
- }
+ virtual SVal getCXXThisVal() const;
virtual const FunctionDecl *getDecl() const;
@@ -550,6 +595,8 @@ public:
}
virtual const Expr *getCXXThisExpr() const;
+
+ virtual RuntimeDefinition getRuntimeDefinition() const;
virtual Kind getKind() const { return CE_CXXMember; }
@@ -605,6 +652,8 @@ class CXXDestructorCall : public CXXInstanceCall {
friend class CallEventManager;
protected:
+ typedef llvm::PointerIntPair<const MemRegion *, 1, bool> DtorDataTy;
+
/// Creates an implicit destructor.
///
/// \param DD The destructor that will be called.
@@ -613,10 +662,10 @@ protected:
/// \param St The path-sensitive state at this point in the program.
/// \param LCtx The location context at this point in the program.
CXXDestructorCall(const CXXDestructorDecl *DD, const Stmt *Trigger,
- const MemRegion *Target, ProgramStateRef St,
- const LocationContext *LCtx)
+ const MemRegion *Target, bool IsBaseDestructor,
+ ProgramStateRef St, const LocationContext *LCtx)
: CXXInstanceCall(DD, St, LCtx) {
- Data = Target;
+ Data = DtorDataTy(Target, IsBaseDestructor).getOpaqueValue();
Location = Trigger->getLocEnd();
}
@@ -627,9 +676,16 @@ public:
virtual SourceRange getSourceRange() const { return Location; }
virtual unsigned getNumArgs() const { return 0; }
+ virtual RuntimeDefinition getRuntimeDefinition() const;
+
/// \brief Returns the value of the implicit 'this' object.
virtual SVal getCXXThisVal() const;
+ /// Returns true if this is a call to a base class destructor.
+ bool isBaseDestructor() const {
+ return DtorDataTy::getFromOpaqueValue(Data).getInt();
+ }
+
virtual Kind getKind() const { return CE_CXXDestructor; }
static bool classof(const CallEvent *CA) {
@@ -651,10 +707,10 @@ protected:
/// a new symbolic region will be used.
/// \param St The path-sensitive state at this point in the program.
/// \param LCtx The location context at this point in the program.
- CXXConstructorCall(const CXXConstructExpr *CE, const MemRegion *target,
+ CXXConstructorCall(const CXXConstructExpr *CE, const MemRegion *Target,
ProgramStateRef St, const LocationContext *LCtx)
: AnyFunctionCall(CE, St, LCtx) {
- Data = target;
+ Data = Target;
}
CXXConstructorCall(const CXXConstructorCall &Other) : AnyFunctionCall(Other){}
@@ -761,8 +817,6 @@ protected:
virtual void getExtraInvalidatedRegions(RegionList &Regions) const;
- virtual QualType getDeclaredResultType() const;
-
/// Check if the selector may have multiple definitions (may have overrides).
virtual bool canBeOverridenInSubclass(ObjCInterfaceDecl *IDecl,
Selector Sel) const;
@@ -796,6 +850,9 @@ public:
/// \brief Returns the value of the receiver at the time of this call.
SVal getReceiverSVal() const;
+ /// \brief Return the value of 'self' if available.
+ SVal getSelfSVal() const;
+
/// \brief Get the interface for the receiver.
///
/// This works whether this is an instance message or a class message.
@@ -804,6 +861,9 @@ public:
return getOriginExpr()->getReceiverInterface();
}
+ /// \brief Checks if the receiver refers to 'self' or 'super'.
+ bool isReceiverSelfOrSuper() const;
+
/// Returns how the message was written in the source (property access,
/// subscript, or explicit message send).
ObjCMessageKind getMessageKind() const;
@@ -879,6 +939,13 @@ class CallEventManager {
return new (allocate()) T(A1, A2, A3, St, LCtx);
}
+ template <typename T, typename Arg1, typename Arg2, typename Arg3,
+ typename Arg4>
+ T *create(Arg1 A1, Arg2 A2, Arg3 A3, Arg4 A4, ProgramStateRef St,
+ const LocationContext *LCtx) {
+ return new (allocate()) T(A1, A2, A3, A4, St, LCtx);
+ }
+
public:
CallEventManager(llvm::BumpPtrAllocator &alloc) : Alloc(alloc) {}
@@ -905,9 +972,9 @@ public:
CallEventRef<CXXDestructorCall>
getCXXDestructorCall(const CXXDestructorDecl *DD, const Stmt *Trigger,
- const MemRegion *Target, ProgramStateRef State,
- const LocationContext *LCtx) {
- return create<CXXDestructorCall>(DD, Trigger, Target, State, LCtx);
+ const MemRegion *Target, bool IsBase,
+ ProgramStateRef State, const LocationContext *LCtx) {
+ return create<CXXDestructorCall>(DD, Trigger, Target, IsBase, State, LCtx);
}
CallEventRef<CXXAllocatorCall>
OpenPOWER on IntegriCloud