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