xref: /freebsd-src/contrib/llvm-project/clang/lib/AST/Interp/Interp.cpp (revision 46c59ea9b61755455ff6bf9f3e7b834e1af634ea)
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 //===----------------------------------------------------------------------===//
8 
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"
25 
26 using namespace clang;
27 using namespace clang::interp;
28 
29 static bool RetValue(InterpState &S, CodePtr &Pt, APValue &Result) {
30   llvm::report_fatal_error("Interpreter cannot return values");
31 }
32 
33 //===----------------------------------------------------------------------===//
34 // Jmp, Jt, Jf
35 //===----------------------------------------------------------------------===//
36 
37 static bool Jmp(InterpState &S, CodePtr &PC, int32_t Offset) {
38   PC += Offset;
39   return true;
40 }
41 
42 static bool Jt(InterpState &S, CodePtr &PC, int32_t Offset) {
43   if (S.Stk.pop<bool>()) {
44     PC += Offset;
45   }
46   return true;
47 }
48 
49 static bool Jf(InterpState &S, CodePtr &PC, int32_t Offset) {
50   if (!S.Stk.pop<bool>()) {
51     PC += Offset;
52   }
53   return true;
54 }
55 
56 static bool CheckActive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
57                         AccessKinds AK) {
58   if (Ptr.isActive())
59     return true;
60 
61   // Get the inactive field descriptor.
62   const FieldDecl *InactiveField = Ptr.getField();
63 
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();
68   }
69 
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;
79     }
80   }
81 
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;
86 }
87 
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;
93 
94     if (Ptr.getDeclDesc()->getType().isConstQualified())
95       return true;
96 
97     if (S.P.getCurrentDecl() == ID)
98       return true;
99 
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;
104   }
105   return true;
106 }
107 
108 static bool CheckGlobal(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
109   if (auto ID = Ptr.getDeclID()) {
110     if (!Ptr.isStatic())
111       return true;
112 
113     if (S.P.getCurrentDecl() == ID)
114       return true;
115 
116     S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_modify_global);
117     return false;
118   }
119   return true;
120 }
121 
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>());
127 }
128 
129 void cleanupAfterFunctionCall(InterpState &S, CodePtr OpPC) {
130   assert(S.Current);
131   const Function *CurFunc = S.Current->getFunction();
132   assert(CurFunc);
133 
134   if (CurFunc->isUnevaluatedBuiltin())
135     return;
136 
137   // Some builtin functions require us to only look at the call site, since
138   // the classified parameter types do not match.
139   if (CurFunc->isBuiltin()) {
140     const auto *CE =
141         cast<CallExpr>(S.Current->Caller->getExpr(S.Current->getRetPC()));
142     for (int32_t I = CE->getNumArgs() - 1; I >= 0; --I) {
143       const Expr *A = CE->getArg(I);
144       popArg(S, A);
145     }
146     return;
147   }
148 
149   if (S.Current->Caller && CurFunc->isVariadic()) {
150     // CallExpr we're look for is at the return PC of the current function, i.e.
151     // in the caller.
152     // This code path should be executed very rarely.
153     const auto *CE =
154         cast<CallExpr>(S.Current->Caller->getExpr(S.Current->getRetPC()));
155     unsigned FixedParams = CurFunc->getNumParams();
156     int32_t ArgsToPop = CE->getNumArgs() - FixedParams;
157     assert(ArgsToPop >= 0);
158     for (int32_t I = ArgsToPop - 1; I >= 0; --I) {
159       const Expr *A = CE->getArg(FixedParams + I);
160       popArg(S, A);
161     }
162   }
163   // And in any case, remove the fixed parameters (the non-variadic ones)
164   // at the end.
165   S.Current->popArgs();
166 }
167 
168 bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
169   if (!Ptr.isExtern())
170     return true;
171 
172   if (!S.checkingPotentialConstantExpression() && S.getLangOpts().CPlusPlus) {
173     const auto *VD = Ptr.getDeclDesc()->asValueDecl();
174     const SourceInfo &Loc = S.Current->getSource(OpPC);
175     S.FFDiag(Loc, diag::note_constexpr_ltor_non_constexpr, 1) << VD;
176     S.Note(VD->getLocation(), diag::note_declared_at);
177   }
178   return false;
179 }
180 
181 bool CheckArray(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
182   if (!Ptr.isUnknownSizeArray())
183     return true;
184   const SourceInfo &E = S.Current->getSource(OpPC);
185   S.FFDiag(E, diag::note_constexpr_unsized_array_indexed);
186   return false;
187 }
188 
189 bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
190                AccessKinds AK) {
191   if (Ptr.isZero()) {
192     const auto &Src = S.Current->getSource(OpPC);
193 
194     if (Ptr.isField())
195       S.FFDiag(Src, diag::note_constexpr_null_subobject) << CSK_Field;
196     else
197       S.FFDiag(Src, diag::note_constexpr_access_null) << AK;
198 
199     return false;
200   }
201 
202   if (!Ptr.isLive()) {
203     const auto &Src = S.Current->getSource(OpPC);
204     bool IsTemp = Ptr.isTemporary();
205 
206     S.FFDiag(Src, diag::note_constexpr_lifetime_ended, 1) << AK << !IsTemp;
207 
208     if (IsTemp)
209       S.Note(Ptr.getDeclLoc(), diag::note_constexpr_temporary_here);
210     else
211       S.Note(Ptr.getDeclLoc(), diag::note_declared_at);
212 
213     return false;
214   }
215 
216   return true;
217 }
218 
219 bool CheckDummy(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
220   return !Ptr.isZero() && !Ptr.isDummy();
221 }
222 
223 bool CheckNull(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
224                CheckSubobjectKind CSK) {
225   if (!Ptr.isZero())
226     return true;
227   const SourceInfo &Loc = S.Current->getSource(OpPC);
228   S.FFDiag(Loc, diag::note_constexpr_null_subobject) << CSK;
229   return false;
230 }
231 
232 bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
233                 AccessKinds AK) {
234   if (!Ptr.isOnePastEnd())
235     return true;
236   const SourceInfo &Loc = S.Current->getSource(OpPC);
237   S.FFDiag(Loc, diag::note_constexpr_access_past_end) << AK;
238   return false;
239 }
240 
241 bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
242                 CheckSubobjectKind CSK) {
243   if (!Ptr.isElementPastEnd())
244     return true;
245   const SourceInfo &Loc = S.Current->getSource(OpPC);
246   S.FFDiag(Loc, diag::note_constexpr_past_end_subobject) << CSK;
247   return false;
248 }
249 
250 bool CheckSubobject(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
251                     CheckSubobjectKind CSK) {
252   if (!Ptr.isOnePastEnd())
253     return true;
254 
255   const SourceInfo &Loc = S.Current->getSource(OpPC);
256   S.FFDiag(Loc, diag::note_constexpr_past_end_subobject) << CSK;
257   return false;
258 }
259 
260 bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
261   assert(Ptr.isLive() && "Pointer is not live");
262   if (!Ptr.isConst())
263     return true;
264 
265   // The This pointer is writable in constructors and destructors,
266   // even if isConst() returns true.
267   if (const Function *Func = S.Current->getFunction();
268       Func && (Func->isConstructor() || Func->isDestructor()) &&
269       Ptr.block() == S.Current->getThis().block()) {
270     return true;
271   }
272 
273   const QualType Ty = Ptr.getType();
274   const SourceInfo &Loc = S.Current->getSource(OpPC);
275   S.FFDiag(Loc, diag::note_constexpr_modify_const_type) << Ty;
276   return false;
277 }
278 
279 bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
280   assert(Ptr.isLive() && "Pointer is not live");
281   if (!Ptr.isMutable()) {
282     return true;
283   }
284 
285   const SourceInfo &Loc = S.Current->getSource(OpPC);
286   const FieldDecl *Field = Ptr.getField();
287   S.FFDiag(Loc, diag::note_constexpr_access_mutable, 1) << AK_Read << Field;
288   S.Note(Field->getLocation(), diag::note_declared_at);
289   return false;
290 }
291 
292 bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
293                       AccessKinds AK) {
294   if (Ptr.isInitialized())
295     return true;
296 
297   if (!S.checkingPotentialConstantExpression()) {
298     S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_uninit)
299         << AK << /*uninitialized=*/true << S.Current->getRange(OpPC);
300   }
301   return false;
302 }
303 
304 bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
305   if (!CheckLive(S, OpPC, Ptr, AK_Read))
306     return false;
307   if (!CheckDummy(S, OpPC, Ptr))
308     return false;
309   if (!CheckExtern(S, OpPC, Ptr))
310     return false;
311   if (!CheckRange(S, OpPC, Ptr, AK_Read))
312     return false;
313   if (!CheckInitialized(S, OpPC, Ptr, AK_Read))
314     return false;
315   if (!CheckActive(S, OpPC, Ptr, AK_Read))
316     return false;
317   if (!CheckTemporary(S, OpPC, Ptr, AK_Read))
318     return false;
319   if (!CheckMutable(S, OpPC, Ptr))
320     return false;
321   return true;
322 }
323 
324 bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
325   if (!CheckLive(S, OpPC, Ptr, AK_Assign))
326     return false;
327   if (!CheckExtern(S, OpPC, Ptr))
328     return false;
329   if (!CheckRange(S, OpPC, Ptr, AK_Assign))
330     return false;
331   if (!CheckGlobal(S, OpPC, Ptr))
332     return false;
333   if (!CheckConst(S, OpPC, Ptr))
334     return false;
335   return true;
336 }
337 
338 bool CheckInvoke(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
339   if (!CheckLive(S, OpPC, Ptr, AK_MemberCall))
340     return false;
341   if (!CheckExtern(S, OpPC, Ptr))
342     return false;
343   if (!CheckRange(S, OpPC, Ptr, AK_MemberCall))
344     return false;
345   return true;
346 }
347 
348 bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
349   if (!CheckLive(S, OpPC, Ptr, AK_Assign))
350     return false;
351   if (!CheckRange(S, OpPC, Ptr, AK_Assign))
352     return false;
353   return true;
354 }
355 
356 bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) {
357 
358   if (F->isVirtual() && !S.getLangOpts().CPlusPlus20) {
359     const SourceLocation &Loc = S.Current->getLocation(OpPC);
360     S.CCEDiag(Loc, diag::note_constexpr_virtual_call);
361     return false;
362   }
363 
364   if (!F->isConstexpr()) {
365     const SourceLocation &Loc = S.Current->getLocation(OpPC);
366     if (S.getLangOpts().CPlusPlus11) {
367       const FunctionDecl *DiagDecl = F->getDecl();
368 
369       // If this function is not constexpr because it is an inherited
370       // non-constexpr constructor, diagnose that directly.
371       const auto *CD = dyn_cast<CXXConstructorDecl>(DiagDecl);
372       if (CD && CD->isInheritingConstructor()) {
373         const auto *Inherited = CD->getInheritedConstructor().getConstructor();
374         if (!Inherited->isConstexpr())
375           DiagDecl = CD = Inherited;
376       }
377 
378       // FIXME: If DiagDecl is an implicitly-declared special member function
379       // or an inheriting constructor, we should be much more explicit about why
380       // it's not constexpr.
381       if (CD && CD->isInheritingConstructor()) {
382         S.FFDiag(Loc, diag::note_constexpr_invalid_inhctor, 1)
383           << CD->getInheritedConstructor().getConstructor()->getParent();
384         S.Note(DiagDecl->getLocation(), diag::note_declared_at);
385       } else {
386         // Don't emit anything if the function isn't defined and we're checking
387         // for a constant expression. It might be defined at the point we're
388         // actually calling it.
389         if (!DiagDecl->isDefined() && S.checkingPotentialConstantExpression())
390           return false;
391 
392         S.FFDiag(Loc, diag::note_constexpr_invalid_function, 1)
393           << DiagDecl->isConstexpr() << (bool)CD << DiagDecl;
394         S.Note(DiagDecl->getLocation(), diag::note_declared_at);
395       }
396     } else {
397       S.FFDiag(Loc, diag::note_invalid_subexpr_in_const_expr);
398     }
399     return false;
400   }
401 
402   return true;
403 }
404 
405 bool CheckCallDepth(InterpState &S, CodePtr OpPC) {
406   if ((S.Current->getDepth() + 1) > S.getLangOpts().ConstexprCallDepth) {
407     S.FFDiag(S.Current->getSource(OpPC),
408              diag::note_constexpr_depth_limit_exceeded)
409         << S.getLangOpts().ConstexprCallDepth;
410     return false;
411   }
412 
413   return true;
414 }
415 
416 bool CheckThis(InterpState &S, CodePtr OpPC, const Pointer &This) {
417   if (!This.isZero())
418     return true;
419 
420   const SourceInfo &Loc = S.Current->getSource(OpPC);
421 
422   bool IsImplicit = false;
423   if (const auto *E = dyn_cast_if_present<CXXThisExpr>(Loc.asExpr()))
424     IsImplicit = E->isImplicit();
425 
426   if (S.getLangOpts().CPlusPlus11)
427     S.FFDiag(Loc, diag::note_constexpr_this) << IsImplicit;
428   else
429     S.FFDiag(Loc);
430 
431   return false;
432 }
433 
434 bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD) {
435   if (!MD->isPure())
436     return true;
437   const SourceInfo &E = S.Current->getSource(OpPC);
438   S.FFDiag(E, diag::note_constexpr_pure_virtual_call, 1) << MD;
439   S.Note(MD->getLocation(), diag::note_declared_at);
440   return false;
441 }
442 
443 static void DiagnoseUninitializedSubobject(InterpState &S, const SourceInfo &SI,
444                                            const FieldDecl *SubObjDecl) {
445   assert(SubObjDecl && "Subobject declaration does not exist");
446   S.FFDiag(SI, diag::note_constexpr_uninitialized)
447       << /*(name)*/ 1 << SubObjDecl;
448   S.Note(SubObjDecl->getLocation(),
449          diag::note_constexpr_subobject_declared_here);
450 }
451 
452 static bool CheckFieldsInitialized(InterpState &S, CodePtr OpPC,
453                                    const Pointer &BasePtr, const Record *R);
454 
455 static bool CheckArrayInitialized(InterpState &S, CodePtr OpPC,
456                                   const Pointer &BasePtr,
457                                   const ConstantArrayType *CAT) {
458   bool Result = true;
459   size_t NumElems = CAT->getSize().getZExtValue();
460   QualType ElemType = CAT->getElementType();
461 
462   if (ElemType->isRecordType()) {
463     const Record *R = BasePtr.getElemRecord();
464     for (size_t I = 0; I != NumElems; ++I) {
465       Pointer ElemPtr = BasePtr.atIndex(I).narrow();
466       Result &= CheckFieldsInitialized(S, OpPC, ElemPtr, R);
467     }
468   } else if (const auto *ElemCAT = dyn_cast<ConstantArrayType>(ElemType)) {
469     for (size_t I = 0; I != NumElems; ++I) {
470       Pointer ElemPtr = BasePtr.atIndex(I).narrow();
471       Result &= CheckArrayInitialized(S, OpPC, ElemPtr, ElemCAT);
472     }
473   } else {
474     for (size_t I = 0; I != NumElems; ++I) {
475       if (!BasePtr.atIndex(I).isInitialized()) {
476         DiagnoseUninitializedSubobject(S, S.Current->getSource(OpPC),
477                                        BasePtr.getField());
478         Result = false;
479       }
480     }
481   }
482 
483   return Result;
484 }
485 
486 static bool CheckFieldsInitialized(InterpState &S, CodePtr OpPC,
487                                    const Pointer &BasePtr, const Record *R) {
488   assert(R);
489   bool Result = true;
490   // Check all fields of this record are initialized.
491   for (const Record::Field &F : R->fields()) {
492     Pointer FieldPtr = BasePtr.atField(F.Offset);
493     QualType FieldType = F.Decl->getType();
494 
495     if (FieldType->isRecordType()) {
496       Result &= CheckFieldsInitialized(S, OpPC, FieldPtr, FieldPtr.getRecord());
497     } else if (FieldType->isIncompleteArrayType()) {
498       // Nothing to do here.
499     } else if (FieldType->isArrayType()) {
500       const auto *CAT =
501           cast<ConstantArrayType>(FieldType->getAsArrayTypeUnsafe());
502       Result &= CheckArrayInitialized(S, OpPC, FieldPtr, CAT);
503     } else if (!FieldPtr.isInitialized()) {
504       DiagnoseUninitializedSubobject(S, S.Current->getSource(OpPC), F.Decl);
505       Result = false;
506     }
507   }
508 
509   // Check Fields in all bases
510   for (const Record::Base &B : R->bases()) {
511     Pointer P = BasePtr.atField(B.Offset);
512     if (!P.isInitialized()) {
513       S.FFDiag(BasePtr.getDeclDesc()->asDecl()->getLocation(),
514                diag::note_constexpr_uninitialized_base)
515           << B.Desc->getType();
516       return false;
517     }
518     Result &= CheckFieldsInitialized(S, OpPC, P, B.R);
519   }
520 
521   // TODO: Virtual bases
522 
523   return Result;
524 }
525 
526 bool CheckCtorCall(InterpState &S, CodePtr OpPC, const Pointer &This) {
527   assert(!This.isZero());
528   if (const Record *R = This.getRecord())
529     return CheckFieldsInitialized(S, OpPC, This, R);
530   const auto *CAT =
531       cast<ConstantArrayType>(This.getType()->getAsArrayTypeUnsafe());
532   return CheckArrayInitialized(S, OpPC, This, CAT);
533 }
534 
535 bool CheckPotentialReinterpretCast(InterpState &S, CodePtr OpPC,
536                                    const Pointer &Ptr) {
537   if (!S.inConstantContext())
538     return true;
539 
540   const SourceInfo &E = S.Current->getSource(OpPC);
541   S.CCEDiag(E, diag::note_constexpr_invalid_cast)
542       << 2 << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC);
543   return false;
544 }
545 
546 bool CheckFloatResult(InterpState &S, CodePtr OpPC, const Floating &Result,
547                       APFloat::opStatus Status) {
548   const SourceInfo &E = S.Current->getSource(OpPC);
549 
550   // [expr.pre]p4:
551   //   If during the evaluation of an expression, the result is not
552   //   mathematically defined [...], the behavior is undefined.
553   // FIXME: C++ rules require us to not conform to IEEE 754 here.
554   if (Result.isNan()) {
555     S.CCEDiag(E, diag::note_constexpr_float_arithmetic)
556         << /*NaN=*/true << S.Current->getRange(OpPC);
557     return S.noteUndefinedBehavior();
558   }
559 
560   // In a constant context, assume that any dynamic rounding mode or FP
561   // exception state matches the default floating-point environment.
562   if (S.inConstantContext())
563     return true;
564 
565   FPOptions FPO = E.asExpr()->getFPFeaturesInEffect(S.Ctx.getLangOpts());
566 
567   if ((Status & APFloat::opInexact) &&
568       FPO.getRoundingMode() == llvm::RoundingMode::Dynamic) {
569     // Inexact result means that it depends on rounding mode. If the requested
570     // mode is dynamic, the evaluation cannot be made in compile time.
571     S.FFDiag(E, diag::note_constexpr_dynamic_rounding);
572     return false;
573   }
574 
575   if ((Status != APFloat::opOK) &&
576       (FPO.getRoundingMode() == llvm::RoundingMode::Dynamic ||
577        FPO.getExceptionMode() != LangOptions::FPE_Ignore ||
578        FPO.getAllowFEnvAccess())) {
579     S.FFDiag(E, diag::note_constexpr_float_arithmetic_strict);
580     return false;
581   }
582 
583   if ((Status & APFloat::opStatus::opInvalidOp) &&
584       FPO.getExceptionMode() != LangOptions::FPE_Ignore) {
585     // There is no usefully definable result.
586     S.FFDiag(E);
587     return false;
588   }
589 
590   return true;
591 }
592 
593 /// We aleady know the given DeclRefExpr is invalid for some reason,
594 /// now figure out why and print appropriate diagnostics.
595 bool CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR) {
596   const ValueDecl *D = DR->getDecl();
597   const SourceInfo &E = S.Current->getSource(OpPC);
598 
599   if (isa<ParmVarDecl>(D)) {
600     if (S.getLangOpts().CPlusPlus11) {
601       S.FFDiag(E, diag::note_constexpr_function_param_value_unknown) << D;
602       S.Note(D->getLocation(), diag::note_declared_at) << D->getSourceRange();
603     } else {
604       S.FFDiag(E);
605     }
606   } else if (const auto *VD = dyn_cast<VarDecl>(D)) {
607     if (!VD->getType().isConstQualified()) {
608       S.FFDiag(E,
609                VD->getType()->isIntegralOrEnumerationType()
610                    ? diag::note_constexpr_ltor_non_const_int
611                    : diag::note_constexpr_ltor_non_constexpr,
612                1)
613           << VD;
614       S.Note(VD->getLocation(), diag::note_declared_at) << VD->getSourceRange();
615       return false;
616     }
617 
618     // const, but no initializer.
619     if (!VD->getAnyInitializer()) {
620       S.FFDiag(E, diag::note_constexpr_var_init_unknown, 1) << VD;
621       S.Note(VD->getLocation(), diag::note_declared_at) << VD->getSourceRange();
622       return false;
623     }
624   }
625 
626   return false;
627 }
628 
629 bool Interpret(InterpState &S, APValue &Result) {
630   // The current stack frame when we started Interpret().
631   // This is being used by the ops to determine wheter
632   // to return from this function and thus terminate
633   // interpretation.
634   const InterpFrame *StartFrame = S.Current;
635   assert(!S.Current->isRoot());
636   CodePtr PC = S.Current->getPC();
637 
638   // Empty program.
639   if (!PC)
640     return true;
641 
642   for (;;) {
643     auto Op = PC.read<Opcode>();
644     CodePtr OpPC = PC;
645 
646     switch (Op) {
647 #define GET_INTERP
648 #include "Opcodes.inc"
649 #undef GET_INTERP
650     }
651   }
652 }
653 
654 } // namespace interp
655 } // namespace clang
656