xref: /llvm-project/clang/lib/AST/ByteCode/Interp.cpp (revision df11ee213e43ae373d1357939cf14ea37d547110)
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 "Function.h"
11 #include "InterpFrame.h"
12 #include "InterpShared.h"
13 #include "InterpStack.h"
14 #include "Opcode.h"
15 #include "PrimType.h"
16 #include "Program.h"
17 #include "State.h"
18 #include "clang/AST/ASTContext.h"
19 #include "clang/AST/ASTDiagnostic.h"
20 #include "clang/AST/CXXInheritance.h"
21 #include "clang/AST/DeclObjC.h"
22 #include "clang/AST/Expr.h"
23 #include "clang/AST/ExprCXX.h"
24 #include "llvm/ADT/APSInt.h"
25 #include "llvm/ADT/StringExtras.h"
26 #include <limits>
27 #include <vector>
28 
29 using namespace clang;
30 using namespace clang::interp;
31 
32 static bool RetValue(InterpState &S, CodePtr &Pt, APValue &Result) {
33   llvm::report_fatal_error("Interpreter cannot return values");
34 }
35 
36 //===----------------------------------------------------------------------===//
37 // Jmp, Jt, Jf
38 //===----------------------------------------------------------------------===//
39 
40 static bool Jmp(InterpState &S, CodePtr &PC, int32_t Offset) {
41   PC += Offset;
42   return true;
43 }
44 
45 static bool Jt(InterpState &S, CodePtr &PC, int32_t Offset) {
46   if (S.Stk.pop<bool>()) {
47     PC += Offset;
48   }
49   return true;
50 }
51 
52 static bool Jf(InterpState &S, CodePtr &PC, int32_t Offset) {
53   if (!S.Stk.pop<bool>()) {
54     PC += Offset;
55   }
56   return true;
57 }
58 
59 static void diagnoseMissingInitializer(InterpState &S, CodePtr OpPC,
60                                        const ValueDecl *VD) {
61   const SourceInfo &E = S.Current->getSource(OpPC);
62   S.FFDiag(E, diag::note_constexpr_var_init_unknown, 1) << VD;
63   S.Note(VD->getLocation(), diag::note_declared_at) << VD->getSourceRange();
64 }
65 
66 static void diagnoseNonConstVariable(InterpState &S, CodePtr OpPC,
67                                      const ValueDecl *VD);
68 static bool diagnoseUnknownDecl(InterpState &S, CodePtr OpPC,
69                                 const ValueDecl *D) {
70   const SourceInfo &E = S.Current->getSource(OpPC);
71 
72   if (isa<ParmVarDecl>(D)) {
73     if (S.getLangOpts().CPlusPlus11) {
74       S.FFDiag(E, diag::note_constexpr_function_param_value_unknown) << D;
75       S.Note(D->getLocation(), diag::note_declared_at) << D->getSourceRange();
76     } else {
77       S.FFDiag(E);
78     }
79     return false;
80   }
81 
82   if (!D->getType().isConstQualified())
83     diagnoseNonConstVariable(S, OpPC, D);
84   else if (const auto *VD = dyn_cast<VarDecl>(D);
85            VD && !VD->getAnyInitializer())
86     diagnoseMissingInitializer(S, OpPC, VD);
87 
88   return false;
89 }
90 
91 static void diagnoseNonConstVariable(InterpState &S, CodePtr OpPC,
92                                      const ValueDecl *VD) {
93   if (!S.getLangOpts().CPlusPlus)
94     return;
95 
96   const SourceInfo &Loc = S.Current->getSource(OpPC);
97   if (const auto *VarD = dyn_cast<VarDecl>(VD);
98       VarD && VarD->getType().isConstQualified() &&
99       !VarD->getAnyInitializer()) {
100     diagnoseMissingInitializer(S, OpPC, VD);
101     return;
102   }
103 
104   // Rather random, but this is to match the diagnostic output of the current
105   // interpreter.
106   if (isa<ObjCIvarDecl>(VD))
107     return;
108 
109   if (VD->getType()->isIntegralOrEnumerationType()) {
110     S.FFDiag(Loc, diag::note_constexpr_ltor_non_const_int, 1) << VD;
111     S.Note(VD->getLocation(), diag::note_declared_at);
112     return;
113   }
114 
115   S.FFDiag(Loc,
116            S.getLangOpts().CPlusPlus11 ? diag::note_constexpr_ltor_non_constexpr
117                                        : diag::note_constexpr_ltor_non_integral,
118            1)
119       << VD << VD->getType();
120   S.Note(VD->getLocation(), diag::note_declared_at);
121 }
122 
123 static bool CheckActive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
124                         AccessKinds AK) {
125   if (Ptr.isActive())
126     return true;
127 
128   assert(Ptr.inUnion());
129   assert(Ptr.isField() && Ptr.getField());
130 
131   Pointer U = Ptr.getBase();
132   Pointer C = Ptr;
133   while (!U.isRoot() && U.inUnion() && !U.isActive()) {
134     if (U.getField())
135       C = U;
136     U = U.getBase();
137   }
138   assert(C.isField());
139 
140   // Get the inactive field descriptor.
141   const FieldDecl *InactiveField = C.getField();
142   assert(InactiveField);
143 
144   // Consider:
145   // union U {
146   //   struct {
147   //     int x;
148   //     int y;
149   //   } a;
150   // }
151   //
152   // When activating x, we will also activate a. If we now try to read
153   // from y, we will get to CheckActive, because y is not active. In that
154   // case, our U will be a (not a union). We return here and let later code
155   // handle this.
156   if (!U.getFieldDesc()->isUnion())
157     return true;
158 
159   // Find the active field of the union.
160   const Record *R = U.getRecord();
161   assert(R && R->isUnion() && "Not a union");
162 
163   const FieldDecl *ActiveField = nullptr;
164   for (const Record::Field &F : R->fields()) {
165     const Pointer &Field = U.atField(F.Offset);
166     if (Field.isActive()) {
167       ActiveField = Field.getField();
168       break;
169     }
170   }
171 
172   const SourceInfo &Loc = S.Current->getSource(OpPC);
173   S.FFDiag(Loc, diag::note_constexpr_access_inactive_union_member)
174       << AK << InactiveField << !ActiveField << ActiveField;
175   return false;
176 }
177 
178 static bool CheckTemporary(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
179                            AccessKinds AK) {
180   if (auto ID = Ptr.getDeclID()) {
181     if (!Ptr.isStaticTemporary())
182       return true;
183 
184     if (Ptr.getDeclDesc()->getType().isConstQualified())
185       return true;
186 
187     if (S.P.getCurrentDecl() == ID)
188       return true;
189 
190     const SourceInfo &E = S.Current->getSource(OpPC);
191     S.FFDiag(E, diag::note_constexpr_access_static_temporary, 1) << AK;
192     S.Note(Ptr.getDeclLoc(), diag::note_constexpr_temporary_here);
193     return false;
194   }
195   return true;
196 }
197 
198 static bool CheckGlobal(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
199   if (auto ID = Ptr.getDeclID()) {
200     if (!Ptr.isStatic())
201       return true;
202 
203     if (S.P.getCurrentDecl() == ID)
204       return true;
205 
206     S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_modify_global);
207     return false;
208   }
209   return true;
210 }
211 
212 namespace clang {
213 namespace interp {
214 static void popArg(InterpState &S, const Expr *Arg) {
215   PrimType Ty = S.getContext().classify(Arg).value_or(PT_Ptr);
216   TYPE_SWITCH(Ty, S.Stk.discard<T>());
217 }
218 
219 void cleanupAfterFunctionCall(InterpState &S, CodePtr OpPC) {
220   assert(S.Current);
221   const Function *CurFunc = S.Current->getFunction();
222   assert(CurFunc);
223 
224   if (CurFunc->isUnevaluatedBuiltin())
225     return;
226 
227   // Some builtin functions require us to only look at the call site, since
228   // the classified parameter types do not match.
229   if (CurFunc->isBuiltin()) {
230     const auto *CE =
231         cast<CallExpr>(S.Current->Caller->getExpr(S.Current->getRetPC()));
232     for (int32_t I = CE->getNumArgs() - 1; I >= 0; --I) {
233       const Expr *A = CE->getArg(I);
234       popArg(S, A);
235     }
236     return;
237   }
238 
239   if (S.Current->Caller && CurFunc->isVariadic()) {
240     // CallExpr we're look for is at the return PC of the current function, i.e.
241     // in the caller.
242     // This code path should be executed very rarely.
243     unsigned NumVarArgs;
244     const Expr *const *Args = nullptr;
245     unsigned NumArgs = 0;
246     const Expr *CallSite = S.Current->Caller->getExpr(S.Current->getRetPC());
247     if (const auto *CE = dyn_cast<CallExpr>(CallSite)) {
248       Args = CE->getArgs();
249       NumArgs = CE->getNumArgs();
250     } else if (const auto *CE = dyn_cast<CXXConstructExpr>(CallSite)) {
251       Args = CE->getArgs();
252       NumArgs = CE->getNumArgs();
253     } else
254       assert(false && "Can't get arguments from that expression type");
255 
256     assert(NumArgs >= CurFunc->getNumWrittenParams());
257     NumVarArgs = NumArgs - (CurFunc->getNumWrittenParams() +
258                             isa<CXXOperatorCallExpr>(CallSite));
259     for (unsigned I = 0; I != NumVarArgs; ++I) {
260       const Expr *A = Args[NumArgs - 1 - I];
261       popArg(S, A);
262     }
263   }
264 
265   // And in any case, remove the fixed parameters (the non-variadic ones)
266   // at the end.
267   S.Current->popArgs();
268 }
269 
270 bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
271   if (!Ptr.isExtern())
272     return true;
273 
274   if (Ptr.isInitialized() ||
275       (Ptr.getDeclDesc()->asVarDecl() == S.EvaluatingDecl))
276     return true;
277 
278   if (!S.checkingPotentialConstantExpression() && S.getLangOpts().CPlusPlus) {
279     const auto *VD = Ptr.getDeclDesc()->asValueDecl();
280     diagnoseNonConstVariable(S, OpPC, VD);
281   }
282   return false;
283 }
284 
285 bool CheckArray(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
286   if (!Ptr.isUnknownSizeArray())
287     return true;
288   const SourceInfo &E = S.Current->getSource(OpPC);
289   S.FFDiag(E, diag::note_constexpr_unsized_array_indexed);
290   return false;
291 }
292 
293 bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
294                AccessKinds AK) {
295   if (Ptr.isZero()) {
296     const auto &Src = S.Current->getSource(OpPC);
297 
298     if (Ptr.isField())
299       S.FFDiag(Src, diag::note_constexpr_null_subobject) << CSK_Field;
300     else
301       S.FFDiag(Src, diag::note_constexpr_access_null) << AK;
302 
303     return false;
304   }
305 
306   if (!Ptr.isLive()) {
307     const auto &Src = S.Current->getSource(OpPC);
308 
309     if (Ptr.isDynamic()) {
310       S.FFDiag(Src, diag::note_constexpr_access_deleted_object) << AK;
311     } else {
312       bool IsTemp = Ptr.isTemporary();
313       S.FFDiag(Src, diag::note_constexpr_lifetime_ended, 1) << AK << !IsTemp;
314 
315       if (IsTemp)
316         S.Note(Ptr.getDeclLoc(), diag::note_constexpr_temporary_here);
317       else
318         S.Note(Ptr.getDeclLoc(), diag::note_declared_at);
319     }
320 
321     return false;
322   }
323 
324   return true;
325 }
326 
327 bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc) {
328   assert(Desc);
329 
330   const auto *D = Desc->asVarDecl();
331   if (!D || !D->hasGlobalStorage())
332     return true;
333 
334   if (D == S.EvaluatingDecl)
335     return true;
336 
337   if (D->isConstexpr())
338     return true;
339 
340   QualType T = D->getType();
341   bool IsConstant = T.isConstant(S.getASTContext());
342   if (T->isIntegralOrEnumerationType()) {
343     if (!IsConstant) {
344       diagnoseNonConstVariable(S, OpPC, D);
345       return false;
346     }
347     return true;
348   }
349 
350   if (IsConstant) {
351     if (S.getLangOpts().CPlusPlus) {
352       S.CCEDiag(S.Current->getLocation(OpPC),
353                 S.getLangOpts().CPlusPlus11
354                     ? diag::note_constexpr_ltor_non_constexpr
355                     : diag::note_constexpr_ltor_non_integral,
356                 1)
357           << D << T;
358       S.Note(D->getLocation(), diag::note_declared_at);
359     } else {
360       S.CCEDiag(S.Current->getLocation(OpPC));
361     }
362     return true;
363   }
364 
365   if (T->isPointerOrReferenceType()) {
366     if (!T->getPointeeType().isConstant(S.getASTContext()) ||
367         !S.getLangOpts().CPlusPlus11) {
368       diagnoseNonConstVariable(S, OpPC, D);
369       return false;
370     }
371     return true;
372   }
373 
374   diagnoseNonConstVariable(S, OpPC, D);
375   return false;
376 }
377 
378 static bool CheckConstant(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
379   if (!Ptr.isBlockPointer())
380     return true;
381   return CheckConstant(S, OpPC, Ptr.getDeclDesc());
382 }
383 
384 bool CheckNull(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
385                CheckSubobjectKind CSK) {
386   if (!Ptr.isZero())
387     return true;
388   const SourceInfo &Loc = S.Current->getSource(OpPC);
389   S.FFDiag(Loc, diag::note_constexpr_null_subobject)
390       << CSK << S.Current->getRange(OpPC);
391 
392   return false;
393 }
394 
395 bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
396                 AccessKinds AK) {
397   if (!Ptr.isOnePastEnd())
398     return true;
399   const SourceInfo &Loc = S.Current->getSource(OpPC);
400   S.FFDiag(Loc, diag::note_constexpr_access_past_end)
401       << AK << S.Current->getRange(OpPC);
402   return false;
403 }
404 
405 bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
406                 CheckSubobjectKind CSK) {
407   if (!Ptr.isElementPastEnd())
408     return true;
409   const SourceInfo &Loc = S.Current->getSource(OpPC);
410   S.FFDiag(Loc, diag::note_constexpr_past_end_subobject)
411       << CSK << S.Current->getRange(OpPC);
412   return false;
413 }
414 
415 bool CheckSubobject(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
416                     CheckSubobjectKind CSK) {
417   if (!Ptr.isOnePastEnd())
418     return true;
419 
420   const SourceInfo &Loc = S.Current->getSource(OpPC);
421   S.FFDiag(Loc, diag::note_constexpr_past_end_subobject)
422       << CSK << S.Current->getRange(OpPC);
423   return false;
424 }
425 
426 bool CheckDowncast(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
427                    uint32_t Offset) {
428   uint32_t MinOffset = Ptr.getDeclDesc()->getMetadataSize();
429   uint32_t PtrOffset = Ptr.getByteOffset();
430 
431   // We subtract Offset from PtrOffset. The result must be at least
432   // MinOffset.
433   if (Offset < PtrOffset && (PtrOffset - Offset) >= MinOffset)
434     return true;
435 
436   const auto *E = cast<CastExpr>(S.Current->getExpr(OpPC));
437   QualType TargetQT = E->getType()->getPointeeType();
438   QualType MostDerivedQT = Ptr.getDeclPtr().getType();
439 
440   S.CCEDiag(E, diag::note_constexpr_invalid_downcast)
441       << MostDerivedQT << TargetQT;
442 
443   return false;
444 }
445 
446 bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
447   assert(Ptr.isLive() && "Pointer is not live");
448   if (!Ptr.isConst() || Ptr.isMutable())
449     return true;
450 
451   // The This pointer is writable in constructors and destructors,
452   // even if isConst() returns true.
453   // TODO(perf): We could be hitting this code path quite a lot in complex
454   // constructors. Is there a better way to do this?
455   if (S.Current->getFunction()) {
456     for (const InterpFrame *Frame = S.Current; Frame; Frame = Frame->Caller) {
457       if (const Function *Func = Frame->getFunction();
458           Func && (Func->isConstructor() || Func->isDestructor()) &&
459           Ptr.block() == Frame->getThis().block()) {
460         return true;
461       }
462     }
463   }
464 
465   if (!Ptr.isBlockPointer())
466     return false;
467 
468   const QualType Ty = Ptr.getType();
469   const SourceInfo &Loc = S.Current->getSource(OpPC);
470   S.FFDiag(Loc, diag::note_constexpr_modify_const_type) << Ty;
471   return false;
472 }
473 
474 bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
475   assert(Ptr.isLive() && "Pointer is not live");
476   if (!Ptr.isMutable())
477     return true;
478 
479   // In C++14 onwards, it is permitted to read a mutable member whose
480   // lifetime began within the evaluation.
481   if (S.getLangOpts().CPlusPlus14 &&
482       Ptr.block()->getEvalID() == S.Ctx.getEvalID())
483     return true;
484 
485   const SourceInfo &Loc = S.Current->getSource(OpPC);
486   const FieldDecl *Field = Ptr.getField();
487   S.FFDiag(Loc, diag::note_constexpr_access_mutable, 1) << AK_Read << Field;
488   S.Note(Field->getLocation(), diag::note_declared_at);
489   return false;
490 }
491 
492 bool CheckVolatile(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
493                    AccessKinds AK) {
494   assert(Ptr.isLive());
495 
496   // FIXME: This check here might be kinda expensive. Maybe it would be better
497   // to have another field in InlineDescriptor for this?
498   if (!Ptr.isBlockPointer())
499     return true;
500 
501   QualType PtrType = Ptr.getType();
502   if (!PtrType.isVolatileQualified())
503     return true;
504 
505   const SourceInfo &Loc = S.Current->getSource(OpPC);
506   if (S.getLangOpts().CPlusPlus)
507     S.FFDiag(Loc, diag::note_constexpr_access_volatile_type) << AK << PtrType;
508   else
509     S.FFDiag(Loc);
510   return false;
511 }
512 
513 bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
514                       AccessKinds AK) {
515   assert(Ptr.isLive());
516 
517   if (Ptr.isInitialized())
518     return true;
519 
520   if (const auto *VD = Ptr.getDeclDesc()->asVarDecl();
521       VD && VD->hasGlobalStorage()) {
522     const SourceInfo &Loc = S.Current->getSource(OpPC);
523     if (VD->getAnyInitializer()) {
524       S.FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
525       S.Note(VD->getLocation(), diag::note_declared_at);
526     } else {
527       diagnoseMissingInitializer(S, OpPC, VD);
528     }
529     return false;
530   }
531 
532   if (!S.checkingPotentialConstantExpression()) {
533     S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_uninit)
534         << AK << /*uninitialized=*/true << S.Current->getRange(OpPC);
535   }
536   return false;
537 }
538 
539 bool CheckGlobalInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
540   if (Ptr.isInitialized())
541     return true;
542 
543   assert(S.getLangOpts().CPlusPlus);
544   const auto *VD = cast<VarDecl>(Ptr.getDeclDesc()->asValueDecl());
545   if ((!VD->hasConstantInitialization() &&
546        VD->mightBeUsableInConstantExpressions(S.getASTContext())) ||
547       (S.getLangOpts().OpenCL && !S.getLangOpts().CPlusPlus11 &&
548        !VD->hasICEInitializer(S.getASTContext()))) {
549     const SourceInfo &Loc = S.Current->getSource(OpPC);
550     S.FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
551     S.Note(VD->getLocation(), diag::note_declared_at);
552   }
553   return false;
554 }
555 
556 bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
557                AccessKinds AK) {
558   if (!CheckLive(S, OpPC, Ptr, AK))
559     return false;
560   if (!CheckConstant(S, OpPC, Ptr))
561     return false;
562 
563   if (!CheckDummy(S, OpPC, Ptr, AK))
564     return false;
565   if (!CheckExtern(S, OpPC, Ptr))
566     return false;
567   if (!CheckRange(S, OpPC, Ptr, AK))
568     return false;
569   if (!CheckActive(S, OpPC, Ptr, AK))
570     return false;
571   if (!CheckInitialized(S, OpPC, Ptr, AK))
572     return false;
573   if (!CheckTemporary(S, OpPC, Ptr, AK))
574     return false;
575   if (!CheckMutable(S, OpPC, Ptr))
576     return false;
577   if (!CheckVolatile(S, OpPC, Ptr, AK))
578     return false;
579   return true;
580 }
581 
582 /// This is not used by any of the opcodes directly. It's used by
583 /// EvalEmitter to do the final lvalue-to-rvalue conversion.
584 bool CheckFinalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
585   if (!CheckLive(S, OpPC, Ptr, AK_Read))
586     return false;
587   if (!CheckConstant(S, OpPC, Ptr))
588     return false;
589 
590   if (!CheckDummy(S, OpPC, Ptr, AK_Read))
591     return false;
592   if (!CheckExtern(S, OpPC, Ptr))
593     return false;
594   if (!CheckRange(S, OpPC, Ptr, AK_Read))
595     return false;
596   if (!CheckActive(S, OpPC, Ptr, AK_Read))
597     return false;
598   if (!CheckInitialized(S, OpPC, Ptr, AK_Read))
599     return false;
600   if (!CheckTemporary(S, OpPC, Ptr, AK_Read))
601     return false;
602   if (!CheckMutable(S, OpPC, Ptr))
603     return false;
604   return true;
605 }
606 
607 bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
608   if (!CheckLive(S, OpPC, Ptr, AK_Assign))
609     return false;
610   if (!CheckDummy(S, OpPC, Ptr, AK_Assign))
611     return false;
612   if (!CheckExtern(S, OpPC, Ptr))
613     return false;
614   if (!CheckRange(S, OpPC, Ptr, AK_Assign))
615     return false;
616   if (!CheckGlobal(S, OpPC, Ptr))
617     return false;
618   if (!CheckConst(S, OpPC, Ptr))
619     return false;
620   return true;
621 }
622 
623 bool CheckInvoke(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
624   if (!CheckLive(S, OpPC, Ptr, AK_MemberCall))
625     return false;
626   if (!Ptr.isDummy()) {
627     if (!CheckExtern(S, OpPC, Ptr))
628       return false;
629     if (!CheckRange(S, OpPC, Ptr, AK_MemberCall))
630       return false;
631   }
632   return true;
633 }
634 
635 bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
636   if (!CheckLive(S, OpPC, Ptr, AK_Assign))
637     return false;
638   if (!CheckRange(S, OpPC, Ptr, AK_Assign))
639     return false;
640   return true;
641 }
642 
643 bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) {
644 
645   if (F->isVirtual() && !S.getLangOpts().CPlusPlus20) {
646     const SourceLocation &Loc = S.Current->getLocation(OpPC);
647     S.CCEDiag(Loc, diag::note_constexpr_virtual_call);
648     return false;
649   }
650 
651   if (F->isConstexpr() && F->hasBody() &&
652       (F->getDecl()->isConstexpr() || F->getDecl()->hasAttr<MSConstexprAttr>()))
653     return true;
654 
655   // Implicitly constexpr.
656   if (F->isLambdaStaticInvoker())
657     return true;
658 
659   const SourceLocation &Loc = S.Current->getLocation(OpPC);
660   if (S.getLangOpts().CPlusPlus11) {
661     const FunctionDecl *DiagDecl = F->getDecl();
662 
663     // Invalid decls have been diagnosed before.
664     if (DiagDecl->isInvalidDecl())
665       return false;
666 
667     // If this function is not constexpr because it is an inherited
668     // non-constexpr constructor, diagnose that directly.
669     const auto *CD = dyn_cast<CXXConstructorDecl>(DiagDecl);
670     if (CD && CD->isInheritingConstructor()) {
671       const auto *Inherited = CD->getInheritedConstructor().getConstructor();
672       if (!Inherited->isConstexpr())
673         DiagDecl = CD = Inherited;
674     }
675 
676     // FIXME: If DiagDecl is an implicitly-declared special member function
677     // or an inheriting constructor, we should be much more explicit about why
678     // it's not constexpr.
679     if (CD && CD->isInheritingConstructor()) {
680       S.FFDiag(Loc, diag::note_constexpr_invalid_inhctor, 1)
681           << CD->getInheritedConstructor().getConstructor()->getParent();
682       S.Note(DiagDecl->getLocation(), diag::note_declared_at);
683     } else {
684       // Don't emit anything if the function isn't defined and we're checking
685       // for a constant expression. It might be defined at the point we're
686       // actually calling it.
687       bool IsExtern = DiagDecl->getStorageClass() == SC_Extern;
688       if (!DiagDecl->isDefined() && !IsExtern && DiagDecl->isConstexpr() &&
689           S.checkingPotentialConstantExpression())
690         return false;
691 
692       // If the declaration is defined, declared 'constexpr' _and_ has a body,
693       // the below diagnostic doesn't add anything useful.
694       if (DiagDecl->isDefined() && DiagDecl->isConstexpr() &&
695           DiagDecl->hasBody())
696         return false;
697 
698       S.FFDiag(Loc, diag::note_constexpr_invalid_function, 1)
699           << DiagDecl->isConstexpr() << (bool)CD << DiagDecl;
700 
701       if (DiagDecl->getDefinition())
702         S.Note(DiagDecl->getDefinition()->getLocation(),
703                diag::note_declared_at);
704       else
705         S.Note(DiagDecl->getLocation(), diag::note_declared_at);
706     }
707   } else {
708     S.FFDiag(Loc, diag::note_invalid_subexpr_in_const_expr);
709   }
710 
711   return false;
712 }
713 
714 bool CheckCallDepth(InterpState &S, CodePtr OpPC) {
715   if ((S.Current->getDepth() + 1) > S.getLangOpts().ConstexprCallDepth) {
716     S.FFDiag(S.Current->getSource(OpPC),
717              diag::note_constexpr_depth_limit_exceeded)
718         << S.getLangOpts().ConstexprCallDepth;
719     return false;
720   }
721 
722   return true;
723 }
724 
725 bool CheckThis(InterpState &S, CodePtr OpPC, const Pointer &This) {
726   if (!This.isZero())
727     return true;
728 
729   const SourceInfo &Loc = S.Current->getSource(OpPC);
730 
731   bool IsImplicit = false;
732   if (const auto *E = dyn_cast_if_present<CXXThisExpr>(Loc.asExpr()))
733     IsImplicit = E->isImplicit();
734 
735   if (S.getLangOpts().CPlusPlus11)
736     S.FFDiag(Loc, diag::note_constexpr_this) << IsImplicit;
737   else
738     S.FFDiag(Loc);
739 
740   return false;
741 }
742 
743 bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD) {
744   if (!MD->isPureVirtual())
745     return true;
746   const SourceInfo &E = S.Current->getSource(OpPC);
747   S.FFDiag(E, diag::note_constexpr_pure_virtual_call, 1) << MD;
748   S.Note(MD->getLocation(), diag::note_declared_at);
749   return false;
750 }
751 
752 bool CheckFloatResult(InterpState &S, CodePtr OpPC, const Floating &Result,
753                       APFloat::opStatus Status) {
754   const SourceInfo &E = S.Current->getSource(OpPC);
755 
756   // [expr.pre]p4:
757   //   If during the evaluation of an expression, the result is not
758   //   mathematically defined [...], the behavior is undefined.
759   // FIXME: C++ rules require us to not conform to IEEE 754 here.
760   if (Result.isNan()) {
761     S.CCEDiag(E, diag::note_constexpr_float_arithmetic)
762         << /*NaN=*/true << S.Current->getRange(OpPC);
763     return S.noteUndefinedBehavior();
764   }
765 
766   // In a constant context, assume that any dynamic rounding mode or FP
767   // exception state matches the default floating-point environment.
768   if (S.inConstantContext())
769     return true;
770 
771   FPOptions FPO = E.asExpr()->getFPFeaturesInEffect(S.Ctx.getLangOpts());
772 
773   if ((Status & APFloat::opInexact) &&
774       FPO.getRoundingMode() == llvm::RoundingMode::Dynamic) {
775     // Inexact result means that it depends on rounding mode. If the requested
776     // mode is dynamic, the evaluation cannot be made in compile time.
777     S.FFDiag(E, diag::note_constexpr_dynamic_rounding);
778     return false;
779   }
780 
781   if ((Status != APFloat::opOK) &&
782       (FPO.getRoundingMode() == llvm::RoundingMode::Dynamic ||
783        FPO.getExceptionMode() != LangOptions::FPE_Ignore ||
784        FPO.getAllowFEnvAccess())) {
785     S.FFDiag(E, diag::note_constexpr_float_arithmetic_strict);
786     return false;
787   }
788 
789   if ((Status & APFloat::opStatus::opInvalidOp) &&
790       FPO.getExceptionMode() != LangOptions::FPE_Ignore) {
791     // There is no usefully definable result.
792     S.FFDiag(E);
793     return false;
794   }
795 
796   return true;
797 }
798 
799 bool CheckDynamicMemoryAllocation(InterpState &S, CodePtr OpPC) {
800   if (S.getLangOpts().CPlusPlus20)
801     return true;
802 
803   const SourceInfo &E = S.Current->getSource(OpPC);
804   S.CCEDiag(E, diag::note_constexpr_new);
805   return true;
806 }
807 
808 bool CheckNewDeleteForms(InterpState &S, CodePtr OpPC, bool NewWasArray,
809                          bool DeleteIsArray, const Descriptor *D,
810                          const Expr *NewExpr) {
811   if (NewWasArray == DeleteIsArray)
812     return true;
813 
814   QualType TypeToDiagnose;
815   // We need to shuffle things around a bit here to get a better diagnostic,
816   // because the expression we allocated the block for was of type int*,
817   // but we want to get the array size right.
818   if (D->isArray()) {
819     QualType ElemQT = D->getType()->getPointeeType();
820     TypeToDiagnose = S.getASTContext().getConstantArrayType(
821         ElemQT, APInt(64, static_cast<uint64_t>(D->getNumElems()), false),
822         nullptr, ArraySizeModifier::Normal, 0);
823   } else
824     TypeToDiagnose = D->getType()->getPointeeType();
825 
826   const SourceInfo &E = S.Current->getSource(OpPC);
827   S.FFDiag(E, diag::note_constexpr_new_delete_mismatch)
828       << DeleteIsArray << 0 << TypeToDiagnose;
829   S.Note(NewExpr->getExprLoc(), diag::note_constexpr_dynamic_alloc_here)
830       << NewExpr->getSourceRange();
831   return false;
832 }
833 
834 bool CheckDeleteSource(InterpState &S, CodePtr OpPC, const Expr *Source,
835                        const Pointer &Ptr) {
836   if (Source && isa<CXXNewExpr>(Source))
837     return true;
838 
839   // Whatever this is, we didn't heap allocate it.
840   const SourceInfo &Loc = S.Current->getSource(OpPC);
841   S.FFDiag(Loc, diag::note_constexpr_delete_not_heap_alloc)
842       << Ptr.toDiagnosticString(S.getASTContext());
843 
844   if (Ptr.isTemporary())
845     S.Note(Ptr.getDeclLoc(), diag::note_constexpr_temporary_here);
846   else
847     S.Note(Ptr.getDeclLoc(), diag::note_declared_at);
848   return false;
849 }
850 
851 /// We aleady know the given DeclRefExpr is invalid for some reason,
852 /// now figure out why and print appropriate diagnostics.
853 bool CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR) {
854   const ValueDecl *D = DR->getDecl();
855   return diagnoseUnknownDecl(S, OpPC, D);
856 }
857 
858 bool CheckDummy(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
859                 AccessKinds AK) {
860   if (!Ptr.isDummy())
861     return true;
862 
863   const Descriptor *Desc = Ptr.getDeclDesc();
864   const ValueDecl *D = Desc->asValueDecl();
865   if (!D)
866     return false;
867 
868   if (AK == AK_Read || AK == AK_Increment || AK == AK_Decrement)
869     return diagnoseUnknownDecl(S, OpPC, D);
870 
871   assert(AK == AK_Assign);
872   if (S.getLangOpts().CPlusPlus11) {
873     const SourceInfo &E = S.Current->getSource(OpPC);
874     S.FFDiag(E, diag::note_constexpr_modify_global);
875   }
876   return false;
877 }
878 
879 bool CheckNonNullArgs(InterpState &S, CodePtr OpPC, const Function *F,
880                       const CallExpr *CE, unsigned ArgSize) {
881   auto Args = llvm::ArrayRef(CE->getArgs(), CE->getNumArgs());
882   auto NonNullArgs = collectNonNullArgs(F->getDecl(), Args);
883   unsigned Offset = 0;
884   unsigned Index = 0;
885   for (const Expr *Arg : Args) {
886     if (NonNullArgs[Index] && Arg->getType()->isPointerType()) {
887       const Pointer &ArgPtr = S.Stk.peek<Pointer>(ArgSize - Offset);
888       if (ArgPtr.isZero()) {
889         const SourceLocation &Loc = S.Current->getLocation(OpPC);
890         S.CCEDiag(Loc, diag::note_non_null_attribute_failed);
891         return false;
892       }
893     }
894 
895     Offset += align(primSize(S.Ctx.classify(Arg).value_or(PT_Ptr)));
896     ++Index;
897   }
898   return true;
899 }
900 
901 // FIXME: This is similar to code we already have in Compiler.cpp.
902 // I think it makes sense to instead add the field and base destruction stuff
903 // to the destructor Function itself. Then destroying a record would really
904 // _just_ be calling its destructor. That would also help with the diagnostic
905 // difference when the destructor or a field/base fails.
906 static bool runRecordDestructor(InterpState &S, CodePtr OpPC,
907                                 const Pointer &BasePtr,
908                                 const Descriptor *Desc) {
909   assert(Desc->isRecord());
910   const Record *R = Desc->ElemRecord;
911   assert(R);
912 
913   if (Pointer::pointToSameBlock(BasePtr, S.Current->getThis())) {
914     const SourceInfo &Loc = S.Current->getSource(OpPC);
915     S.FFDiag(Loc, diag::note_constexpr_double_destroy);
916     return false;
917   }
918 
919   // Destructor of this record.
920   if (const CXXDestructorDecl *Dtor = R->getDestructor();
921       Dtor && !Dtor->isTrivial()) {
922     const Function *DtorFunc = S.getContext().getOrCreateFunction(Dtor);
923     if (!DtorFunc)
924       return false;
925 
926     S.Stk.push<Pointer>(BasePtr);
927     if (!Call(S, OpPC, DtorFunc, 0))
928       return false;
929   }
930   return true;
931 }
932 
933 bool RunDestructors(InterpState &S, CodePtr OpPC, const Block *B) {
934   assert(B);
935   const Descriptor *Desc = B->getDescriptor();
936 
937   if (Desc->isPrimitive() || Desc->isPrimitiveArray())
938     return true;
939 
940   assert(Desc->isRecord() || Desc->isCompositeArray());
941 
942   if (Desc->isCompositeArray()) {
943     const Descriptor *ElemDesc = Desc->ElemDesc;
944     assert(ElemDesc->isRecord());
945 
946     Pointer RP(const_cast<Block *>(B));
947     for (unsigned I = 0; I != Desc->getNumElems(); ++I) {
948       if (!runRecordDestructor(S, OpPC, RP.atIndex(I).narrow(), ElemDesc))
949         return false;
950     }
951     return true;
952   }
953 
954   assert(Desc->isRecord());
955   return runRecordDestructor(S, OpPC, Pointer(const_cast<Block *>(B)), Desc);
956 }
957 
958 void diagnoseEnumValue(InterpState &S, CodePtr OpPC, const EnumDecl *ED,
959                        const APSInt &Value) {
960   llvm::APInt Min;
961   llvm::APInt Max;
962 
963   if (S.EvaluatingDecl && !S.EvaluatingDecl->isConstexpr())
964     return;
965 
966   ED->getValueRange(Max, Min);
967   --Max;
968 
969   if (ED->getNumNegativeBits() &&
970       (Max.slt(Value.getSExtValue()) || Min.sgt(Value.getSExtValue()))) {
971     const SourceLocation &Loc = S.Current->getLocation(OpPC);
972     S.CCEDiag(Loc, diag::note_constexpr_unscoped_enum_out_of_range)
973         << llvm::toString(Value, 10) << Min.getSExtValue() << Max.getSExtValue()
974         << ED;
975   } else if (!ED->getNumNegativeBits() && Max.ult(Value.getZExtValue())) {
976     const SourceLocation &Loc = S.Current->getLocation(OpPC);
977     S.CCEDiag(Loc, diag::note_constexpr_unscoped_enum_out_of_range)
978         << llvm::toString(Value, 10) << Min.getZExtValue() << Max.getZExtValue()
979         << ED;
980   }
981 }
982 
983 bool Interpret(InterpState &S, APValue &Result) {
984   // The current stack frame when we started Interpret().
985   // This is being used by the ops to determine wheter
986   // to return from this function and thus terminate
987   // interpretation.
988   const InterpFrame *StartFrame = S.Current;
989   assert(!S.Current->isRoot());
990   CodePtr PC = S.Current->getPC();
991 
992   // Empty program.
993   if (!PC)
994     return true;
995 
996   for (;;) {
997     auto Op = PC.read<Opcode>();
998     CodePtr OpPC = PC;
999 
1000     switch (Op) {
1001 #define GET_INTERP
1002 #include "Opcodes.inc"
1003 #undef GET_INTERP
1004     }
1005   }
1006 }
1007 
1008 } // namespace interp
1009 } // namespace clang
1010