1 //===------- Interp.cpp - Interpreter for the constexpr VM ------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
13 #include "InterpFrame.h"
14 #include "InterpStack.h"
19 #include "clang/AST/ASTContext.h"
20 #include "clang/AST/ASTDiagnostic.h"
21 #include "clang/AST/CXXInheritance.h"
22 #include "clang/AST/Expr.h"
23 #include "clang/AST/ExprCXX.h"
24 #include "llvm/ADT/APSInt.h"
26 using namespace clang
;
27 using namespace clang::interp
;
29 static bool RetValue(InterpState
&S
, CodePtr
&Pt
, APValue
&Result
) {
30 llvm::report_fatal_error("Interpreter cannot return values");
33 //===----------------------------------------------------------------------===//
35 //===----------------------------------------------------------------------===//
37 static bool Jmp(InterpState
&S
, CodePtr
&PC
, int32_t Offset
) {
42 static bool Jt(InterpState
&S
, CodePtr
&PC
, int32_t Offset
) {
43 if (S
.Stk
.pop
<bool>()) {
49 static bool Jf(InterpState
&S
, CodePtr
&PC
, int32_t Offset
) {
50 if (!S
.Stk
.pop
<bool>()) {
56 static bool CheckActive(InterpState
&S
, CodePtr OpPC
, const Pointer
&Ptr
,
61 // Get the inactive field descriptor.
62 const FieldDecl
*InactiveField
= Ptr
.getField();
64 // Walk up the pointer chain to find the union which is not active.
65 Pointer U
= Ptr
.getBase();
66 while (!U
.isActive()) {
70 // Find the active field of the union.
71 const Record
*R
= U
.getRecord();
72 assert(R
&& R
->isUnion() && "Not a union");
73 const FieldDecl
*ActiveField
= nullptr;
74 for (unsigned I
= 0, N
= R
->getNumFields(); I
< N
; ++I
) {
75 const Pointer
&Field
= U
.atField(R
->getField(I
)->Offset
);
76 if (Field
.isActive()) {
77 ActiveField
= Field
.getField();
82 const SourceInfo
&Loc
= S
.Current
->getSource(OpPC
);
83 S
.FFDiag(Loc
, diag::note_constexpr_access_inactive_union_member
)
84 << AK
<< InactiveField
<< !ActiveField
<< ActiveField
;
88 static bool CheckTemporary(InterpState
&S
, CodePtr OpPC
, const Pointer
&Ptr
,
90 if (auto ID
= Ptr
.getDeclID()) {
91 if (!Ptr
.isStaticTemporary())
94 if (Ptr
.getDeclDesc()->getType().isConstQualified())
97 if (S
.P
.getCurrentDecl() == ID
)
100 const SourceInfo
&E
= S
.Current
->getSource(OpPC
);
101 S
.FFDiag(E
, diag::note_constexpr_access_static_temporary
, 1) << AK
;
102 S
.Note(Ptr
.getDeclLoc(), diag::note_constexpr_temporary_here
);
108 static bool CheckGlobal(InterpState
&S
, CodePtr OpPC
, const Pointer
&Ptr
) {
109 if (auto ID
= Ptr
.getDeclID()) {
113 if (S
.P
.getCurrentDecl() == ID
)
116 S
.FFDiag(S
.Current
->getLocation(OpPC
), diag::note_constexpr_modify_global
);
124 static void popArg(InterpState
&S
, const Expr
*Arg
) {
125 PrimType Ty
= S
.getContext().classify(Arg
->getType()).value_or(PT_Ptr
);
126 TYPE_SWITCH(Ty
, S
.Stk
.discard
<T
>());
129 void cleanupAfterFunctionCall(InterpState
&S
, CodePtr OpPC
) {
131 const Function
*CurFunc
= S
.Current
->getFunction();
134 // Certain builtin functions are declared as func-name(...), so the
135 // parameters are checked in Sema and only available through the CallExpr.
136 // The interp::Function we create for them has 0 parameters, so we need to
137 // remove them from the stack by checking the CallExpr.
138 // FIXME: This is potentially just a special case and could be handled more
139 // generally with the code just below?
140 if (CurFunc
->needsRuntimeArgPop(S
.getCtx())) {
141 const auto *CE
= cast
<CallExpr
>(S
.Current
->getExpr(OpPC
));
142 for (int32_t I
= CE
->getNumArgs() - 1; I
>= 0; --I
) {
143 popArg(S
, CE
->getArg(I
));
148 if (S
.Current
->Caller
&& CurFunc
->isVariadic()) {
149 // CallExpr we're look for is at the return PC of the current function, i.e.
151 // This code path should be executed very rarely.
153 cast
<CallExpr
>(S
.Current
->Caller
->getExpr(S
.Current
->getRetPC()));
154 unsigned FixedParams
= CurFunc
->getNumParams();
155 int32_t ArgsToPop
= CE
->getNumArgs() - FixedParams
;
156 assert(ArgsToPop
>= 0);
157 for (int32_t I
= ArgsToPop
- 1; I
>= 0; --I
) {
158 const Expr
*A
= CE
->getArg(FixedParams
+ I
);
162 // And in any case, remove the fixed parameters (the non-variadic ones)
164 S
.Current
->popArgs();
167 bool CheckExtern(InterpState
&S
, CodePtr OpPC
, const Pointer
&Ptr
) {
171 if (!S
.checkingPotentialConstantExpression() && S
.getLangOpts().CPlusPlus
) {
172 const auto *VD
= Ptr
.getDeclDesc()->asValueDecl();
173 const SourceInfo
&Loc
= S
.Current
->getSource(OpPC
);
174 S
.FFDiag(Loc
, diag::note_constexpr_ltor_non_constexpr
, 1) << VD
;
175 S
.Note(VD
->getLocation(), diag::note_declared_at
);
180 bool CheckArray(InterpState
&S
, CodePtr OpPC
, const Pointer
&Ptr
) {
181 if (!Ptr
.isUnknownSizeArray())
183 const SourceInfo
&E
= S
.Current
->getSource(OpPC
);
184 S
.FFDiag(E
, diag::note_constexpr_unsized_array_indexed
);
188 bool CheckLive(InterpState
&S
, CodePtr OpPC
, const Pointer
&Ptr
,
191 const auto &Src
= S
.Current
->getSource(OpPC
);
194 S
.FFDiag(Src
, diag::note_constexpr_null_subobject
) << CSK_Field
;
196 S
.FFDiag(Src
, diag::note_constexpr_access_null
) << AK
;
202 const auto &Src
= S
.Current
->getSource(OpPC
);
203 bool IsTemp
= Ptr
.isTemporary();
205 S
.FFDiag(Src
, diag::note_constexpr_lifetime_ended
, 1) << AK
<< !IsTemp
;
208 S
.Note(Ptr
.getDeclLoc(), diag::note_constexpr_temporary_here
);
210 S
.Note(Ptr
.getDeclLoc(), diag::note_declared_at
);
218 bool CheckDummy(InterpState
&S
, CodePtr OpPC
, const Pointer
&Ptr
) {
219 return !Ptr
.isZero() && !Ptr
.isDummy();
222 bool CheckNull(InterpState
&S
, CodePtr OpPC
, const Pointer
&Ptr
,
223 CheckSubobjectKind CSK
) {
226 const SourceInfo
&Loc
= S
.Current
->getSource(OpPC
);
227 S
.FFDiag(Loc
, diag::note_constexpr_null_subobject
) << CSK
;
231 bool CheckRange(InterpState
&S
, CodePtr OpPC
, const Pointer
&Ptr
,
233 if (!Ptr
.isOnePastEnd())
235 const SourceInfo
&Loc
= S
.Current
->getSource(OpPC
);
236 S
.FFDiag(Loc
, diag::note_constexpr_access_past_end
) << AK
;
240 bool CheckRange(InterpState
&S
, CodePtr OpPC
, const Pointer
&Ptr
,
241 CheckSubobjectKind CSK
) {
242 if (!Ptr
.isElementPastEnd())
244 const SourceInfo
&Loc
= S
.Current
->getSource(OpPC
);
245 S
.FFDiag(Loc
, diag::note_constexpr_past_end_subobject
) << CSK
;
249 bool CheckSubobject(InterpState
&S
, CodePtr OpPC
, const Pointer
&Ptr
,
250 CheckSubobjectKind CSK
) {
251 if (!Ptr
.isOnePastEnd())
254 const SourceInfo
&Loc
= S
.Current
->getSource(OpPC
);
255 S
.FFDiag(Loc
, diag::note_constexpr_past_end_subobject
) << CSK
;
259 bool CheckConst(InterpState
&S
, CodePtr OpPC
, const Pointer
&Ptr
) {
260 assert(Ptr
.isLive() && "Pointer is not live");
264 // The This pointer is writable in constructors and destructors,
265 // even if isConst() returns true.
266 if (const Function
*Func
= S
.Current
->getFunction();
267 Func
&& (Func
->isConstructor() || Func
->isDestructor()) &&
268 Ptr
.block() == S
.Current
->getThis().block()) {
272 const QualType Ty
= Ptr
.getType();
273 const SourceInfo
&Loc
= S
.Current
->getSource(OpPC
);
274 S
.FFDiag(Loc
, diag::note_constexpr_modify_const_type
) << Ty
;
278 bool CheckMutable(InterpState
&S
, CodePtr OpPC
, const Pointer
&Ptr
) {
279 assert(Ptr
.isLive() && "Pointer is not live");
280 if (!Ptr
.isMutable()) {
284 const SourceInfo
&Loc
= S
.Current
->getSource(OpPC
);
285 const FieldDecl
*Field
= Ptr
.getField();
286 S
.FFDiag(Loc
, diag::note_constexpr_access_mutable
, 1) << AK_Read
<< Field
;
287 S
.Note(Field
->getLocation(), diag::note_declared_at
);
291 bool CheckInitialized(InterpState
&S
, CodePtr OpPC
, const Pointer
&Ptr
,
293 if (Ptr
.isInitialized())
296 if (!S
.checkingPotentialConstantExpression()) {
297 S
.FFDiag(S
.Current
->getSource(OpPC
), diag::note_constexpr_access_uninit
)
298 << AK
<< /*uninitialized=*/true << S
.Current
->getRange(OpPC
);
303 bool CheckLoad(InterpState
&S
, CodePtr OpPC
, const Pointer
&Ptr
) {
304 if (!CheckDummy(S
, OpPC
, Ptr
))
306 if (!CheckLive(S
, OpPC
, Ptr
, AK_Read
))
308 if (!CheckExtern(S
, OpPC
, Ptr
))
310 if (!CheckRange(S
, OpPC
, Ptr
, AK_Read
))
312 if (!CheckInitialized(S
, OpPC
, Ptr
, AK_Read
))
314 if (!CheckActive(S
, OpPC
, Ptr
, AK_Read
))
316 if (!CheckTemporary(S
, OpPC
, Ptr
, AK_Read
))
318 if (!CheckMutable(S
, OpPC
, Ptr
))
323 bool CheckStore(InterpState
&S
, CodePtr OpPC
, const Pointer
&Ptr
) {
324 if (!CheckLive(S
, OpPC
, Ptr
, AK_Assign
))
326 if (!CheckExtern(S
, OpPC
, Ptr
))
328 if (!CheckRange(S
, OpPC
, Ptr
, AK_Assign
))
330 if (!CheckGlobal(S
, OpPC
, Ptr
))
332 if (!CheckConst(S
, OpPC
, Ptr
))
337 bool CheckInvoke(InterpState
&S
, CodePtr OpPC
, const Pointer
&Ptr
) {
338 if (!CheckLive(S
, OpPC
, Ptr
, AK_MemberCall
))
340 if (!CheckExtern(S
, OpPC
, Ptr
))
342 if (!CheckRange(S
, OpPC
, Ptr
, AK_MemberCall
))
347 bool CheckInit(InterpState
&S
, CodePtr OpPC
, const Pointer
&Ptr
) {
348 if (!CheckLive(S
, OpPC
, Ptr
, AK_Assign
))
350 if (!CheckRange(S
, OpPC
, Ptr
, AK_Assign
))
355 bool CheckCallable(InterpState
&S
, CodePtr OpPC
, const Function
*F
) {
357 if (F
->isVirtual() && !S
.getLangOpts().CPlusPlus20
) {
358 const SourceLocation
&Loc
= S
.Current
->getLocation(OpPC
);
359 S
.CCEDiag(Loc
, diag::note_constexpr_virtual_call
);
363 if (!F
->isConstexpr()) {
364 // Don't emit anything if we're checking for a potential constant
365 // expression. That will happen later when actually executing.
366 if (S
.checkingPotentialConstantExpression())
369 const SourceLocation
&Loc
= S
.Current
->getLocation(OpPC
);
370 if (S
.getLangOpts().CPlusPlus11
) {
371 const FunctionDecl
*DiagDecl
= F
->getDecl();
373 // If this function is not constexpr because it is an inherited
374 // non-constexpr constructor, diagnose that directly.
375 const auto *CD
= dyn_cast
<CXXConstructorDecl
>(DiagDecl
);
376 if (CD
&& CD
->isInheritingConstructor()) {
377 const auto *Inherited
= CD
->getInheritedConstructor().getConstructor();
378 if (!Inherited
->isConstexpr())
379 DiagDecl
= CD
= Inherited
;
382 // FIXME: If DiagDecl is an implicitly-declared special member function
383 // or an inheriting constructor, we should be much more explicit about why
384 // it's not constexpr.
385 if (CD
&& CD
->isInheritingConstructor())
386 S
.FFDiag(Loc
, diag::note_constexpr_invalid_inhctor
, 1)
387 << CD
->getInheritedConstructor().getConstructor()->getParent();
389 S
.FFDiag(Loc
, diag::note_constexpr_invalid_function
, 1)
390 << DiagDecl
->isConstexpr() << (bool)CD
<< DiagDecl
;
391 S
.Note(DiagDecl
->getLocation(), diag::note_declared_at
);
393 S
.FFDiag(Loc
, diag::note_invalid_subexpr_in_const_expr
);
401 bool CheckCallDepth(InterpState
&S
, CodePtr OpPC
) {
402 if ((S
.Current
->getDepth() + 1) > S
.getLangOpts().ConstexprCallDepth
) {
403 S
.FFDiag(S
.Current
->getSource(OpPC
),
404 diag::note_constexpr_depth_limit_exceeded
)
405 << S
.getLangOpts().ConstexprCallDepth
;
412 bool CheckThis(InterpState
&S
, CodePtr OpPC
, const Pointer
&This
) {
416 const SourceInfo
&Loc
= S
.Current
->getSource(OpPC
);
418 bool IsImplicit
= false;
419 if (const auto *E
= dyn_cast_if_present
<CXXThisExpr
>(Loc
.asExpr()))
420 IsImplicit
= E
->isImplicit();
422 if (S
.getLangOpts().CPlusPlus11
)
423 S
.FFDiag(Loc
, diag::note_constexpr_this
) << IsImplicit
;
430 bool CheckPure(InterpState
&S
, CodePtr OpPC
, const CXXMethodDecl
*MD
) {
433 const SourceInfo
&E
= S
.Current
->getSource(OpPC
);
434 S
.FFDiag(E
, diag::note_constexpr_pure_virtual_call
, 1) << MD
;
435 S
.Note(MD
->getLocation(), diag::note_declared_at
);
439 static void DiagnoseUninitializedSubobject(InterpState
&S
, const SourceInfo
&SI
,
440 const FieldDecl
*SubObjDecl
) {
441 assert(SubObjDecl
&& "Subobject declaration does not exist");
442 S
.FFDiag(SI
, diag::note_constexpr_uninitialized
)
443 << /*(name)*/ 1 << SubObjDecl
;
444 S
.Note(SubObjDecl
->getLocation(),
445 diag::note_constexpr_subobject_declared_here
);
448 static bool CheckFieldsInitialized(InterpState
&S
, CodePtr OpPC
,
449 const Pointer
&BasePtr
, const Record
*R
);
451 static bool CheckArrayInitialized(InterpState
&S
, CodePtr OpPC
,
452 const Pointer
&BasePtr
,
453 const ConstantArrayType
*CAT
) {
455 size_t NumElems
= CAT
->getSize().getZExtValue();
456 QualType ElemType
= CAT
->getElementType();
458 if (ElemType
->isRecordType()) {
459 const Record
*R
= BasePtr
.getElemRecord();
460 for (size_t I
= 0; I
!= NumElems
; ++I
) {
461 Pointer ElemPtr
= BasePtr
.atIndex(I
).narrow();
462 Result
&= CheckFieldsInitialized(S
, OpPC
, ElemPtr
, R
);
464 } else if (const auto *ElemCAT
= dyn_cast
<ConstantArrayType
>(ElemType
)) {
465 for (size_t I
= 0; I
!= NumElems
; ++I
) {
466 Pointer ElemPtr
= BasePtr
.atIndex(I
).narrow();
467 Result
&= CheckArrayInitialized(S
, OpPC
, ElemPtr
, ElemCAT
);
470 for (size_t I
= 0; I
!= NumElems
; ++I
) {
471 if (!BasePtr
.atIndex(I
).isInitialized()) {
472 DiagnoseUninitializedSubobject(S
, S
.Current
->getSource(OpPC
),
482 static bool CheckFieldsInitialized(InterpState
&S
, CodePtr OpPC
,
483 const Pointer
&BasePtr
, const Record
*R
) {
486 // Check all fields of this record are initialized.
487 for (const Record::Field
&F
: R
->fields()) {
488 Pointer FieldPtr
= BasePtr
.atField(F
.Offset
);
489 QualType FieldType
= F
.Decl
->getType();
491 if (FieldType
->isRecordType()) {
492 Result
&= CheckFieldsInitialized(S
, OpPC
, FieldPtr
, FieldPtr
.getRecord());
493 } else if (FieldType
->isIncompleteArrayType()) {
494 // Nothing to do here.
495 } else if (FieldType
->isArrayType()) {
497 cast
<ConstantArrayType
>(FieldType
->getAsArrayTypeUnsafe());
498 Result
&= CheckArrayInitialized(S
, OpPC
, FieldPtr
, CAT
);
499 } else if (!FieldPtr
.isInitialized()) {
500 DiagnoseUninitializedSubobject(S
, S
.Current
->getSource(OpPC
), F
.Decl
);
505 // Check Fields in all bases
506 for (const Record::Base
&B
: R
->bases()) {
507 Pointer P
= BasePtr
.atField(B
.Offset
);
508 if (!P
.isInitialized()) {
509 S
.FFDiag(BasePtr
.getDeclDesc()->asDecl()->getLocation(),
510 diag::note_constexpr_uninitialized_base
)
511 << B
.Desc
->getType();
514 Result
&= CheckFieldsInitialized(S
, OpPC
, P
, B
.R
);
517 // TODO: Virtual bases
522 bool CheckCtorCall(InterpState
&S
, CodePtr OpPC
, const Pointer
&This
) {
523 assert(!This
.isZero());
524 if (const Record
*R
= This
.getRecord())
525 return CheckFieldsInitialized(S
, OpPC
, This
, R
);
527 cast
<ConstantArrayType
>(This
.getType()->getAsArrayTypeUnsafe());
528 return CheckArrayInitialized(S
, OpPC
, This
, CAT
);
531 bool CheckPotentialReinterpretCast(InterpState
&S
, CodePtr OpPC
,
532 const Pointer
&Ptr
) {
533 if (!S
.inConstantContext())
536 const SourceInfo
&E
= S
.Current
->getSource(OpPC
);
537 S
.CCEDiag(E
, diag::note_constexpr_invalid_cast
)
538 << 2 << S
.getLangOpts().CPlusPlus
<< S
.Current
->getRange(OpPC
);
542 bool CheckFloatResult(InterpState
&S
, CodePtr OpPC
, const Floating
&Result
,
543 APFloat::opStatus Status
) {
544 const SourceInfo
&E
= S
.Current
->getSource(OpPC
);
547 // If during the evaluation of an expression, the result is not
548 // mathematically defined [...], the behavior is undefined.
549 // FIXME: C++ rules require us to not conform to IEEE 754 here.
550 if (Result
.isNan()) {
551 S
.CCEDiag(E
, diag::note_constexpr_float_arithmetic
)
552 << /*NaN=*/true << S
.Current
->getRange(OpPC
);
553 return S
.noteUndefinedBehavior();
556 // In a constant context, assume that any dynamic rounding mode or FP
557 // exception state matches the default floating-point environment.
558 if (S
.inConstantContext())
561 FPOptions FPO
= E
.asExpr()->getFPFeaturesInEffect(S
.Ctx
.getLangOpts());
563 if ((Status
& APFloat::opInexact
) &&
564 FPO
.getRoundingMode() == llvm::RoundingMode::Dynamic
) {
565 // Inexact result means that it depends on rounding mode. If the requested
566 // mode is dynamic, the evaluation cannot be made in compile time.
567 S
.FFDiag(E
, diag::note_constexpr_dynamic_rounding
);
571 if ((Status
!= APFloat::opOK
) &&
572 (FPO
.getRoundingMode() == llvm::RoundingMode::Dynamic
||
573 FPO
.getExceptionMode() != LangOptions::FPE_Ignore
||
574 FPO
.getAllowFEnvAccess())) {
575 S
.FFDiag(E
, diag::note_constexpr_float_arithmetic_strict
);
579 if ((Status
& APFloat::opStatus::opInvalidOp
) &&
580 FPO
.getExceptionMode() != LangOptions::FPE_Ignore
) {
581 // There is no usefully definable result.
589 /// We aleady know the given DeclRefExpr is invalid for some reason,
590 /// now figure out why and print appropriate diagnostics.
591 bool CheckDeclRef(InterpState
&S
, CodePtr OpPC
, const DeclRefExpr
*DR
) {
592 const ValueDecl
*D
= DR
->getDecl();
593 const SourceInfo
&E
= S
.Current
->getSource(OpPC
);
595 if (isa
<ParmVarDecl
>(D
)) {
596 if (S
.getLangOpts().CPlusPlus11
) {
597 S
.FFDiag(E
, diag::note_constexpr_function_param_value_unknown
) << D
;
598 S
.Note(D
->getLocation(), diag::note_declared_at
) << D
->getSourceRange();
602 } else if (const auto *VD
= dyn_cast
<VarDecl
>(D
)) {
603 if (!VD
->getType().isConstQualified()) {
605 VD
->getType()->isIntegralOrEnumerationType()
606 ? diag::note_constexpr_ltor_non_const_int
607 : diag::note_constexpr_ltor_non_constexpr
,
610 S
.Note(VD
->getLocation(), diag::note_declared_at
) << VD
->getSourceRange();
614 // const, but no initializer.
615 if (!VD
->getAnyInitializer()) {
616 S
.FFDiag(E
, diag::note_constexpr_var_init_unknown
, 1) << VD
;
617 S
.Note(VD
->getLocation(), diag::note_declared_at
) << VD
->getSourceRange();
625 bool Interpret(InterpState
&S
, APValue
&Result
) {
626 // The current stack frame when we started Interpret().
627 // This is being used by the ops to determine wheter
628 // to return from this function and thus terminate
630 const InterpFrame
*StartFrame
= S
.Current
;
631 assert(!S
.Current
->isRoot());
632 CodePtr PC
= S
.Current
->getPC();
639 auto Op
= PC
.read
<Opcode
>();
644 #include "Opcodes.inc"
650 } // namespace interp