clang 24.0.0git
InterpHelpers.h
Go to the documentation of this file.
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-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_CLANG_AST_INTERP_INTERPHELPERS_H
10#define LLVM_CLANG_AST_INTERP_INTERPHELPERS_H
11
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 Pointer &Ptr,
44 AccessKinds AK);
45bool diagnoseDummy(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
46 AccessKinds AK);
47
48bool arrayElemPtrOpaque(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
49 APSInt &&Index, bool AllowReplace = true);
50
51/// Checks if a pointer is in range.
52inline bool CheckRange(InterpState &S, CodePtr OpPC, PtrView Ptr,
53 AccessKinds AK) {
54 if (!Ptr.isOnePastEnd() && !Ptr.isZeroSizeArray())
55 return true;
56 if (S.getLangOpts().CPlusPlus)
57 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_past_end)
58 << AK << S.Current->getRange(OpPC);
59
60 return false;
61}
62inline bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
63 AccessKinds AK) {
64 if (!Ptr.isOnePastEnd() && !Ptr.isZeroSizeArray())
65 return true;
66 if (S.getLangOpts().CPlusPlus)
67 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_past_end)
68 << AK << S.Current->getRange(OpPC);
69
70 return false;
71}
72
73/// Checks if a field from which a pointer is going to be derived is valid.
74bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
76
77/// Checks if a pointer points to a mutable field.
78bool CheckMutable(InterpState &S, CodePtr OpPC, PtrView Ptr,
79 AccessKinds AK = AK_Read);
80inline bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
81 AccessKinds AK = AK_Read) {
82 if (!Ptr.isBlockPointer())
83 return true;
84 return CheckMutable(S, OpPC, Ptr.view(), AK);
85}
86
87/// Checks if a value can be loaded from a block.
88bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
89 AccessKinds AK = AK_Read);
90bool CheckLoad(InterpState &S, CodePtr OpPC, PtrView Ptr,
91 AccessKinds AK = AK_Read);
92
93/// Diagnose mismatched new[]/delete or new/delete[] pairs.
94bool CheckNewDeleteForms(InterpState &S, CodePtr OpPC,
95 DynamicAllocator::Form AllocForm,
96 DynamicAllocator::Form DeleteForm, const Descriptor *D,
97 const Expr *NewExpr);
98
99/// Copy the contents of Src into Dest.
100bool DoMemcpy(InterpState &S, CodePtr OpPC, const Pointer &Src, Pointer &Dest,
101 bool Activate = true, bool Diagnose = false);
102
104 unsigned Kind, Pointer &Ptr,
105 const Expr *E, bool IsDynamic = false);
106
107bool diagnoseUninitialized(InterpState &S, CodePtr OpPC, bool Extern,
108 const Block *B, Lifetime LT = Lifetime::Started,
109 AccessKinds AK = AK_Read);
110
111template <typename T>
112bool handleOverflow(InterpState &S, CodePtr OpPC, const T &SrcValue) {
113 const Expr *E = S.Current->getExpr(OpPC);
114 S.CCEDiag(E, diag::note_constexpr_overflow) << SrcValue << E->getType();
115 return S.noteUndefinedBehavior();
116}
117
118inline bool CheckArraySize(InterpState &S, CodePtr OpPC, uint64_t NumElems) {
119 // Descriptors store the number of elements as unsigned.
120 if (NumElems > std::numeric_limits<unsigned>::max()) {
121 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_new_too_large)
122 << NumElems;
123 return false;
124 }
125
126 uint64_t Limit = S.getLangOpts().ConstexprStepLimit;
127 if (Limit != 0 && NumElems > Limit) {
128 S.FFDiag(S.Current->getSource(OpPC),
129 diag::note_constexpr_new_exceeds_limits, 1)
130 << NumElems << Limit;
131 S.Note(S.Current->getSource(OpPC), diag::note_constexpr_steps);
132 return false;
133 }
134 return true;
135}
136
137static inline llvm::RoundingMode getRoundingMode(FPOptions FPO) {
138 auto RM = FPO.getRoundingMode();
139 if (RM == llvm::RoundingMode::Dynamic)
140 return llvm::RoundingMode::NearestTiesToEven;
141 return RM;
142}
143
144inline bool Invalid(InterpState &S, CodePtr OpPC) {
145 if (S.diagnosing())
146 S.FFDiag(S.Current->getSource(OpPC),
147 diag::note_invalid_subexpr_in_const_expr)
148 << S.Current->getRange(OpPC);
149 return false;
150}
151
152template <typename SizeT>
153bool CheckArraySize(InterpState &S, CodePtr OpPC, SizeT NumElements,
154 unsigned ElemSize, bool IsNoThrow) {
155
156 if (ElemSize == 0)
157 return true;
158
159 // FIXME: Both the SizeT::from() as well as the
160 // NumElements.toAPSInt() in this function are rather expensive.
161
162 // Can't be too many elements if the bitwidth of NumElements is lower than
163 // that of Descriptor::MaxArrayElemBytes.
164 if ((NumElements.bitWidth() - NumElements.isSigned()) <
165 (sizeof(Descriptor::MaxArrayElemBytes) * 8))
166 return true;
167
168 // FIXME: GH63562
169 // APValue stores array extents as unsigned,
170 // so anything that is greater that unsigned would overflow when
171 // constructing the array, we catch this here.
172 SizeT MaxElements = SizeT::from(Descriptor::MaxArrayElemBytes / ElemSize);
173 assert(MaxElements.isPositive());
174 if (NumElements.toAPSInt().getActiveBits() >
176 NumElements > MaxElements) {
177 if (!IsNoThrow) {
178 if (NumElements.isSigned() && NumElements.isNegative()) {
179 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_new_negative)
180 << NumElements.toDiagnosticString(S.getASTContext());
181 } else {
182 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_new_too_large)
183 << NumElements.toDiagnosticString(S.getASTContext());
184 }
185 }
186 return false;
187 }
188 return true;
189}
190
191} // namespace interp
192} // namespace clang
193
194#endif // LLVM_CLANG_AST_INTERP_INTERPHELPERS_H
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:239
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2987
static unsigned getMaxSizeBits(const ASTContext &Context)
Determine the maximum number of active bits that an array's size can require, which limits the maximu...
Definition Type.cpp:376
This represents one expression.
Definition Expr.h:113
QualType getType() const
Definition Expr.h:145
RoundingMode getRoundingMode() const
OffsetOfExpr - [C99 7.17] - This represents an expression of the form offsetof(record-type,...
Definition Expr.h:2571
A memory block, either on the stack or in the heap.
Definition InterpBlock.h:43
Pointer into the code segment.
Definition Source.h:31
SourceInfo getSource(CodePtr PC) const
Map a location to a source.
SourceRange getRange(CodePtr PC) const
const Expr * getExpr(CodePtr PC) const
Interpreter context.
Definition InterpState.h:47
InterpFrame * Current
The current frame.
A pointer to a memory block, live or dead.
Definition Pointer.h:546
OptionalDiagnostic Note(SourceLocation Loc, diag::kind DiagId)
Add a note to a prior diagnostic.
Definition State.cpp:86
OptionalDiagnostic FFDiag(SourceLocation Loc, diag::kind DiagId=diag::note_invalid_subexpr_in_const_expr, unsigned ExtraNotes=0)
Diagnose that the evaluation could not be folded (FF => FoldFailure)
Definition State.cpp:37
ASTContext & getASTContext() const
Definition State.h:90
bool noteUndefinedBehavior() const
Note that we hit something that was technically undefined behavior, but that we can evaluate past it ...
Definition State.h:115
OptionalDiagnostic CCEDiag(SourceLocation Loc, diag::kind DiagId=diag::note_invalid_subexpr_in_const_expr, unsigned ExtraNotes=0)
Diagnose that the evaluation does not produce a C++11 core constant expression.
Definition State.cpp:60
const LangOptions & getLangOpts() const
Definition State.h:91
bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr, CheckSubobjectKind CSK)
Checks if a field from which a pointer is going to be derived is valid.
Definition Interp.cpp:618
bool arrayElemPtrOpaque(InterpState &S, CodePtr OpPC, const Pointer &Ptr, APSInt &&Index, bool AllowReplace)
Definition Interp.cpp:3570
bool handleOverflow(InterpState &S, CodePtr OpPC, const T &SrcValue)
bool LT(InterpState &S, CodePtr OpPC)
Definition Interp.h:1526
bool CheckNewDeleteForms(InterpState &S, CodePtr OpPC, DynamicAllocator::Form AllocForm, DynamicAllocator::Form DeleteForm, const Descriptor *D, const Expr *NewExpr)
Diagnose mismatched new[]/delete or new/delete[] pairs.
Definition Interp.cpp:1369
static llvm::RoundingMode getRoundingMode(FPOptions FPO)
bool Call(InterpState &S, CodePtr OpPC, const Function *Func, uint32_t VarArgSize)
Definition Interp.cpp:2140
bool InterpretOffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E, ArrayRef< int64_t > ArrayIndices, int64_t &IntResult)
Interpret an offsetof operation.
bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a pointer is live and accessible.
Definition Interp.cpp:495
bool diagnoseUninitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Definition Interp.cpp:797
bool diagnoseDummy(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Definition Interp.cpp:1436
bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call, uint32_t BuiltinID)
Interpret a builtin function.
static bool Activate(InterpState &S)
Definition Interp.h:2309
bool DoMemcpy(InterpState &S, CodePtr OpPC, const Pointer &Src, Pointer &Dest, bool Activate, bool Diagnose)
Copy the contents of Src into Dest.
bool CheckArray(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if the array is offsetable.
Definition Interp.cpp:487
bool CheckDummy(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a pointer is a dummy pointer.
Definition Interp.cpp:1453
bool CheckMutable(InterpState &S, CodePtr OpPC, PtrView Ptr, AccessKinds AK)
Checks if a pointer points to a mutable field.
Definition Interp.cpp:723
bool CheckArraySize(InterpState &S, CodePtr OpPC, uint64_t NumElems)
bool CheckLoad(InterpState &S, CodePtr OpPC, PtrView Ptr, AccessKinds AK)
Definition Interp.cpp:960
UnsignedOrNone evaluateBuiltinObjectSize(const ASTContext &ASTCtx, unsigned Kind, Pointer &Ptr, const Expr *E, bool IsDynamic)
Evaluate __builtin_object_size or __builtin_dynamic_object_size for the given pointer and Kind.
bool Interpret(InterpState &S)
Interpreter entry point.
Definition Interp.cpp:3836
llvm::APSInt APSInt
Definition FixedPoint.h:20
Top level wrappers for InstallAPI frontend operations.
CheckSubobjectKind
The order of this enum is important for diagnostics.
Definition State.h:42
@ Result
The result type of a method or function.
Definition TypeBase.h:906
AccessKinds
Kinds of access we can perform on an object, for diagnostics.
Definition State.h:26
@ AK_Read
Definition State.h:27
OptionalUnsigned< unsigned > UnsignedOrNone
const FunctionProtoType * T
int32_t uint32_t
Describes a memory block created by an allocation site.
Definition Descriptor.h:122
static constexpr unsigned MaxArrayElemBytes
Maximum number of bytes to be used for array elements.
Definition Descriptor.h:142