24 #include "llvm/ADT/APSInt.h"
28 using namespace clang;
30 using namespace clang;
34 llvm::report_fatal_error(
"Interpreter cannot return values");
47 if (S.Stk.pop<
bool>()) {
54 if (!S.Stk.pop<
bool>()) {
62 const SourceInfo &E = S.Current->getSource(OpPC);
63 S.FFDiag(E, diag::note_constexpr_var_init_unknown, 1) << VD;
71 const SourceInfo &E = S.Current->getSource(OpPC);
73 if (isa<ParmVarDecl>(D)) {
75 S.FFDiag(E, diag::note_constexpr_function_param_value_unknown) << D;
85 else if (
const auto *VD = dyn_cast<VarDecl>(D);
86 VD && !VD->getAnyInitializer())
98 if (
const auto *VarD = dyn_cast<VarDecl>(VD);
99 VarD && VarD->getType().isConstQualified() &&
100 !VarD->getAnyInitializer()) {
107 if (isa<ObjCIvarDecl>(VD))
111 S.FFDiag(
Loc, diag::note_constexpr_ltor_non_const_int, 1) << VD;
117 S.
getLangOpts().CPlusPlus11 ? diag::note_constexpr_ltor_non_constexpr
118 : diag::note_constexpr_ltor_non_integral,
134 while (!
U.isActive()) {
139 const Record *R =
U.getRecord();
140 assert(R && R->
isUnion() &&
"Not a union");
142 for (
unsigned I = 0, N = R->
getNumFields(); I < N; ++I) {
144 if (Field.isActive()) {
145 ActiveField = Field.getField();
151 S.FFDiag(
Loc, diag::note_constexpr_access_inactive_union_member)
152 << AK << InactiveField << !ActiveField << ActiveField;
165 if (S.P.getCurrentDecl() ==
ID)
168 const SourceInfo &E = S.Current->getSource(OpPC);
169 S.FFDiag(E, diag::note_constexpr_access_static_temporary, 1) << AK;
170 S.Note(Ptr.
getDeclLoc(), diag::note_constexpr_temporary_here);
181 if (S.P.getCurrentDecl() ==
ID)
184 S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_modify_global);
199 const Function *CurFunc = S.Current->getFunction();
209 cast<CallExpr>(S.Current->Caller->getExpr(S.Current->getRetPC()));
210 for (int32_t I = CE->getNumArgs() - 1; I >= 0; --I) {
211 const Expr *A = CE->getArg(I);
217 if (S.Current->Caller && CurFunc->
isVariadic()) {
222 const Expr *
const *Args =
nullptr;
223 unsigned NumArgs = 0;
224 const Expr *CallSite = S.Current->Caller->getExpr(S.Current->getRetPC());
225 if (
const auto *CE = dyn_cast<CallExpr>(CallSite)) {
226 Args = CE->getArgs();
227 NumArgs = CE->getNumArgs();
228 }
else if (
const auto *CE = dyn_cast<CXXConstructExpr>(CallSite)) {
229 Args = CE->getArgs();
230 NumArgs = CE->getNumArgs();
232 assert(
false &&
"Can't get arguments from that expression type");
236 for (
unsigned I = 0; I != NumVarArgs; ++I) {
237 const Expr *A = Args[NumArgs - 1 - I];
244 S.Current->popArgs();
254 if (!S.checkingPotentialConstantExpression() && S.
getLangOpts().CPlusPlus) {
264 const SourceInfo &E = S.Current->getSource(OpPC);
265 S.FFDiag(E, diag::note_constexpr_unsized_array_indexed);
272 const auto &Src = S.Current->getSource(OpPC);
275 S.FFDiag(Src, diag::note_constexpr_null_subobject) <<
CSK_Field;
277 S.FFDiag(Src, diag::note_constexpr_access_null) << AK;
283 const auto &Src = S.Current->getSource(OpPC);
286 S.FFDiag(Src, diag::note_constexpr_lifetime_ended, 1) << AK << !IsTemp;
289 S.Note(Ptr.
getDeclLoc(), diag::note_constexpr_temporary_here);
291 S.Note(Ptr.
getDeclLoc(), diag::note_declared_at);
302 auto IsConstType = [&S](
const VarDecl *VD) ->
bool {
303 if (VD->isConstexpr())
310 T.isConstQualified();
312 if (
T.isConstQualified())
319 return PT->getPointeeType().isConstQualified();
327 return S.inConstantContext();
344 S.FFDiag(
Loc, diag::note_constexpr_null_subobject) << CSK;
353 S.FFDiag(
Loc, diag::note_constexpr_access_past_end) << AK;
362 S.FFDiag(
Loc, diag::note_constexpr_past_end_subobject) << CSK;
372 S.FFDiag(
Loc, diag::note_constexpr_past_end_subobject) << CSK;
377 assert(Ptr.
isLive() &&
"Pointer is not live");
384 Func && (
Func->isConstructor() ||
Func->isDestructor()) &&
385 Ptr.
block() == S.Current->getThis().block()) {
394 S.FFDiag(
Loc, diag::note_constexpr_modify_const_type) << Ty;
399 assert(Ptr.
isLive() &&
"Pointer is not live");
406 S.FFDiag(
Loc, diag::note_constexpr_access_mutable, 1) <<
AK_Read << Field;
407 S.Note(Field->getLocation(), diag::note_declared_at);
421 if (VD->getAnyInitializer()) {
422 S.FFDiag(
Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
423 S.Note(VD->getLocation(), diag::note_declared_at);
430 if (!S.checkingPotentialConstantExpression()) {
431 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_uninit)
432 << AK <<
true << S.Current->getRange(OpPC);
443 if ((!VD->hasConstantInitialization() &&
444 VD->mightBeUsableInConstantExpressions(S.getCtx())) ||
446 !VD->hasICEInitializer(S.getCtx()))) {
448 S.FFDiag(
Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
449 S.Note(VD->getLocation(), diag::note_declared_at);
515 S.CCEDiag(
Loc, diag::note_constexpr_virtual_call);
530 const auto *CD = dyn_cast<CXXConstructorDecl>(DiagDecl);
531 if (CD && CD->isInheritingConstructor()) {
532 const auto *Inherited = CD->getInheritedConstructor().getConstructor();
533 if (!Inherited->isConstexpr())
534 DiagDecl = CD = Inherited;
540 if (CD && CD->isInheritingConstructor()) {
541 S.FFDiag(
Loc, diag::note_constexpr_invalid_inhctor, 1)
542 << CD->getInheritedConstructor().getConstructor()->getParent();
543 S.Note(DiagDecl->
getLocation(), diag::note_declared_at);
549 if (!DiagDecl->
isDefined() && !IsExtern &&
550 S.checkingPotentialConstantExpression())
558 S.FFDiag(
Loc, diag::note_constexpr_invalid_function, 1)
560 S.Note(DiagDecl->
getLocation(), diag::note_declared_at);
563 S.FFDiag(
Loc, diag::note_invalid_subexpr_in_const_expr);
572 if ((S.Current->getDepth() + 1) > S.
getLangOpts().ConstexprCallDepth) {
573 S.FFDiag(S.Current->getSource(OpPC),
574 diag::note_constexpr_depth_limit_exceeded)
588 bool IsImplicit =
false;
589 if (
const auto *E = dyn_cast_if_present<CXXThisExpr>(
Loc.asExpr()))
590 IsImplicit = E->isImplicit();
593 S.FFDiag(
Loc, diag::note_constexpr_this) << IsImplicit;
603 const SourceInfo &E = S.Current->getSource(OpPC);
604 S.FFDiag(E, diag::note_constexpr_pure_virtual_call, 1) << MD;
610 APFloat::opStatus Status) {
611 const SourceInfo &E = S.Current->getSource(OpPC);
617 if (Result.isNan()) {
618 S.CCEDiag(E, diag::note_constexpr_float_arithmetic)
619 <<
true << S.Current->getRange(OpPC);
620 return S.noteUndefinedBehavior();
625 if (S.inConstantContext())
630 if ((Status & APFloat::opInexact) &&
634 S.FFDiag(E, diag::note_constexpr_dynamic_rounding);
638 if ((Status != APFloat::opOK) &&
641 FPO.getAllowFEnvAccess())) {
642 S.FFDiag(E, diag::note_constexpr_float_arithmetic_strict);
646 if ((Status & APFloat::opStatus::opInvalidOp) &&
678 const SourceInfo &E = S.Current->getSource(OpPC);
679 S.FFDiag(E, diag::note_constexpr_modify_global);
685 const CallExpr *CE,
unsigned ArgSize) {
690 for (
const Expr *Arg : Args) {
691 if (NonNullArgs[Index] && Arg->getType()->isPointerType()) {
695 S.CCEDiag(
Loc, diag::note_non_null_attribute_failed);
712 assert(!S.Current->isRoot());
713 CodePtr PC = S.Current->getPC();
725 #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]).
Expr ** getArgs()
Retrieve the call arguments.
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
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 ...
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
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.
bool isVirtual() const
Checks if the function is virtual.
const FunctionDecl * getDecl() const
Returns the original FunctionDecl.
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.
const Descriptor * getDeclDesc() const
Accessor for information about the declaration site.
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.
bool isOnePastEnd() const
Checks if the index is one past end.
bool isElementPastEnd() const
Checks if the pointer is an out-of-bounds element pointer.
bool isBlockPointer() const
const Block * block() const
bool isTemporary() const
Checks if the storage is temporary.
std::optional< unsigned > getDeclID() const
Returns the declaration ID.
SourceLocation getDeclLoc() const
const FieldDecl * getField() const
Returns the field information.
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.
bool CheckDummy(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a pointer is a dummy pointer.
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 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.
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