llvm/clang/lib/AST/ByteCode/Interp.cpp

//===------- Interp.cpp - Interpreter for the constexpr VM ------*- 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
//
//===----------------------------------------------------------------------===//

#include "Interp.h"
#include "Function.h"
#include "InterpFrame.h"
#include "InterpShared.h"
#include "InterpStack.h"
#include "Opcode.h"
#include "PrimType.h"
#include "Program.h"
#include "State.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTDiagnostic.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/Basic/DiagnosticSema.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/StringExtras.h"
#include <limits>
#include <vector>

usingnamespaceclang;
usingnamespaceclang::interp;

static bool RetValue(InterpState &S, CodePtr &Pt, APValue &Result) {}

//===----------------------------------------------------------------------===//
// Jmp, Jt, Jf
//===----------------------------------------------------------------------===//

static bool Jmp(InterpState &S, CodePtr &PC, int32_t Offset) {}

static bool Jt(InterpState &S, CodePtr &PC, int32_t Offset) {}

static bool Jf(InterpState &S, CodePtr &PC, int32_t Offset) {}

static void diagnoseMissingInitializer(InterpState &S, CodePtr OpPC,
                                       const ValueDecl *VD) {}

static void diagnoseNonConstVariable(InterpState &S, CodePtr OpPC,
                                     const ValueDecl *VD);
static bool diagnoseUnknownDecl(InterpState &S, CodePtr OpPC,
                                const ValueDecl *D) {}

static void diagnoseNonConstVariable(InterpState &S, CodePtr OpPC,
                                     const ValueDecl *VD) {}

static bool CheckActive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
                        AccessKinds AK) {}

static bool CheckTemporary(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
                           AccessKinds AK) {}

static bool CheckGlobal(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {}

namespace clang {
namespace interp {
static void popArg(InterpState &S, const Expr *Arg) {}

void cleanupAfterFunctionCall(InterpState &S, CodePtr OpPC,
                              const Function *Func) {}

bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {}

bool CheckArray(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {}

bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
               AccessKinds AK) {}

bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc) {}

static bool CheckConstant(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {}

bool CheckNull(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
               CheckSubobjectKind CSK) {}

bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
                AccessKinds AK) {}

bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
                CheckSubobjectKind CSK) {}

bool CheckSubobject(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
                    CheckSubobjectKind CSK) {}

bool CheckDowncast(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
                   uint32_t Offset) {}

bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {}

bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {}

bool CheckVolatile(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
                   AccessKinds AK) {}

bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
                      AccessKinds AK) {}

bool CheckGlobalInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {}

static bool CheckWeak(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {}

bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
               AccessKinds AK) {}

/// This is not used by any of the opcodes directly. It's used by
/// EvalEmitter to do the final lvalue-to-rvalue conversion.
bool CheckFinalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {}

bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {}

bool CheckInvoke(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {}

bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {}

bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) {}

bool CheckCallDepth(InterpState &S, CodePtr OpPC) {}

bool CheckThis(InterpState &S, CodePtr OpPC, const Pointer &This) {}

bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD) {}

bool CheckFloatResult(InterpState &S, CodePtr OpPC, const Floating &Result,
                      APFloat::opStatus Status, FPOptions FPO) {}

bool CheckDynamicMemoryAllocation(InterpState &S, CodePtr OpPC) {}

bool CheckNewDeleteForms(InterpState &S, CodePtr OpPC,
                         DynamicAllocator::Form AllocForm,
                         DynamicAllocator::Form DeleteForm, const Descriptor *D,
                         const Expr *NewExpr) {}

bool CheckDeleteSource(InterpState &S, CodePtr OpPC, const Expr *Source,
                       const Pointer &Ptr) {}

/// We aleady know the given DeclRefExpr is invalid for some reason,
/// now figure out why and print appropriate diagnostics.
bool CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR) {}

bool CheckDummy(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
                AccessKinds AK) {}

bool CheckNonNullArgs(InterpState &S, CodePtr OpPC, const Function *F,
                      const CallExpr *CE, unsigned ArgSize) {}

// FIXME: This is similar to code we already have in Compiler.cpp.
// I think it makes sense to instead add the field and base destruction stuff
// to the destructor Function itself. Then destroying a record would really
// _just_ be calling its destructor. That would also help with the diagnostic
// difference when the destructor or a field/base fails.
static bool runRecordDestructor(InterpState &S, CodePtr OpPC,
                                const Pointer &BasePtr,
                                const Descriptor *Desc) {}

static bool RunDestructors(InterpState &S, CodePtr OpPC, const Block *B) {}

bool Free(InterpState &S, CodePtr OpPC, bool DeleteIsArrayForm,
          bool IsGlobalDelete) {}

void diagnoseEnumValue(InterpState &S, CodePtr OpPC, const EnumDecl *ED,
                       const APSInt &Value) {}

bool CheckLiteralType(InterpState &S, CodePtr OpPC, const Type *T) {}

static bool checkConstructor(InterpState &S, CodePtr OpPC, const Function *Func,
                             const Pointer &ThisPtr) {}

bool CallVar(InterpState &S, CodePtr OpPC, const Function *Func,
             uint32_t VarArgSize) {}

bool Call(InterpState &S, CodePtr OpPC, const Function *Func,
          uint32_t VarArgSize) {}

bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func,
              uint32_t VarArgSize) {}

bool CallBI(InterpState &S, CodePtr OpPC, const Function *Func,
            const CallExpr *CE, uint32_t BuiltinID) {}

bool CallPtr(InterpState &S, CodePtr OpPC, uint32_t ArgSize,
             const CallExpr *CE) {}

bool CheckNewTypeMismatch(InterpState &S, CodePtr OpPC, const Expr *E,
                          std::optional<uint64_t> ArraySize) {}

bool InvalidNewDeleteExpr(InterpState &S, CodePtr OpPC, const Expr *E) {}

bool handleFixedPointOverflow(InterpState &S, CodePtr OpPC,
                              const FixedPoint &FP) {}

bool InvalidShuffleVectorIndex(InterpState &S, CodePtr OpPC, uint32_t Index) {}

bool CheckPointerToIntegralCast(InterpState &S, CodePtr OpPC,
                                const Pointer &Ptr, unsigned BitWidth) {}

bool CastPointerIntegralAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {}

bool CastPointerIntegralAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {}

// https://github.com/llvm/llvm-project/issues/102513
#if defined(_WIN32) && !defined(__clang__) && !defined(NDEBUG)
#pragma optimize("", off)
#endif
bool Interpret(InterpState &S, APValue &Result) {}
// https://github.com/llvm/llvm-project/issues/102513
#if defined(_WIN32) && !defined(__clang__) && !defined(NDEBUG)
#pragma optimize("", on)
#endif

} // namespace interp
} // namespace clang