diff options
Diffstat (limited to 'include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h')
| -rw-r--r-- | include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h | 80 |
1 files changed, 62 insertions, 18 deletions
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h index 9078fb94d282..81dd83fc1071 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h @@ -80,7 +80,9 @@ class CallDescription { mutable IdentifierInfo *II = nullptr; mutable bool IsLookupDone = false; - StringRef FuncName; + // The list of the qualified names used to identify the specified CallEvent, + // e.g. "{a, b}" represent the qualified names, like "a::b". + std::vector<const char *> QualifiedName; unsigned RequiredArgs; public: @@ -88,16 +90,20 @@ public: /// Constructs a CallDescription object. /// - /// @param FuncName The name of the function that will be matched. + /// @param QualifiedName The list of the name qualifiers of the function that + /// will be matched. The user is allowed to skip any of the qualifiers. + /// For example, {"std", "basic_string", "c_str"} would match both + /// std::basic_string<...>::c_str() and std::__1::basic_string<...>::c_str(). /// /// @param RequiredArgs The number of arguments that is expected to match a /// call. Omit this parameter to match every occurrence of call with a given /// name regardless the number of arguments. - CallDescription(StringRef FuncName, unsigned RequiredArgs = NoArgRequirement) - : FuncName(FuncName), RequiredArgs(RequiredArgs) {} + CallDescription(ArrayRef<const char *> QualifiedName, + unsigned RequiredArgs = NoArgRequirement) + : QualifiedName(QualifiedName), RequiredArgs(RequiredArgs) {} /// Get the name of the function that this object matches. - StringRef getFunctionName() const { return FuncName; } + StringRef getFunctionName() const { return QualifiedName.back(); } }; template<typename T = CallEvent> @@ -428,21 +434,23 @@ public: bool isArgumentConstructedDirectly(unsigned Index) const { // This assumes that the object was not yet removed from the state. return ExprEngine::getObjectUnderConstruction( - getState(), {getOriginExpr(), Index}, getCalleeStackFrame()).hasValue(); + getState(), {getOriginExpr(), Index}, getLocationContext()).hasValue(); } /// Some calls have parameter numbering mismatched from argument numbering. /// This function converts an argument index to the corresponding /// parameter index. Returns None is the argument doesn't correspond /// to any parameter variable. - Optional<unsigned> getAdjustedParameterIndex(unsigned ArgumentIndex) const { - if (dyn_cast_or_null<CXXOperatorCallExpr>(getOriginExpr()) && - dyn_cast_or_null<CXXMethodDecl>(getDecl())) { - // For member operator calls argument 0 on the expression corresponds - // to implicit this-parameter on the declaration. - return (ArgumentIndex > 0) ? Optional<unsigned>(ArgumentIndex - 1) : None; - } - return ArgumentIndex; + virtual Optional<unsigned> + getAdjustedParameterIndex(unsigned ASTArgumentIndex) const { + return ASTArgumentIndex; + } + + /// Some call event sub-classes conveniently adjust mismatching AST indices + /// to match parameter indices. This function converts an argument index + /// as understood by CallEvent to the argument index as understood by the AST. + virtual unsigned getASTArgumentIndex(unsigned CallArgumentIndex) const { + return CallArgumentIndex; } // Iterator access to formal parameters and their types. @@ -769,6 +777,20 @@ public: static bool classof(const CallEvent *CA) { return CA->getKind() == CE_CXXMemberOperator; } + + Optional<unsigned> + getAdjustedParameterIndex(unsigned ASTArgumentIndex) const override { + // For member operator calls argument 0 on the expression corresponds + // to implicit this-parameter on the declaration. + return (ASTArgumentIndex > 0) ? Optional<unsigned>(ASTArgumentIndex - 1) + : None; + } + + unsigned getASTArgumentIndex(unsigned CallArgumentIndex) const override { + // For member operator calls argument 0 on the expression corresponds + // to implicit this-parameter on the declaration. + return CallArgumentIndex + 1; + } }; /// Represents an implicit call to a C++ destructor. @@ -793,7 +815,7 @@ protected: ProgramStateRef St, const LocationContext *LCtx) : CXXInstanceCall(DD, St, LCtx) { Data = DtorDataTy(Target, IsBaseDestructor).getOpaqueValue(); - Location = Trigger->getLocEnd(); + Location = Trigger->getEndLoc(); } CXXDestructorCall(const CXXDestructorCall &Other) = default; @@ -899,15 +921,30 @@ public: return getOriginExpr()->getOperatorNew(); } + /// Number of non-placement arguments to the call. It is equal to 2 for + /// C++17 aligned operator new() calls that have alignment implicitly + /// passed as the second argument, and to 1 for other operator new() calls. + unsigned getNumImplicitArgs() const { + return getOriginExpr()->passAlignment() ? 2 : 1; + } + unsigned getNumArgs() const override { - return getOriginExpr()->getNumPlacementArgs() + 1; + return getOriginExpr()->getNumPlacementArgs() + getNumImplicitArgs(); } const Expr *getArgExpr(unsigned Index) const override { // The first argument of an allocator call is the size of the allocation. - if (Index == 0) + if (Index < getNumImplicitArgs()) return nullptr; - return getOriginExpr()->getPlacementArg(Index - 1); + return getOriginExpr()->getPlacementArg(Index - getNumImplicitArgs()); + } + + /// Number of placement arguments to the operator new() call. For example, + /// standard std::nothrow operator new and standard placement new both have + /// 1 implicit argument (size) and 1 placement argument, while regular + /// operator new() has 1 implicit argument and 0 placement arguments. + const Expr *getPlacementArgExpr(unsigned Index) const { + return getOriginExpr()->getPlacementArg(Index); } Kind getKind() const override { return CE_CXXAllocator; } @@ -1101,9 +1138,16 @@ class CallEventManager { public: CallEventManager(llvm::BumpPtrAllocator &alloc) : Alloc(alloc) {} + /// Gets an outside caller given a callee context. CallEventRef<> getCaller(const StackFrameContext *CalleeCtx, ProgramStateRef State); + /// Gets a call event for a function call, Objective-C method call, + /// or a 'new' call. + CallEventRef<> + getCall(const Stmt *S, ProgramStateRef State, + const LocationContext *LC); + CallEventRef<> getSimpleCall(const CallExpr *E, ProgramStateRef State, const LocationContext *LCtx); |
