142 lines · c
1//===--- InterpHelpers.h - Interpreter Helper Functions --------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_CLANG_AST_INTERP_INTERPHELPERS_H10#define LLVM_CLANG_AST_INTERP_INTERPHELPERS_H11 12#include "DynamicAllocator.h"13#include "InterpState.h"14#include "Pointer.h"15 16namespace clang {17class CallExpr;18class OffsetOfExpr;19 20namespace interp {21class Block;22struct Descriptor;23 24/// Interpreter entry point.25bool Interpret(InterpState &S);26 27/// Interpret a builtin function.28bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,29 uint32_t BuiltinID);30 31/// Interpret an offsetof operation.32bool InterpretOffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E,33 ArrayRef<int64_t> ArrayIndices, int64_t &Result);34 35/// Checks if the array is offsetable.36bool CheckArray(InterpState &S, CodePtr OpPC, const Pointer &Ptr);37 38/// Checks if a pointer is live and accessible.39bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,40 AccessKinds AK);41 42/// Checks if a pointer is a dummy pointer.43bool CheckDummy(InterpState &S, CodePtr OpPC, const Block *B, AccessKinds AK);44 45/// Checks if a pointer is in range.46bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,47 AccessKinds AK);48 49/// Checks if a field from which a pointer is going to be derived is valid.50bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,51 CheckSubobjectKind CSK);52 53/// Checks if a pointer points to a mutable field.54bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr);55 56/// Checks if a value can be loaded from a block.57bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr,58 AccessKinds AK = AK_Read);59 60/// Diagnose mismatched new[]/delete or new/delete[] pairs.61bool CheckNewDeleteForms(InterpState &S, CodePtr OpPC,62 DynamicAllocator::Form AllocForm,63 DynamicAllocator::Form DeleteForm, const Descriptor *D,64 const Expr *NewExpr);65 66/// Copy the contents of Src into Dest.67bool DoMemcpy(InterpState &S, CodePtr OpPC, const Pointer &Src, Pointer &Dest);68 69template <typename T>70static bool handleOverflow(InterpState &S, CodePtr OpPC, const T &SrcValue) {71 const Expr *E = S.Current->getExpr(OpPC);72 S.CCEDiag(E, diag::note_constexpr_overflow) << SrcValue << E->getType();73 return S.noteUndefinedBehavior();74}75 76inline bool CheckArraySize(InterpState &S, CodePtr OpPC, uint64_t NumElems) {77 uint64_t Limit = S.getLangOpts().ConstexprStepLimit;78 if (Limit != 0 && NumElems > Limit) {79 S.FFDiag(S.Current->getSource(OpPC),80 diag::note_constexpr_new_exceeds_limits)81 << NumElems << Limit;82 return false;83 }84 return true;85}86 87static inline llvm::RoundingMode getRoundingMode(FPOptions FPO) {88 auto RM = FPO.getRoundingMode();89 if (RM == llvm::RoundingMode::Dynamic)90 return llvm::RoundingMode::NearestTiesToEven;91 return RM;92}93 94inline bool Invalid(InterpState &S, CodePtr OpPC) {95 const SourceLocation &Loc = S.Current->getLocation(OpPC);96 S.FFDiag(Loc, diag::note_invalid_subexpr_in_const_expr)97 << S.Current->getRange(OpPC);98 return false;99}100 101template <typename SizeT>102bool CheckArraySize(InterpState &S, CodePtr OpPC, SizeT *NumElements,103 unsigned ElemSize, bool IsNoThrow) {104 // FIXME: Both the SizeT::from() as well as the105 // NumElements.toAPSInt() in this function are rather expensive.106 107 // Can't be too many elements if the bitwidth of NumElements is lower than108 // that of Descriptor::MaxArrayElemBytes.109 if ((NumElements->bitWidth() - NumElements->isSigned()) <110 (sizeof(Descriptor::MaxArrayElemBytes) * 8))111 return true;112 113 // FIXME: GH63562114 // APValue stores array extents as unsigned,115 // so anything that is greater that unsigned would overflow when116 // constructing the array, we catch this here.117 SizeT MaxElements = SizeT::from(Descriptor::MaxArrayElemBytes / ElemSize);118 assert(MaxElements.isPositive());119 if (NumElements->toAPSInt().getActiveBits() >120 ConstantArrayType::getMaxSizeBits(S.getASTContext()) ||121 *NumElements > MaxElements) {122 if (!IsNoThrow) {123 const SourceInfo &Loc = S.Current->getSource(OpPC);124 125 if (NumElements->isSigned() && NumElements->isNegative()) {126 S.FFDiag(Loc, diag::note_constexpr_new_negative)127 << NumElements->toDiagnosticString(S.getASTContext());128 } else {129 S.FFDiag(Loc, diag::note_constexpr_new_too_large)130 << NumElements->toDiagnosticString(S.getASTContext());131 }132 }133 return false;134 }135 return true;136}137 138} // namespace interp139} // namespace clang140 141#endif // LLVM_CLANG_AST_INTERP_INTERPHELPERS_H142