llvm/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp

//=-- ExprEngineCallAndReturn.cpp - Support for call/return -----*- 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
//
//===----------------------------------------------------------------------===//
//
//  This file defines ExprEngine's support for calls and returns.
//
//===----------------------------------------------------------------------===//

#include "PrettyStackTraceLocationContext.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/Analysis/Analyses/LiveVariables.h"
#include "clang/Analysis/ConstructionContext.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/SaveAndRestore.h"
#include <optional>

usingnamespaceclang;
usingnamespaceento;

#define DEBUG_TYPE

STATISTIC(NumOfDynamicDispatchPathSplits,
  "The # of times we split the path due to imprecise dynamic dispatch info");

STATISTIC(NumInlinedCalls,
  "The # of times we inlined a call");

STATISTIC(NumReachedInlineCountMax,
  "The # of times we reached inline count maximum");

void ExprEngine::processCallEnter(NodeBuilderContext& BC, CallEnter CE,
                                  ExplodedNode *Pred) {}

// Find the last statement on the path to the exploded node and the
// corresponding Block.
static std::pair<const Stmt*,
                 const CFGBlock*> getLastStmt(const ExplodedNode *Node) {}

/// Adjusts a return value when the called function's return type does not
/// match the caller's expression type. This can happen when a dynamic call
/// is devirtualized, and the overriding method has a covariant (more specific)
/// return type than the parent's method. For C++ objects, this means we need
/// to add base casts.
static SVal adjustReturnValue(SVal V, QualType ExpectedTy, QualType ActualTy,
                              StoreManager &StoreMgr) {}

void ExprEngine::removeDeadOnEndOfFunction(NodeBuilderContext& BC,
                                           ExplodedNode *Pred,
                                           ExplodedNodeSet &Dst) {}

static bool wasDifferentDeclUsedForInlining(CallEventRef<> Call,
    const StackFrameContext *calleeCtx) {}

// Returns the number of elements in the array currently being destructed.
// If the element count is not found 0 will be returned.
static unsigned getElementCountOfArrayBeingDestructed(
    const CallEvent &Call, const ProgramStateRef State, SValBuilder &SVB) {}

ProgramStateRef ExprEngine::removeStateTraitsUsedForArrayEvaluation(
    ProgramStateRef State, const CXXConstructExpr *E,
    const LocationContext *LCtx) {}

/// The call exit is simulated with a sequence of nodes, which occur between
/// CallExitBegin and CallExitEnd. The following operations occur between the
/// two program points:
/// 1. CallExitBegin (triggers the start of call exit sequence)
/// 2. Bind the return value
/// 3. Run Remove dead bindings to clean up the dead symbols from the callee.
/// 4. CallExitEnd (switch to the caller context)
/// 5. PostStmt<CallExpr>
void ExprEngine::processCallExit(ExplodedNode *CEBNode) {}

bool ExprEngine::isSmall(AnalysisDeclContext *ADC) const {}

bool ExprEngine::isLarge(AnalysisDeclContext *ADC) const {}

bool ExprEngine::isHuge(AnalysisDeclContext *ADC) const {}

void ExprEngine::examineStackFrames(const Decl *D, const LocationContext *LCtx,
                               bool &IsRecursive, unsigned &StackDepth) {}

// The GDM component containing the dynamic dispatch bifurcation info. When
// the exact type of the receiver is not known, we want to explore both paths -
// one on which we do inline it and the other one on which we don't. This is
// done to ensure we do not drop coverage.
// This is the map from the receiver region to a bool, specifying either we
// consider this region's information precise or not along the given path.
namespace {
  enum DynamicDispatchMode {};
} // end anonymous namespace

REGISTER_MAP_WITH_PROGRAMSTATE()
REGISTER_TRAIT_WITH_PROGRAMSTATE()

void ExprEngine::ctuBifurcate(const CallEvent &Call, const Decl *D,
                              NodeBuilder &Bldr, ExplodedNode *Pred,
                              ProgramStateRef State) {}

void ExprEngine::inlineCall(WorkList *WList, const CallEvent &Call,
                            const Decl *D, NodeBuilder &Bldr,
                            ExplodedNode *Pred, ProgramStateRef State) {}

static ProgramStateRef getInlineFailedState(ProgramStateRef State,
                                            const Stmt *CallE) {}

void ExprEngine::VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred,
                               ExplodedNodeSet &dst) {}

ProgramStateRef ExprEngine::finishArgumentConstruction(ProgramStateRef State,
                                                       const CallEvent &Call) {}

void ExprEngine::finishArgumentConstruction(ExplodedNodeSet &Dst,
                                            ExplodedNode *Pred,
                                            const CallEvent &Call) {}

void ExprEngine::evalCall(ExplodedNodeSet &Dst, ExplodedNode *Pred,
                          const CallEvent &Call) {}

ProgramStateRef ExprEngine::bindReturnValue(const CallEvent &Call,
                                            const LocationContext *LCtx,
                                            ProgramStateRef State) {}

// Conservatively evaluate call by invalidating regions and binding
// a conjured return value.
void ExprEngine::conservativeEvalCall(const CallEvent &Call, NodeBuilder &Bldr,
                                      ExplodedNode *Pred, ProgramStateRef State) {}

ExprEngine::CallInlinePolicy
ExprEngine::mayInlineCallKind(const CallEvent &Call, const ExplodedNode *Pred,
                              AnalyzerOptions &Opts,
                              const EvalCallOptions &CallOpts) {}

/// Returns true if the given C++ class contains a member with the given name.
static bool hasMember(const ASTContext &Ctx, const CXXRecordDecl *RD,
                      StringRef Name) {}

/// Returns true if the given C++ class is a container or iterator.
///
/// Our heuristic for this is whether it contains a method named 'begin()' or a
/// nested type named 'iterator' or 'iterator_category'.
static bool isContainerClass(const ASTContext &Ctx, const CXXRecordDecl *RD) {}

/// Returns true if the given function refers to a method of a C++ container
/// or iterator.
///
/// We generally do a poor job modeling most containers right now, and might
/// prefer not to inline their methods.
static bool isContainerMethod(const ASTContext &Ctx,
                              const FunctionDecl *FD) {}

/// Returns true if the given function is the destructor of a class named
/// "shared_ptr".
static bool isCXXSharedPtrDtor(const FunctionDecl *FD) {}

/// Returns true if the function in \p CalleeADC may be inlined in general.
///
/// This checks static properties of the function, such as its signature and
/// CFG, to determine whether the analyzer should ever consider inlining it,
/// in any context.
bool ExprEngine::mayInlineDecl(AnalysisDeclContext *CalleeADC) const {}

bool ExprEngine::shouldInlineCall(const CallEvent &Call, const Decl *D,
                                  const ExplodedNode *Pred,
                                  const EvalCallOptions &CallOpts) {}

bool ExprEngine::shouldInlineArrayConstruction(const ProgramStateRef State,
                                               const CXXConstructExpr *CE,
                                               const LocationContext *LCtx) {}

bool ExprEngine::shouldInlineArrayDestruction(uint64_t Size) {}

bool ExprEngine::shouldRepeatCtorCall(ProgramStateRef State,
                                      const CXXConstructExpr *E,
                                      const LocationContext *LCtx) {}

static bool isTrivialObjectAssignment(const CallEvent &Call) {}

void ExprEngine::defaultEvalCall(NodeBuilder &Bldr, ExplodedNode *Pred,
                                 const CallEvent &CallTemplate,
                                 const EvalCallOptions &CallOpts) {}

void ExprEngine::BifurcateCall(const MemRegion *BifurReg,
                               const CallEvent &Call, const Decl *D,
                               NodeBuilder &Bldr, ExplodedNode *Pred) {}

void ExprEngine::VisitReturnStmt(const ReturnStmt *RS, ExplodedNode *Pred,
                                 ExplodedNodeSet &Dst) {}