23#include "llvm/ADT/APSInt.h"
33 llvm::report_fatal_error(
"Interpreter cannot return values");
46 if (S.Stk.pop<
bool>()) {
53 if (!S.Stk.pop<
bool>()) {
61 const SourceInfo &E = S.Current->getSource(OpPC);
62 S.FFDiag(E, diag::note_constexpr_var_init_unknown, 1) << VD;
70 const SourceInfo &E = S.Current->getSource(OpPC);
72 if (isa<ParmVarDecl>(D)) {
74 S.FFDiag(E, diag::note_constexpr_function_param_value_unknown) << D;
79 }
else if (
const auto *VD = dyn_cast<VarDecl>(D)) {
80 if (!VD->getType().isConstQualified()) {
86 if (!VD->getAnyInitializer()) {
99 const SourceInfo &Loc = S.Current->getSource(OpPC);
100 if (
const auto *VarD = dyn_cast<VarDecl>(VD);
101 VarD && VarD->getType().isConstQualified() &&
102 !VarD->getAnyInitializer()) {
108 S.FFDiag(Loc, diag::note_constexpr_ltor_non_const_int, 1) << VD;
114 S.
getLangOpts().CPlusPlus11 ? diag::note_constexpr_ltor_non_constexpr
115 : diag::note_constexpr_ltor_non_integral,
131 while (!
U.isActive()) {
136 const Record *R =
U.getRecord();
137 assert(R && R->
isUnion() &&
"Not a union");
139 for (
unsigned I = 0, N = R->
getNumFields(); I < N; ++I) {
141 if (Field.isActive()) {
142 ActiveField = Field.getField();
147 const SourceInfo &Loc = S.Current->getSource(OpPC);
148 S.FFDiag(Loc, diag::note_constexpr_access_inactive_union_member)
149 << AK << InactiveField << !ActiveField << ActiveField;
162 if (S.P.getCurrentDecl() == ID)
165 const SourceInfo &E = S.Current->getSource(OpPC);
166 S.FFDiag(E, diag::note_constexpr_access_static_temporary, 1) << AK;
167 S.Note(Ptr.
getDeclLoc(), diag::note_constexpr_temporary_here);
178 if (S.P.getCurrentDecl() == ID)
181 S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_modify_global);
196 const Function *CurFunc = S.Current->getFunction();
206 cast<CallExpr>(S.Current->Caller->getExpr(S.Current->getRetPC()));
207 for (int32_t I = CE->getNumArgs() - 1; I >= 0; --I) {
208 const Expr *A = CE->getArg(I);
214 if (S.Current->Caller && CurFunc->
isVariadic()) {
219 const Expr *
const *Args =
nullptr;
220 unsigned NumArgs = 0;
221 const Expr *CallSite = S.Current->Caller->getExpr(S.Current->getRetPC());
222 if (
const auto *CE = dyn_cast<CallExpr>(CallSite)) {
223 Args = CE->getArgs();
224 NumArgs = CE->getNumArgs();
225 }
else if (
const auto *CE = dyn_cast<CXXConstructExpr>(CallSite)) {
226 Args = CE->getArgs();
227 NumArgs = CE->getNumArgs();
229 assert(
false &&
"Can't get arguments from that expression type");
233 for (
unsigned I = 0; I != NumVarArgs; ++I) {
234 const Expr *A = Args[NumArgs - 1 - I];
241 S.Current->popArgs();
251 if (!S.checkingPotentialConstantExpression() && S.
getLangOpts().CPlusPlus) {
261 const SourceInfo &E = S.Current->getSource(OpPC);
262 S.FFDiag(E, diag::note_constexpr_unsized_array_indexed);
269 const auto &Src = S.Current->getSource(OpPC);
272 S.FFDiag(Src, diag::note_constexpr_null_subobject) <<
CSK_Field;
274 S.FFDiag(Src, diag::note_constexpr_access_null) << AK;
280 const auto &Src = S.Current->getSource(OpPC);
283 S.FFDiag(Src, diag::note_constexpr_lifetime_ended, 1) << AK << !IsTemp;
286 S.Note(Ptr.
getDeclLoc(), diag::note_constexpr_temporary_here);
288 S.Note(Ptr.
getDeclLoc(), diag::note_declared_at);
299 auto IsConstType = [&S](
const VarDecl *VD) ->
bool {
300 if (VD->isConstexpr())
307 if (
T.isConstQualified())
311 return RT->getPointeeType().isConstQualified();
314 return PT->getPointeeType().isConstQualified();
320 if (
const auto *VD = dyn_cast<VarDecl>(D);
321 VD && VD->hasGlobalStorage() && !IsConstType(VD)) {
323 return S.inConstantContext();
340 const SourceInfo &Loc = S.Current->getSource(OpPC);
341 S.FFDiag(Loc, diag::note_constexpr_null_subobject) << CSK;
349 const SourceInfo &Loc = S.Current->getSource(OpPC);
350 S.FFDiag(Loc, diag::note_constexpr_access_past_end) << AK;
358 const SourceInfo &Loc = S.Current->getSource(OpPC);
359 S.FFDiag(Loc, diag::note_constexpr_past_end_subobject) << CSK;
368 const SourceInfo &Loc = S.Current->getSource(OpPC);
369 S.FFDiag(Loc, diag::note_constexpr_past_end_subobject) << CSK;
374 assert(Ptr.
isLive() &&
"Pointer is not live");
381 Func && (
Func->isConstructor() ||
Func->isDestructor()) &&
382 Ptr.
block() == S.Current->getThis().block()) {
390 const SourceInfo &Loc = S.Current->getSource(OpPC);
391 S.FFDiag(Loc, diag::note_constexpr_modify_const_type) << Ty;
396 assert(Ptr.
isLive() &&
"Pointer is not live");
401 const SourceInfo &Loc = S.Current->getSource(OpPC);
403 S.FFDiag(Loc, diag::note_constexpr_access_mutable, 1) <<
AK_Read << Field;
404 S.Note(Field->getLocation(), diag::note_declared_at);
417 const SourceInfo &Loc = S.Current->getSource(OpPC);
418 if (VD->getAnyInitializer()) {
419 S.FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
420 S.Note(VD->getLocation(), diag::note_declared_at);
427 if (!S.checkingPotentialConstantExpression()) {
428 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_uninit)
429 << AK <<
true << S.Current->getRange(OpPC);
440 if ((!VD->hasConstantInitialization() &&
441 VD->mightBeUsableInConstantExpressions(S.getCtx())) ||
443 !VD->hasICEInitializer(S.getCtx()))) {
444 const SourceInfo &Loc = S.Current->getSource(OpPC);
445 S.FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
446 S.Note(VD->getLocation(), diag::note_declared_at);
512 S.CCEDiag(Loc, diag::note_constexpr_virtual_call);
527 const auto *CD = dyn_cast<CXXConstructorDecl>(DiagDecl);
528 if (CD && CD->isInheritingConstructor()) {
529 const auto *Inherited = CD->getInheritedConstructor().getConstructor();
530 if (!Inherited->isConstexpr())
531 DiagDecl = CD = Inherited;
537 if (CD && CD->isInheritingConstructor()) {
538 S.FFDiag(Loc, diag::note_constexpr_invalid_inhctor, 1)
539 << CD->getInheritedConstructor().getConstructor()->getParent();
540 S.Note(DiagDecl->
getLocation(), diag::note_declared_at);
546 if (!DiagDecl->
isDefined() && !IsExtern &&
547 S.checkingPotentialConstantExpression())
555 S.FFDiag(Loc, diag::note_constexpr_invalid_function, 1)
557 S.Note(DiagDecl->
getLocation(), diag::note_declared_at);
560 S.FFDiag(Loc, diag::note_invalid_subexpr_in_const_expr);
569 if ((S.Current->getDepth() + 1) > S.
getLangOpts().ConstexprCallDepth) {
570 S.FFDiag(S.Current->getSource(OpPC),
571 diag::note_constexpr_depth_limit_exceeded)
583 const SourceInfo &Loc = S.Current->getSource(OpPC);
585 bool IsImplicit =
false;
586 if (
const auto *E = dyn_cast_if_present<CXXThisExpr>(Loc.
asExpr()))
587 IsImplicit = E->isImplicit();
590 S.FFDiag(Loc, diag::note_constexpr_this) << IsImplicit;
600 const SourceInfo &E = S.Current->getSource(OpPC);
601 S.FFDiag(E, diag::note_constexpr_pure_virtual_call, 1) << MD;
607 APFloat::opStatus Status) {
608 const SourceInfo &E = S.Current->getSource(OpPC);
615 S.CCEDiag(E, diag::note_constexpr_float_arithmetic)
616 <<
true << S.Current->getRange(OpPC);
617 return S.noteUndefinedBehavior();
622 if (S.inConstantContext())
627 if ((Status & APFloat::opInexact) &&
631 S.FFDiag(E, diag::note_constexpr_dynamic_rounding);
635 if ((Status != APFloat::opOK) &&
638 FPO.getAllowFEnvAccess())) {
639 S.FFDiag(E, diag::note_constexpr_float_arithmetic_strict);
643 if ((Status & APFloat::opStatus::opInvalidOp) &&
673 const CallExpr *CE,
unsigned ArgSize) {
678 for (
const Expr *Arg : Args) {
679 if (NonNullArgs[Index] && Arg->getType()->isPointerType()) {
683 S.CCEDiag(Loc, diag::note_non_null_attribute_failed);
700 assert(!S.Current->isRoot());
701 CodePtr PC = S.Current->getPC();
713#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 void diagnoseNonConstVariable(InterpState &S, CodePtr OpPC, const ValueDecl *VD)
static bool RetValue(InterpState &S, CodePtr &Pt, APValue &Result)
static bool diagnoseUnknownDecl(InterpState &S, CodePtr OpPC, const ValueDecl *D)
static bool Jf(InterpState &S, CodePtr &PC, int32_t Offset)
static void diagnoseMissingInitializer(InterpState &S, CodePtr OpPC, const ValueDecl *VD)
#define TYPE_SWITCH(Expr, B)
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Represents a static or instance method of a struct/union/class.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Expr ** getArgs()
Retrieve the call arguments.
A reference to a declared variable, function, enum, etc.
bool isInvalidDecl() const
SourceLocation getLocation() const
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
This represents one expression.
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.
StorageClass getStorageClass() const
Returns the storage class as written in the source.
bool isConstexpr() const
Whether this is a (C++11) constexpr function or constexpr constructor.
bool isPureVirtual() const
Whether this virtual function is pure, i.e.
bool isDefined(const FunctionDecl *&Definition, bool CheckForPendingFriendDefinition=false) const
Returns true if the function has a definition that does not need to be instantiated.
@ FPE_Ignore
Assume that floating-point exceptions are masked.
PointerType - C99 6.7.5.1 - Pointer Declarators.
A (possibly-)qualified type.
bool isConstQualified() const
Determine whether this type is const-qualified.
Base for LValueReferenceType and RValueReferenceType.
const LangOptions & getLangOpts() const
Encodes a location in the source.
bool isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
bool isUnsignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is unsigned or an enumeration types whose underlying ...
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
const T * getAs() const
Member-template getAs<specific type>'.
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
Pointer into the code segment.
std::enable_if_t<!std::is_pointer< T >::value, T > read()
Reads data and advances the pointer.
const FunctionDecl * getDecl() const
Returns the original FunctionDecl.
bool isVirtual() const
Checks if the function is virtual.
bool isUnevaluatedBuiltin() const
bool isConstexpr() const
Checks if the function is valid to call in constexpr.
unsigned getNumWrittenParams() const
Returns the number of parameter this function takes when it's called, i.e excluding the instance poin...
Frame storing local variables.
A pointer to a memory block, live or dead.
bool isInitialized() const
Checks if an object was initialized.
bool isStatic() const
Checks if the storage is static.
bool isDummy() const
Checks if the pointer points to a dummy value.
bool isExtern() const
Checks if the storage is extern.
bool isActive() const
Checks if the object is active.
bool isConst() const
Checks if an object or a subfield is mutable.
bool isMutable() const
Checks if the field is mutable.
bool isUnknownSizeArray() const
Checks if the structure is an array of unknown size.
bool isIntegralPointer() const
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.
const Descriptor * getDeclDesc() const
Accessor for information about the declaration site.
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.
bool isBlockPointer() const
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.
unsigned getNumFields() 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 CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR)
We aleady know the given DeclRefExpr is invalid for some reason, now figure out why and print appropr...
bool CheckCallDepth(InterpState &S, CodePtr OpPC)
Checks if calling the currently active function would exceed the allowed call depth.
bool CheckThis(InterpState &S, CodePtr OpPC, const Pointer &This)
Checks the 'this' pointer.
bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc)
Checks if the Descriptor is of a constexpr or const global variable.
bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a pointer points to a mutable field.
bool CheckSubobject(InterpState &S, CodePtr OpPC, const Pointer &Ptr, CheckSubobjectKind CSK)
Checks if Ptr is a one-past-the-end pointer.
bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
constexpr size_t align(size_t Size)
Aligns a size to the pointer alignment.
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 CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a pointer is live and accessible.
static void popArg(InterpState &S, const Expr *Arg)
PrimType
Enumeration of the primitive types of the VM.
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 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.
bool CheckGlobalInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Check if a global variable is initialized.
bool CheckNonNullArgs(InterpState &S, CodePtr OpPC, const Function *F, const CallExpr *CE, unsigned ArgSize)
Checks if all the arguments annotated as 'nonnull' are in fact not null.
void cleanupAfterFunctionCall(InterpState &S, CodePtr OpPC)
llvm::BitVector collectNonNullArgs(const FunctionDecl *F, const llvm::ArrayRef< const Expr * > &Args)
size_t primSize(PrimType Type)
Returns the size of a primitive type in bytes.
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 CheckDummy(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a pointer is a dummy pointer.
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.
bool CheckFloatResult(InterpState &S, CodePtr OpPC, const Floating &Result, APFloat::opStatus Status)
Checks if the result of a floating-point operation is valid in the current context.
The JSON file list parser is used to communicate input to InstallAPI.
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 FunctionProtoType * T
Describes a memory block created by an allocation site.
const ValueDecl * asValueDecl() const
const VarDecl * asVarDecl() const