[clang][modules] Don't prevent translation of FW_Private includes when explicitly...
[llvm-project.git] / clang / lib / AST / Interp / Interp.cpp
blob144b674451e353c7bfe1fe9be5cc243686283dcb
1 //===------- Interp.cpp - Interpreter for the constexpr VM ------*- 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 //===----------------------------------------------------------------------===//
9 #include "Interp.h"
10 #include <limits>
11 #include <vector>
12 #include "Function.h"
13 #include "InterpFrame.h"
14 #include "InterpStack.h"
15 #include "Opcode.h"
16 #include "PrimType.h"
17 #include "Program.h"
18 #include "State.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 //===----------------------------------------------------------------------===//
34 // Jmp, Jt, Jf
35 //===----------------------------------------------------------------------===//
37 static bool Jmp(InterpState &S, CodePtr &PC, int32_t Offset) {
38 PC += Offset;
39 return true;
42 static bool Jt(InterpState &S, CodePtr &PC, int32_t Offset) {
43 if (S.Stk.pop<bool>()) {
44 PC += Offset;
46 return true;
49 static bool Jf(InterpState &S, CodePtr &PC, int32_t Offset) {
50 if (!S.Stk.pop<bool>()) {
51 PC += Offset;
53 return true;
56 static bool CheckActive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
57 AccessKinds AK) {
58 if (Ptr.isActive())
59 return true;
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()) {
67 U = U.getBase();
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();
78 break;
82 const SourceInfo &Loc = S.Current->getSource(OpPC);
83 S.FFDiag(Loc, diag::note_constexpr_access_inactive_union_member)
84 << AK << InactiveField << !ActiveField << ActiveField;
85 return false;
88 static bool CheckTemporary(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
89 AccessKinds AK) {
90 if (auto ID = Ptr.getDeclID()) {
91 if (!Ptr.isStaticTemporary())
92 return true;
94 if (Ptr.getDeclDesc()->getType().isConstQualified())
95 return true;
97 if (S.P.getCurrentDecl() == ID)
98 return true;
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);
103 return false;
105 return true;
108 static bool CheckGlobal(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
109 if (auto ID = Ptr.getDeclID()) {
110 if (!Ptr.isStatic())
111 return true;
113 if (S.P.getCurrentDecl() == ID)
114 return true;
116 S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_modify_global);
117 return false;
119 return true;
122 namespace clang {
123 namespace interp {
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) {
130 assert(S.Current);
131 const Function *CurFunc = S.Current->getFunction();
132 assert(CurFunc);
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));
145 return;
148 if (S.Current->Caller && CurFunc->isVariadic()) {
149 // CallExpr we're look for is at the return PC of the current function, i.e.
150 // in the caller.
151 // This code path should be executed very rarely.
152 const auto *CE =
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);
159 popArg(S, A);
162 // And in any case, remove the fixed parameters (the non-variadic ones)
163 // at the end.
164 S.Current->popArgs();
167 bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
168 if (!Ptr.isExtern())
169 return true;
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);
177 return false;
180 bool CheckArray(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
181 if (!Ptr.isUnknownSizeArray())
182 return true;
183 const SourceInfo &E = S.Current->getSource(OpPC);
184 S.FFDiag(E, diag::note_constexpr_unsized_array_indexed);
185 return false;
188 bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
189 AccessKinds AK) {
190 if (Ptr.isZero()) {
191 const auto &Src = S.Current->getSource(OpPC);
193 if (Ptr.isField())
194 S.FFDiag(Src, diag::note_constexpr_null_subobject) << CSK_Field;
195 else
196 S.FFDiag(Src, diag::note_constexpr_access_null) << AK;
198 return false;
201 if (!Ptr.isLive()) {
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;
207 if (IsTemp)
208 S.Note(Ptr.getDeclLoc(), diag::note_constexpr_temporary_here);
209 else
210 S.Note(Ptr.getDeclLoc(), diag::note_declared_at);
212 return false;
215 return true;
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) {
224 if (!Ptr.isZero())
225 return true;
226 const SourceInfo &Loc = S.Current->getSource(OpPC);
227 S.FFDiag(Loc, diag::note_constexpr_null_subobject) << CSK;
228 return false;
231 bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
232 AccessKinds AK) {
233 if (!Ptr.isOnePastEnd())
234 return true;
235 const SourceInfo &Loc = S.Current->getSource(OpPC);
236 S.FFDiag(Loc, diag::note_constexpr_access_past_end) << AK;
237 return false;
240 bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
241 CheckSubobjectKind CSK) {
242 if (!Ptr.isElementPastEnd())
243 return true;
244 const SourceInfo &Loc = S.Current->getSource(OpPC);
245 S.FFDiag(Loc, diag::note_constexpr_past_end_subobject) << CSK;
246 return false;
249 bool CheckSubobject(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
250 CheckSubobjectKind CSK) {
251 if (!Ptr.isOnePastEnd())
252 return true;
254 const SourceInfo &Loc = S.Current->getSource(OpPC);
255 S.FFDiag(Loc, diag::note_constexpr_past_end_subobject) << CSK;
256 return false;
259 bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
260 assert(Ptr.isLive() && "Pointer is not live");
261 if (!Ptr.isConst())
262 return true;
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()) {
269 return true;
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;
275 return false;
278 bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
279 assert(Ptr.isLive() && "Pointer is not live");
280 if (!Ptr.isMutable()) {
281 return true;
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);
288 return false;
291 bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
292 AccessKinds AK) {
293 if (Ptr.isInitialized())
294 return true;
296 if (!S.checkingPotentialConstantExpression()) {
297 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_uninit)
298 << AK << /*uninitialized=*/true << S.Current->getRange(OpPC);
300 return false;
303 bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
304 if (!CheckDummy(S, OpPC, Ptr))
305 return false;
306 if (!CheckLive(S, OpPC, Ptr, AK_Read))
307 return false;
308 if (!CheckExtern(S, OpPC, Ptr))
309 return false;
310 if (!CheckRange(S, OpPC, Ptr, AK_Read))
311 return false;
312 if (!CheckInitialized(S, OpPC, Ptr, AK_Read))
313 return false;
314 if (!CheckActive(S, OpPC, Ptr, AK_Read))
315 return false;
316 if (!CheckTemporary(S, OpPC, Ptr, AK_Read))
317 return false;
318 if (!CheckMutable(S, OpPC, Ptr))
319 return false;
320 return true;
323 bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
324 if (!CheckLive(S, OpPC, Ptr, AK_Assign))
325 return false;
326 if (!CheckExtern(S, OpPC, Ptr))
327 return false;
328 if (!CheckRange(S, OpPC, Ptr, AK_Assign))
329 return false;
330 if (!CheckGlobal(S, OpPC, Ptr))
331 return false;
332 if (!CheckConst(S, OpPC, Ptr))
333 return false;
334 return true;
337 bool CheckInvoke(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
338 if (!CheckLive(S, OpPC, Ptr, AK_MemberCall))
339 return false;
340 if (!CheckExtern(S, OpPC, Ptr))
341 return false;
342 if (!CheckRange(S, OpPC, Ptr, AK_MemberCall))
343 return false;
344 return true;
347 bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
348 if (!CheckLive(S, OpPC, Ptr, AK_Assign))
349 return false;
350 if (!CheckRange(S, OpPC, Ptr, AK_Assign))
351 return false;
352 return true;
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);
360 return false;
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())
367 return false;
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();
388 else
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);
392 } else {
393 S.FFDiag(Loc, diag::note_invalid_subexpr_in_const_expr);
395 return false;
398 return true;
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;
406 return false;
409 return true;
412 bool CheckThis(InterpState &S, CodePtr OpPC, const Pointer &This) {
413 if (!This.isZero())
414 return true;
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;
424 else
425 S.FFDiag(Loc);
427 return false;
430 bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD) {
431 if (!MD->isPure())
432 return true;
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);
436 return false;
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) {
454 bool Result = true;
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);
469 } else {
470 for (size_t I = 0; I != NumElems; ++I) {
471 if (!BasePtr.atIndex(I).isInitialized()) {
472 DiagnoseUninitializedSubobject(S, S.Current->getSource(OpPC),
473 BasePtr.getField());
474 Result = false;
479 return Result;
482 static bool CheckFieldsInitialized(InterpState &S, CodePtr OpPC,
483 const Pointer &BasePtr, const Record *R) {
484 assert(R);
485 bool Result = true;
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()) {
496 const auto *CAT =
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);
501 Result = false;
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();
512 return false;
514 Result &= CheckFieldsInitialized(S, OpPC, P, B.R);
517 // TODO: Virtual bases
519 return Result;
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);
526 const auto *CAT =
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())
534 return true;
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);
539 return false;
542 bool CheckFloatResult(InterpState &S, CodePtr OpPC, const Floating &Result,
543 APFloat::opStatus Status) {
544 const SourceInfo &E = S.Current->getSource(OpPC);
546 // [expr.pre]p4:
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())
559 return true;
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);
568 return false;
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);
576 return false;
579 if ((Status & APFloat::opStatus::opInvalidOp) &&
580 FPO.getExceptionMode() != LangOptions::FPE_Ignore) {
581 // There is no usefully definable result.
582 S.FFDiag(E);
583 return false;
586 return true;
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();
599 } else {
600 S.FFDiag(E);
602 } else if (const auto *VD = dyn_cast<VarDecl>(D)) {
603 if (!VD->getType().isConstQualified()) {
604 S.FFDiag(E,
605 VD->getType()->isIntegralOrEnumerationType()
606 ? diag::note_constexpr_ltor_non_const_int
607 : diag::note_constexpr_ltor_non_constexpr,
609 << VD;
610 S.Note(VD->getLocation(), diag::note_declared_at) << VD->getSourceRange();
611 return false;
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();
618 return false;
622 return false;
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
629 // interpretation.
630 const InterpFrame *StartFrame = S.Current;
631 assert(!S.Current->isRoot());
632 CodePtr PC = S.Current->getPC();
634 // Empty program.
635 if (!PC)
636 return true;
638 for (;;) {
639 auto Op = PC.read<Opcode>();
640 CodePtr OpPC = PC;
642 switch (Op) {
643 #define GET_INTERP
644 #include "Opcodes.inc"
645 #undef GET_INTERP
650 } // namespace interp
651 } // namespace clang