diff options
author | dim <dim@FreeBSD.org> | 2012-12-02 13:20:44 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2012-12-02 13:20:44 +0000 |
commit | 056abd2059c65a3e908193aeae16fad98017437c (patch) | |
tree | 2732d02d7d51218d6eed98ac7fcfc5b8794896b5 /include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h | |
parent | cc73504950eb7b5dff2dded9bedd67bc36d64641 (diff) | |
download | FreeBSD-src-056abd2059c65a3e908193aeae16fad98017437c.zip FreeBSD-src-056abd2059c65a3e908193aeae16fad98017437c.tar.gz |
Vendor import of clang release_32 branch r168974 (effectively, 3.2 RC2):
http://llvm.org/svn/llvm-project/cfe/branches/release_32@168974
Diffstat (limited to 'include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h')
-rw-r--r-- | include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h | 167 |
1 files changed, 117 insertions, 50 deletions
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h index f6c5830..a6a91e2 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h +++ b/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> |