//===- CallEvent.h - Wrapper for all function and method calls --*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // /// \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_CORE_PATHSENSITIVE_CALLEVENT_H #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CALLEVENT_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/Stmt.h" #include "clang/AST/Type.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/iterator_range.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" #include <cassert> #include <limits> #include <optional> #include <utility> namespace clang { class LocationContext; class ProgramPoint; class ProgramPointTag; class StackFrameContext; namespace ento { enum CallEventKind { … }; class CallEvent; template <typename T = CallEvent> class CallEventRef : public IntrusiveRefCntPtr<const T> { … }; /// \class RuntimeDefinition /// 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 { … }; /// 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 { … }; /// Represents a call to any sort of function that might have a /// FunctionDecl. class AnyFunctionCall : public CallEvent { … }; /// Represents a C function or static C++ member function call. /// /// Example: \c fun() class SimpleFunctionCall : public AnyFunctionCall { … }; /// Represents a call to a block. /// /// Example: <tt>^{ statement-body }()</tt> class BlockCall : public CallEvent { … }; /// Represents a non-static C++ member function call, no matter how /// it is written. class CXXInstanceCall : public AnyFunctionCall { … }; /// Represents a static C++ operator call. /// /// "A" in this example. /// However, "B" and "C" are represented by SimpleFunctionCall. /// \code /// struct S { /// int pad; /// static void operator()(int x, int y); /// }; /// S s{10}; /// void (*fptr)(int, int) = &S::operator(); /// /// s(1, 2); // A /// S::operator()(1, 2); // B /// fptr(1, 2); // C /// \endcode class CXXStaticOperatorCall : public SimpleFunctionCall { … }; /// Represents a non-static C++ member function call. /// /// Example: \c obj.fun() class CXXMemberCall : public CXXInstanceCall { … }; /// Represents a C++ overloaded operator call where the operator is /// implemented as a non-static member function. /// /// Example: <tt>iter + 1</tt> class CXXMemberOperatorCall : public CXXInstanceCall { … }; /// Represents an implicit call to a C++ destructor. /// /// This can occur at the end of a scope (for automatic objects), at the end /// of a full-expression (for temporaries), or as part of a delete. class CXXDestructorCall : public CXXInstanceCall { … }; /// Represents any constructor invocation. This includes regular constructors /// and inherited constructors. class AnyCXXConstructorCall : public AnyFunctionCall { … }; /// Represents a call to a C++ constructor. /// /// Example: \c T(1) class CXXConstructorCall : public AnyCXXConstructorCall { … }; /// Represents a call to a C++ inherited constructor. /// /// Example: \c class T : public S { using S::S; }; T(1); /// // Note, it is difficult to model the parameters. This is one of the reasons // why we skip analysis of inheriting constructors as top-level functions. // CXXInheritedCtorInitExpr doesn't take arguments and doesn't model parameter // initialization because there is none: the arguments in the outer // CXXConstructExpr directly initialize the parameters of the base class // constructor, and no copies are made. (Making a copy of the parameter is // incorrect, at least if it's done in an observable way.) The derived class // constructor doesn't even exist in the formal model. /// E.g., in: /// /// struct X { X *p = this; ~X() {} }; /// struct A { A(X x) : b(x.p == &x) {} bool b; }; /// struct B : A { using A::A; }; /// B b = X{}; /// /// ... b.b is initialized to true. class CXXInheritedConstructorCall : public AnyCXXConstructorCall { … }; /// Represents the memory allocation call in a C++ new-expression. /// /// This is a call to "operator new". class CXXAllocatorCall : public AnyFunctionCall { … }; /// Represents the memory deallocation call in a C++ delete-expression. /// /// This is a call to "operator delete". // FIXME: CXXDeleteExpr isn't present for custom delete operators, or even for // some those that are in the standard library, like the no-throw or align_val // versions. // Some pointers: // http://lists.llvm.org/pipermail/cfe-dev/2020-April/065080.html // clang/test/Analysis/cxx-dynamic-memory-analysis-order.cpp // clang/unittests/StaticAnalyzer/CallEventTest.cpp class CXXDeallocatorCall : public AnyFunctionCall { … }; /// Represents the ways an Objective-C message send can occur. // // Note to maintainers: OCM_Message should always be last, since it does not // need to fit in the Data field's low bits. enum ObjCMessageKind { … }; /// Represents any expression that calls an Objective-C method. /// /// This includes all of the kinds listed in ObjCMessageKind. class ObjCMethodCall : public CallEvent { … }; /// Manages the lifetime of CallEvent objects. /// /// CallEventManager provides a way to create arbitrary CallEvents "on the /// stack" as if they were value objects by keeping a cache of CallEvent-sized /// memory blocks. The CallEvents created by CallEventManager are only valid /// for the lifetime of the OwnedCallEvent that holds them; right now these /// objects cannot be copied and ownership cannot be transferred. class CallEventManager { … }; template <typename T> CallEventRef<T> CallEvent::cloneWithState(ProgramStateRef NewState) const { … } inline void CallEvent::Release() const { … } } // namespace ento } // namespace clang namespace llvm { // Support isa<>, cast<>, and dyn_cast<> for CallEventRef. simplify_type<clang::ento::CallEventRef<T>>; } // namespace llvm #endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CALLEVENT_H