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