diff options
Diffstat (limited to 'clang/lib/StaticAnalyzer/Core/CallEvent.cpp')
| -rw-r--r-- | clang/lib/StaticAnalyzer/Core/CallEvent.cpp | 134 |
1 files changed, 78 insertions, 56 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp index 47a10bf23c4..0d234d5a273 100644 --- a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp +++ b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp @@ -1,4 +1,4 @@ -//===- Calls.cpp - Wrapper for all function and method calls ------*- C++ -*--// +//===- CallEvent.cpp - Wrapper for all function and method calls ----------===// // // The LLVM Compiler Infrastructure // @@ -14,14 +14,51 @@ //===----------------------------------------------------------------------===// #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclBase.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprObjC.h" #include "clang/AST/ParentMap.h" +#include "clang/AST/Stmt.h" +#include "clang/AST/Type.h" +#include "clang/Analysis/AnalysisDeclContext.h" +#include "clang/Analysis/CFG.h" #include "clang/Analysis/ProgramPoint.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Basic/Specifiers.h" +#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h" #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" -#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include <cassert> +#include <utility> #define DEBUG_TYPE "static-analyzer-call-event" @@ -78,7 +115,7 @@ static bool isCallback(QualType T) { } static bool isVoidPointerToNonConst(QualType T) { - if (const PointerType *PT = T->getAs<PointerType>()) { + if (const auto *PT = T->getAs<PointerType>()) { QualType PointeeTy = PT->getPointeeType(); if (PointeeTy.isConstQualified()) return false; @@ -119,7 +156,7 @@ bool CallEvent::hasVoidPointerToNonConstArg() const { } bool CallEvent::isGlobalCFunction(StringRef FunctionName) const { - const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(getDecl()); + const auto *FD = dyn_cast_or_null<FunctionDecl>(getDecl()); if (!FD) return false; @@ -235,7 +272,7 @@ SVal CallEvent::getArgSVal(unsigned Index) const { SourceRange CallEvent::getArgSourceRange(unsigned Index) const { const Expr *ArgE = getArgExpr(Index); if (!ArgE) - return SourceRange(); + return {}; return ArgE->getSourceRange(); } @@ -266,7 +303,6 @@ void CallEvent::dump(raw_ostream &Out) const { Out << "Unknown call (type " << getKind() << ")"; } - bool CallEvent::isCallStmt(const Stmt *S) { return isa<CallExpr>(S) || isa<ObjCMessageExpr>(S) || isa<CXXConstructExpr>(S) @@ -275,11 +311,11 @@ bool CallEvent::isCallStmt(const Stmt *S) { QualType CallEvent::getDeclaredResultType(const Decl *D) { assert(D); - if (const FunctionDecl* FD = dyn_cast<FunctionDecl>(D)) + if (const auto *FD = dyn_cast<FunctionDecl>(D)) return FD->getReturnType(); - if (const ObjCMethodDecl* MD = dyn_cast<ObjCMethodDecl>(D)) + if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) return MD->getReturnType(); - if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) { + if (const auto *BD = dyn_cast<BlockDecl>(D)) { // Blocks are difficult because the return type may not be stored in the // BlockDecl itself. The AST should probably be enhanced, but for now we // just do what we can. @@ -296,7 +332,7 @@ QualType CallEvent::getDeclaredResultType(const Decl *D) { return Ty; } - return QualType(); + return {}; } llvm_unreachable("unknown callable kind"); @@ -305,11 +341,11 @@ QualType CallEvent::getDeclaredResultType(const Decl *D) { bool CallEvent::isVariadic(const Decl *D) { assert(D); - if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) + if (const auto *FD = dyn_cast<FunctionDecl>(D)) return FD->isVariadic(); - if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) + if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) return MD->isVariadic(); - if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) + if (const auto *BD = dyn_cast<BlockDecl>(D)) return BD->isVariadic(); llvm_unreachable("unknown callable kind"); @@ -369,13 +405,13 @@ RuntimeDefinition AnyFunctionCall::getRuntimeDefinition() const { } } - return RuntimeDefinition(); + return {}; } void AnyFunctionCall::getInitialStackFrameContents( const StackFrameContext *CalleeCtx, BindingsTy &Bindings) const { - const FunctionDecl *D = cast<FunctionDecl>(CalleeCtx->getDecl()); + const auto *D = cast<FunctionDecl>(CalleeCtx->getDecl()); SValBuilder &SVB = getState()->getStateManager().getSValBuilder(); addParameterValuesToBindings(CalleeCtx, Bindings, SVB, *this, D->parameters()); @@ -442,7 +478,6 @@ bool AnyFunctionCall::argumentsMayEscape() const { return false; } - const FunctionDecl *SimpleFunctionCall::getDecl() const { const FunctionDecl *D = getOriginExpr()->getDirectCallee(); if (D) @@ -451,9 +486,8 @@ const FunctionDecl *SimpleFunctionCall::getDecl() const { return getSVal(getOriginExpr()->getCallee()).getAsFunctionDecl(); } - const FunctionDecl *CXXInstanceCall::getDecl() const { - const CallExpr *CE = cast_or_null<CallExpr>(getOriginExpr()); + const auto *CE = cast_or_null<CallExpr>(getOriginExpr()); if (!CE) return AnyFunctionCall::getDecl(); @@ -470,7 +504,7 @@ void CXXInstanceCall::getExtraInvalidatedValues( Values.push_back(ThisVal); // Don't invalidate if the method is const and there are no mutable fields. - if (const CXXMethodDecl *D = cast_or_null<CXXMethodDecl>(getDecl())) { + if (const auto *D = cast_or_null<CXXMethodDecl>(getDecl())) { if (!D->isConst()) return; // Get the record decl for the class of 'This'. D->getParent() may return a @@ -501,27 +535,26 @@ SVal CXXInstanceCall::getCXXThisVal() const { return ThisVal; } - RuntimeDefinition CXXInstanceCall::getRuntimeDefinition() const { // Do we have a decl at all? const Decl *D = getDecl(); if (!D) - return RuntimeDefinition(); + return {}; // If the method is non-virtual, we know we can inline it. - const CXXMethodDecl *MD = cast<CXXMethodDecl>(D); + const auto *MD = cast<CXXMethodDecl>(D); if (!MD->isVirtual()) return AnyFunctionCall::getRuntimeDefinition(); // Do we know the implicit 'this' object being called? const MemRegion *R = getCXXThisVal().getAsRegion(); if (!R) - return RuntimeDefinition(); + return {}; // Do we know anything about the type of 'this'? DynamicTypeInfo DynType = getDynamicTypeInfo(getState(), R); if (!DynType.isValid()) - return RuntimeDefinition(); + return {}; // Is the type a C++ class? (This is mostly a defensive check.) QualType RegionType = DynType.getType()->getPointeeType(); @@ -529,7 +562,7 @@ RuntimeDefinition CXXInstanceCall::getRuntimeDefinition() const { const CXXRecordDecl *RD = RegionType->getAsCXXRecordDecl(); if (!RD || !RD->hasDefinition()) - return RuntimeDefinition(); + return {}; // Find the decl for this method in that class. const CXXMethodDecl *Result = MD->getCorrespondingMethodInClass(RD, true); @@ -547,13 +580,13 @@ RuntimeDefinition CXXInstanceCall::getRuntimeDefinition() const { // this is fixed. <rdar://problem/12287087> //assert(!MD->getParent()->isDerivedFrom(RD) && "Bad DynamicTypeInfo"); - return RuntimeDefinition(); + return {}; } // Does the decl that we found have an implementation? const FunctionDecl *Definition; if (!Result->hasBody(Definition)) - return RuntimeDefinition(); + return {}; // We found a definition. If we're not sure that this devirtualization is // actually what will happen at runtime, make sure to provide the region so @@ -574,7 +607,7 @@ void CXXInstanceCall::getInitialStackFrameContents( ProgramStateManager &StateMgr = getState()->getStateManager(); SValBuilder &SVB = StateMgr.getSValBuilder(); - const CXXMethodDecl *MD = cast<CXXMethodDecl>(CalleeCtx->getDecl()); + const auto *MD = cast<CXXMethodDecl>(CalleeCtx->getDecl()); Loc ThisLoc = SVB.getCXXThis(MD, CalleeCtx); // If we devirtualized to a different member function, we need to make sure @@ -603,8 +636,6 @@ void CXXInstanceCall::getInitialStackFrameContents( } } - - const Expr *CXXMemberCall::getCXXThisExpr() const { return getOriginExpr()->getImplicitObjectArgument(); } @@ -614,19 +645,17 @@ RuntimeDefinition CXXMemberCall::getRuntimeDefinition() const { // id-expression in the class member access expression is a qualified-id, // that function is called. Otherwise, its final overrider in the dynamic type // of the object expression is called. - if (const MemberExpr *ME = dyn_cast<MemberExpr>(getOriginExpr()->getCallee())) + if (const auto *ME = dyn_cast<MemberExpr>(getOriginExpr()->getCallee())) if (ME->hasQualifier()) return AnyFunctionCall::getRuntimeDefinition(); return CXXInstanceCall::getRuntimeDefinition(); } - const Expr *CXXMemberOperatorCall::getCXXThisExpr() const { return getOriginExpr()->getArg(0); } - const BlockDataRegion *BlockCall::getBlockRegion() const { const Expr *Callee = getOriginExpr()->getCallee(); const MemRegion *DataReg = getSVal(Callee).getAsRegion(); @@ -671,7 +700,6 @@ void BlockCall::getInitialStackFrameContents(const StackFrameContext *CalleeCtx, Params); } - SVal CXXConstructorCall::getCXXThisVal() const { if (Data) return loc::MemRegionVal(static_cast<const MemRegion *>(Data)); @@ -697,7 +725,7 @@ void CXXConstructorCall::getInitialStackFrameContents( SVal ThisVal = getCXXThisVal(); if (!ThisVal.isUnknown()) { SValBuilder &SVB = getState()->getStateManager().getSValBuilder(); - const CXXMethodDecl *MD = cast<CXXMethodDecl>(CalleeCtx->getDecl()); + const auto *MD = cast<CXXMethodDecl>(CalleeCtx->getDecl()); Loc ThisLoc = SVB.getCXXThis(MD, CalleeCtx); Bindings.push_back(std::make_pair(ThisLoc, ThisVal)); } @@ -798,7 +826,7 @@ SourceRange ObjCMethodCall::getSourceRange() const { llvm_unreachable("unknown message kind"); } -typedef llvm::PointerIntPair<const PseudoObjectExpr *, 2> ObjCMessageDataTy; +using ObjCMessageDataTy = llvm::PointerIntPair<const PseudoObjectExpr *, 2>; const PseudoObjectExpr *ObjCMethodCall::getContainingPseudoObjectExpr() const { assert(Data && "Lazy lookup not yet performed."); @@ -812,7 +840,7 @@ getSyntacticFromForPseudoObjectExpr(const PseudoObjectExpr *POE) { // This handles the funny case of assigning to the result of a getter. // This can happen if the getter returns a non-const reference. - if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(Syntactic)) + if (const auto *BO = dyn_cast<BinaryOperator>(Syntactic)) Syntactic = BO->getLHS(); return Syntactic; @@ -820,13 +848,12 @@ getSyntacticFromForPseudoObjectExpr(const PseudoObjectExpr *POE) { ObjCMessageKind ObjCMethodCall::getMessageKind() const { if (!Data) { - // Find the parent, ignoring implicit casts. ParentMap &PM = getLocationContext()->getParentMap(); const Stmt *S = PM.getParentIgnoreParenCasts(getOriginExpr()); // Check if parent is a PseudoObjectExpr. - if (const PseudoObjectExpr *POE = dyn_cast_or_null<PseudoObjectExpr>(S)) { + if (const auto *POE = dyn_cast_or_null<PseudoObjectExpr>(S)) { const Expr *Syntactic = getSyntacticFromForPseudoObjectExpr(POE); ObjCMessageKind K; @@ -978,7 +1005,6 @@ RuntimeDefinition ObjCMethodCall::getRuntimeDefinition() const { Selector Sel = E->getSelector(); if (E->isInstanceMessage()) { - // Find the receiver type. const ObjCObjectPointerType *ReceiverT = nullptr; bool CanBeSubClassed = false; @@ -993,13 +1019,13 @@ RuntimeDefinition ObjCMethodCall::getRuntimeDefinition() const { } else { Receiver = getReceiverSVal().getAsRegion(); if (!Receiver) - return RuntimeDefinition(); + return {}; DynamicTypeInfo DTI = getDynamicTypeInfo(getState(), Receiver); if (!DTI.isValid()) { assert(isa<AllocaRegion>(Receiver) && "Unhandled untyped region class!"); - return RuntimeDefinition(); + return {}; } QualType DynType = DTI.getType(); @@ -1054,11 +1080,9 @@ RuntimeDefinition ObjCMethodCall::getRuntimeDefinition() const { // need to revisit this someday. In terms of memory, this table // stays around until clang quits, which also may be bad if we // need to release memory. - typedef std::pair<const ObjCInterfaceDecl*, Selector> - PrivateMethodKey; - typedef llvm::DenseMap<PrivateMethodKey, - Optional<const ObjCMethodDecl *> > - PrivateMethodCache; + using PrivateMethodKey = std::pair<const ObjCInterfaceDecl *, Selector>; + using PrivateMethodCache = + llvm::DenseMap<PrivateMethodKey, Optional<const ObjCMethodDecl *>>; static PrivateMethodCache PMC; Optional<const ObjCMethodDecl *> &Val = PMC[std::make_pair(IDecl, Sel)]; @@ -1103,7 +1127,6 @@ RuntimeDefinition ObjCMethodCall::getRuntimeDefinition() const { else return RuntimeDefinition(MD, nullptr); } - } else { // This is a class method. // If we have type info for the receiver class, we are calling via @@ -1114,7 +1137,7 @@ RuntimeDefinition ObjCMethodCall::getRuntimeDefinition() const { } } - return RuntimeDefinition(); + return {}; } bool ObjCMethodCall::argumentsMayEscape() const { @@ -1131,7 +1154,7 @@ bool ObjCMethodCall::argumentsMayEscape() const { void ObjCMethodCall::getInitialStackFrameContents( const StackFrameContext *CalleeCtx, BindingsTy &Bindings) const { - const ObjCMethodDecl *D = cast<ObjCMethodDecl>(CalleeCtx->getDecl()); + const auto *D = cast<ObjCMethodDecl>(CalleeCtx->getDecl()); SValBuilder &SVB = getState()->getStateManager().getSValBuilder(); addParameterValuesToBindings(CalleeCtx, Bindings, SVB, *this, D->parameters()); @@ -1148,12 +1171,12 @@ void ObjCMethodCall::getInitialStackFrameContents( CallEventRef<> CallEventManager::getSimpleCall(const CallExpr *CE, ProgramStateRef State, const LocationContext *LCtx) { - if (const CXXMemberCallExpr *MCE = dyn_cast<CXXMemberCallExpr>(CE)) + if (const auto *MCE = dyn_cast<CXXMemberCallExpr>(CE)) return create<CXXMemberCall>(MCE, State, LCtx); - if (const CXXOperatorCallExpr *OpCE = dyn_cast<CXXOperatorCallExpr>(CE)) { + if (const auto *OpCE = dyn_cast<CXXOperatorCallExpr>(CE)) { const FunctionDecl *DirectCallee = OpCE->getDirectCallee(); - if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DirectCallee)) + if (const auto *MD = dyn_cast<CXXMethodDecl>(DirectCallee)) if (MD->isInstance()) return create<CXXMemberOperatorCall>(OpCE, State, LCtx); @@ -1166,7 +1189,6 @@ CallEventManager::getSimpleCall(const CallExpr *CE, ProgramStateRef State, return create<SimpleFunctionCall>(CE, State, LCtx); } - CallEventRef<> CallEventManager::getCaller(const StackFrameContext *CalleeCtx, ProgramStateRef State) { @@ -1184,7 +1206,7 @@ CallEventManager::getCaller(const StackFrameContext *CalleeCtx, case Stmt::CXXConstructExprClass: case Stmt::CXXTemporaryObjectExprClass: { SValBuilder &SVB = State->getStateManager().getSValBuilder(); - const CXXMethodDecl *Ctor = cast<CXXMethodDecl>(CalleeCtx->getDecl()); + const auto *Ctor = cast<CXXMethodDecl>(CalleeCtx->getDecl()); Loc ThisPtr = SVB.getCXXThis(Ctor, CalleeCtx); SVal ThisVal = State->getSVal(ThisPtr); @@ -1209,7 +1231,7 @@ CallEventManager::getCaller(const StackFrameContext *CalleeCtx, "All other CFG elements should have exprs"); SValBuilder &SVB = State->getStateManager().getSValBuilder(); - const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CalleeCtx->getDecl()); + const auto *Dtor = cast<CXXDestructorDecl>(CalleeCtx->getDecl()); Loc ThisPtr = SVB.getCXXThis(Dtor, CalleeCtx); SVal ThisVal = State->getSVal(ThisPtr); |

