24#include "llvm/ADT/APSInt.h"
30 llvm::report_fatal_error(
"Interpreter cannot return values");
43 if (S.Stk.pop<
bool>()) {
50 if (!S.Stk.pop<
bool>()) {
60 if (!S.checkingPotentialConstantExpression()) {
61 const SourceInfo &Loc = S.Current->getSource(OpPC);
62 S.FFDiag(Loc, diag::note_constexpr_access_uninit) << AK <<
false;
77 while (!
U.isActive()) {
83 assert(R && R->
isUnion() &&
"Not a union");
85 for (
unsigned I = 0, N = R->
getNumFields(); I < N; ++I) {
87 if (Field.isActive()) {
88 ActiveField = Field.getField();
93 const SourceInfo &Loc = S.Current->getSource(OpPC);
94 S.FFDiag(Loc, diag::note_constexpr_access_inactive_union_member)
95 << AK << InactiveField << !ActiveField << ActiveField;
108 if (S.P.getCurrentDecl() == ID)
111 const SourceInfo &E = S.Current->getSource(OpPC);
112 S.FFDiag(E, diag::note_constexpr_access_static_temporary, 1) << AK;
113 S.Note(Ptr.
getDeclLoc(), diag::note_constexpr_temporary_here);
124 if (S.P.getCurrentDecl() == ID)
127 S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_modify_global);
140 if (!S.checkingPotentialConstantExpression()) {
142 const SourceInfo &Loc = S.Current->getSource(OpPC);
143 S.FFDiag(Loc, diag::note_constexpr_ltor_non_constexpr, 1) << VD;
144 S.Note(VD->getLocation(), diag::note_declared_at);
152 const SourceInfo &E = S.Current->getSource(OpPC);
153 S.FFDiag(E, diag::note_constexpr_unsized_array_indexed);
160 const auto &Src = S.Current->getSource(OpPC);
163 S.FFDiag(Src, diag::note_constexpr_null_subobject) <<
CSK_Field;
165 S.FFDiag(Src, diag::note_constexpr_access_null) << AK;
171 const auto &Src = S.Current->getSource(OpPC);
174 S.FFDiag(Src, diag::note_constexpr_lifetime_ended, 1) << AK << !IsTemp;
177 S.Note(Ptr.
getDeclLoc(), diag::note_constexpr_temporary_here);
179 S.Note(Ptr.
getDeclLoc(), diag::note_declared_at);
191 const SourceInfo &Loc = S.Current->getSource(OpPC);
192 S.FFDiag(Loc, diag::note_constexpr_null_subobject) << CSK;
200 const SourceInfo &Loc = S.Current->getSource(OpPC);
201 S.FFDiag(Loc, diag::note_constexpr_access_past_end) << AK;
209 const SourceInfo &Loc = S.Current->getSource(OpPC);
210 S.FFDiag(Loc, diag::note_constexpr_past_end_subobject) << CSK;
215 assert(Ptr.
isLive() &&
"Pointer is not live");
221 if (
const Function *Func = S.Current->getFunction();
222 Func && (Func->isConstructor() || Func->isDestructor()) &&
223 Ptr.
block() == S.Current->getThis().block()) {
228 const SourceInfo &Loc = S.Current->getSource(OpPC);
229 S.FFDiag(Loc, diag::note_constexpr_modify_const_type) << Ty;
234 assert(Ptr.
isLive() &&
"Pointer is not live");
239 const SourceInfo &Loc = S.Current->getSource(OpPC);
241 S.FFDiag(Loc, diag::note_constexpr_access_mutable, 1) <<
AK_Read << Field;
242 S.Note(Field->getLocation(), diag::note_declared_at);
301 S.CCEDiag(Loc, diag::note_constexpr_virtual_call);
309 if (S.checkingPotentialConstantExpression())
318 auto *CD = dyn_cast<CXXConstructorDecl>(DiagDecl);
319 if (CD && CD->isInheritingConstructor()) {
320 auto *Inherited = CD->getInheritedConstructor().getConstructor();
321 if (!Inherited->isConstexpr())
322 DiagDecl = CD = Inherited;
328 if (CD && CD->isInheritingConstructor())
329 S.FFDiag(Loc, diag::note_constexpr_invalid_inhctor, 1)
330 << CD->getInheritedConstructor().getConstructor()->getParent();
332 S.FFDiag(Loc, diag::note_constexpr_invalid_function, 1)
334 S.Note(DiagDecl->
getLocation(), diag::note_declared_at);
336 S.FFDiag(Loc, diag::note_invalid_subexpr_in_const_expr);
348 const SourceInfo &Loc = S.Current->getSource(OpPC);
350 bool IsImplicit =
false;
351 if (
auto *E = dyn_cast_if_present<CXXThisExpr>(Loc.
asExpr()))
352 IsImplicit = E->isImplicit();
355 S.FFDiag(Loc, diag::note_constexpr_this) << IsImplicit;
365 const SourceInfo &E = S.Current->getSource(OpPC);
366 S.FFDiag(E, diag::note_constexpr_pure_virtual_call, 1) << MD;
373 assert(SubObjDecl &&
"Subobject declaration does not exist");
374 S.FFDiag(SI, diag::note_constexpr_uninitialized) << SubObjDecl;
376 diag::note_constexpr_subobject_declared_here);
386 size_t NumElems = CAT->
getSize().getZExtValue();
391 for (
size_t I = 0; I != NumElems; ++I) {
395 }
else if (
auto *ElemCAT = dyn_cast<ConstantArrayType>(ElemType)) {
396 for (
size_t I = 0; I != NumElems; ++I) {
401 for (
size_t I = 0; I != NumElems; ++I) {
420 QualType FieldType = F.Decl->getType();
446 assert(!
This.isZero());
454 if (S.inConstantContext())
457 const SourceInfo &E = S.Current->getSource(OpPC);
460 if ((Status & APFloat::opInexact) &&
464 S.FFDiag(E, diag::note_constexpr_dynamic_rounding);
468 if ((Status != APFloat::opOK) &&
471 FPO.getAllowFEnvAccess())) {
472 S.FFDiag(E, diag::note_constexpr_float_arithmetic_strict);
476 if ((Status & APFloat::opStatus::opInvalidOp) &&
487 llvm::RoundingMode RM) {
500 assert(!S.Current->isRoot());
501 CodePtr PC = S.Current->getPC();
513#include "Opcodes.inc"
Defines the clang::ASTContext interface.
Defines the clang::Expr interface and subclasses for C++ expressions.
static bool Jmp(InterpState &S, CodePtr &PC, int32_t Offset)
static bool CheckActive(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
static bool CheckGlobal(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
static bool CheckTemporary(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
static bool Jt(InterpState &S, CodePtr &PC, int32_t Offset)
static bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
static bool RetValue(InterpState &S, CodePtr &Pt, APValue &Result)
static bool Jf(InterpState &S, CodePtr &PC, int32_t Offset)
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
QualType getElementType() const
Represents a static or instance method of a struct/union/class.
Represents the canonical version of C arrays with a specified constant size.
const llvm::APInt & getSize() const
SourceLocation getLocation() const
FPOptions getFPFeaturesInEffect(const LangOptions &LO) const
Returns the set of floating point options that apply to this expression.
LangOptions::FPExceptionModeKind getExceptionMode() const
RoundingMode getRoundingMode() const
Represents a member of a struct/union/class.
Represents a function declaration or definition.
bool isPure() const
Whether this virtual function is pure, i.e.
bool isConstexpr() const
Whether this is a (C++11) constexpr function or constexpr constructor.
@ FPE_Ignore
Assume that floating-point exceptions are masked.
A (possibly-)qualified type.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
bool isConstQualified() const
Determine whether this type is const-qualified.
const LangOptions & getLangOpts() const
Encodes a location in the source.
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
bool isRecordType() const
Pointer into the code segment.
std::enable_if_t<!std::is_pointer< T >::value, T > read()
Reads data and advances the pointer.
Floating toSemantics(const llvm::fltSemantics *Sem, llvm::RoundingMode RM) const
const FunctionDecl * getDecl() const
Returns the original FunctionDecl.
bool isVirtual() const
Checks if the function is virtual.
bool isConstexpr() const
Checks if the function is valid to call in constexpr.
Frame storing local variables.
A pointer to a memory block, live or dead.
Pointer narrow() const
Restricts the scope of an array element pointer.
bool isInitialized() const
Checks if an object was initialized.
bool isStatic() const
Checks if the storage is static.
bool isExtern() const
Checks if the storage is extern.
Pointer atIndex(unsigned Idx) const
Offsets a pointer inside an array.
bool isActive() const
Checks if the object is active.
bool isConst() const
Checks if an object or a subfield is mutable.
Pointer atField(unsigned Off) const
Creates a pointer to a field.
bool isMutable() const
Checks if the field is mutable.
bool isUnknownSizeArray() const
Checks if the structure is an array of unknown size.
QualType getType() const
Returns the type of the innermost field.
bool isLive() const
Checks if the pointer is live.
bool isStaticTemporary() const
Checks if the storage is a static temporary.
Pointer getBase() const
Returns a pointer to the object of which this pointer is a field.
bool isZero() const
Checks if the pointer is null.
Descriptor * getDeclDesc() const
Accessor for information about the declaration site.
Record * getElemRecord() const
bool isOnePastEnd() const
Checks if the index is one past end.
const FieldDecl * getField() const
Returns the field information.
bool isElementPastEnd() const
Checks if the pointer is an out-of-bounds element pointer.
Record * getRecord() const
Returns the record descriptor of a class.
bool isTemporary() const
Checks if the storage is temporary.
SourceLocation getDeclLoc() const
const Block * block() const
std::optional< unsigned > getDeclID() const
Returns the declaration ID.
bool isField() const
Checks if the item is a field in an object.
Structure/Class descriptor.
bool isUnion() const
Checks if the record is a union.
const Field * getField(const FieldDecl *FD) const
Returns a field.
llvm::iterator_range< const_base_iter > bases() const
unsigned getNumFields() const
llvm::iterator_range< const_field_iter > fields() const
Describes the statement/declaration an opcode was generated from.
const Expr * asExpr() const
bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a value can be initialized.
bool Interpret(InterpState &S, APValue &Result)
Interpreter entry point.
bool CheckThis(InterpState &S, CodePtr OpPC, const Pointer &This)
Checks the 'this' pointer.
bool CheckCtorCall(InterpState &S, CodePtr OpPC, const Pointer &This)
Checks that all fields are initialized after a constructor call.
bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a pointer points to a mutable field.
bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a pointer is in range.
bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD)
Checks if a method is pure virtual.
bool This(InterpState &S, CodePtr OpPC)
bool CheckFloatResult(InterpState &S, CodePtr OpPC, APFloat::opStatus Status)
Checks if the result is a floating-point operation is valid in the current context.
bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a pointer is live and accessible.
bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a value can be stored in a block.
bool CheckNull(InterpState &S, CodePtr OpPC, const Pointer &Ptr, CheckSubobjectKind CSK)
Checks if a pointer is null.
bool CastFP(InterpState &S, CodePtr OpPC, const llvm::fltSemantics *Sem, llvm::RoundingMode RM)
1) Pops a Floating from the stack.
bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a value can be loaded from a block.
bool CheckArray(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if the array is offsetable.
static bool CheckFieldsInitialized(InterpState &S, CodePtr OpPC, const Pointer &BasePtr, const Record *R)
static void DiagnoseUninitializedSubobject(InterpState &S, const SourceInfo &SI, const FieldDecl *SubObjDecl)
static bool CheckArrayInitialized(InterpState &S, CodePtr OpPC, const Pointer &BasePtr, const ConstantArrayType *CAT)
bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if the variable has externally defined storage.
bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F)
Checks if a method can be called.
bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a pointer points to const storage.
bool CheckInvoke(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a method can be invoked on an object.
CheckSubobjectKind
The order of this enum is important for diagnostics.
@ Result
The result type of a method or function.
AccessKinds
Kinds of access we can perform on an object, for diagnostics.
const ValueDecl * asValueDecl() const
Describes a record field.