xref: /netbsd-src/external/apache2/llvm/dist/clang/lib/AST/Interp/Interp.cpp (revision e038c9c4676b0f19b1b7dd08a940c6ed64a6d5ae)
17330f729Sjoerg //===--- InterpState.cpp - Interpreter for the constexpr VM -----*- C++ -*-===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg 
97330f729Sjoerg #include "Interp.h"
107330f729Sjoerg #include <limits>
117330f729Sjoerg #include <vector>
127330f729Sjoerg #include "Function.h"
137330f729Sjoerg #include "InterpFrame.h"
147330f729Sjoerg #include "InterpStack.h"
157330f729Sjoerg #include "Opcode.h"
167330f729Sjoerg #include "PrimType.h"
177330f729Sjoerg #include "Program.h"
187330f729Sjoerg #include "State.h"
197330f729Sjoerg #include "clang/AST/ASTContext.h"
207330f729Sjoerg #include "clang/AST/ASTDiagnostic.h"
217330f729Sjoerg #include "clang/AST/CXXInheritance.h"
227330f729Sjoerg #include "clang/AST/Expr.h"
237330f729Sjoerg #include "clang/AST/ExprCXX.h"
247330f729Sjoerg #include "llvm/ADT/APSInt.h"
257330f729Sjoerg 
267330f729Sjoerg using namespace clang;
277330f729Sjoerg using namespace clang::interp;
287330f729Sjoerg 
297330f729Sjoerg //===----------------------------------------------------------------------===//
307330f729Sjoerg // Ret
317330f729Sjoerg //===----------------------------------------------------------------------===//
327330f729Sjoerg 
337330f729Sjoerg template <PrimType Name, class T = typename PrimConv<Name>::T>
Ret(InterpState & S,CodePtr & PC,APValue & Result)347330f729Sjoerg static bool Ret(InterpState &S, CodePtr &PC, APValue &Result) {
357330f729Sjoerg   S.CallStackDepth--;
367330f729Sjoerg   const T &Ret = S.Stk.pop<T>();
377330f729Sjoerg 
387330f729Sjoerg   assert(S.Current->getFrameOffset() == S.Stk.size() && "Invalid frame");
397330f729Sjoerg   if (!S.checkingPotentialConstantExpression())
407330f729Sjoerg     S.Current->popArgs();
417330f729Sjoerg 
427330f729Sjoerg   if (InterpFrame *Caller = S.Current->Caller) {
437330f729Sjoerg     PC = S.Current->getRetPC();
447330f729Sjoerg     delete S.Current;
457330f729Sjoerg     S.Current = Caller;
467330f729Sjoerg     S.Stk.push<T>(Ret);
477330f729Sjoerg   } else {
487330f729Sjoerg     delete S.Current;
497330f729Sjoerg     S.Current = nullptr;
507330f729Sjoerg     if (!ReturnValue<T>(Ret, Result))
517330f729Sjoerg       return false;
527330f729Sjoerg   }
537330f729Sjoerg   return true;
547330f729Sjoerg }
557330f729Sjoerg 
RetVoid(InterpState & S,CodePtr & PC,APValue & Result)567330f729Sjoerg static bool RetVoid(InterpState &S, CodePtr &PC, APValue &Result) {
577330f729Sjoerg   S.CallStackDepth--;
587330f729Sjoerg 
597330f729Sjoerg   assert(S.Current->getFrameOffset() == S.Stk.size() && "Invalid frame");
607330f729Sjoerg   if (!S.checkingPotentialConstantExpression())
617330f729Sjoerg     S.Current->popArgs();
627330f729Sjoerg 
637330f729Sjoerg   if (InterpFrame *Caller = S.Current->Caller) {
647330f729Sjoerg     PC = S.Current->getRetPC();
657330f729Sjoerg     delete S.Current;
667330f729Sjoerg     S.Current = Caller;
677330f729Sjoerg   } else {
687330f729Sjoerg     delete S.Current;
697330f729Sjoerg     S.Current = nullptr;
707330f729Sjoerg   }
717330f729Sjoerg   return true;
727330f729Sjoerg }
737330f729Sjoerg 
RetValue(InterpState & S,CodePtr & Pt,APValue & Result)747330f729Sjoerg static bool RetValue(InterpState &S, CodePtr &Pt, APValue &Result) {
757330f729Sjoerg   llvm::report_fatal_error("Interpreter cannot return values");
767330f729Sjoerg }
777330f729Sjoerg 
787330f729Sjoerg //===----------------------------------------------------------------------===//
797330f729Sjoerg // Jmp, Jt, Jf
807330f729Sjoerg //===----------------------------------------------------------------------===//
817330f729Sjoerg 
Jmp(InterpState & S,CodePtr & PC,int32_t Offset)827330f729Sjoerg static bool Jmp(InterpState &S, CodePtr &PC, int32_t Offset) {
837330f729Sjoerg   PC += Offset;
847330f729Sjoerg   return true;
857330f729Sjoerg }
867330f729Sjoerg 
Jt(InterpState & S,CodePtr & PC,int32_t Offset)877330f729Sjoerg static bool Jt(InterpState &S, CodePtr &PC, int32_t Offset) {
887330f729Sjoerg   if (S.Stk.pop<bool>()) {
897330f729Sjoerg     PC += Offset;
907330f729Sjoerg   }
917330f729Sjoerg   return true;
927330f729Sjoerg }
937330f729Sjoerg 
Jf(InterpState & S,CodePtr & PC,int32_t Offset)947330f729Sjoerg static bool Jf(InterpState &S, CodePtr &PC, int32_t Offset) {
957330f729Sjoerg   if (!S.Stk.pop<bool>()) {
967330f729Sjoerg     PC += Offset;
977330f729Sjoerg   }
987330f729Sjoerg   return true;
997330f729Sjoerg }
1007330f729Sjoerg 
CheckInitialized(InterpState & S,CodePtr OpPC,const Pointer & Ptr,AccessKinds AK)1017330f729Sjoerg static bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
1027330f729Sjoerg                              AccessKinds AK) {
1037330f729Sjoerg   if (Ptr.isInitialized())
1047330f729Sjoerg     return true;
1057330f729Sjoerg   if (!S.checkingPotentialConstantExpression()) {
1067330f729Sjoerg     const SourceInfo &Loc = S.Current->getSource(OpPC);
1077330f729Sjoerg     S.FFDiag(Loc, diag::note_constexpr_access_uninit) << AK << false;
1087330f729Sjoerg   }
1097330f729Sjoerg   return false;
1107330f729Sjoerg }
1117330f729Sjoerg 
CheckActive(InterpState & S,CodePtr OpPC,const Pointer & Ptr,AccessKinds AK)1127330f729Sjoerg static bool CheckActive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
1137330f729Sjoerg                         AccessKinds AK) {
1147330f729Sjoerg   if (Ptr.isActive())
1157330f729Sjoerg     return true;
1167330f729Sjoerg 
1177330f729Sjoerg   // Get the inactive field descriptor.
1187330f729Sjoerg   const FieldDecl *InactiveField = Ptr.getField();
1197330f729Sjoerg 
1207330f729Sjoerg   // Walk up the pointer chain to find the union which is not active.
1217330f729Sjoerg   Pointer U = Ptr.getBase();
1227330f729Sjoerg   while (!U.isActive()) {
1237330f729Sjoerg     U = U.getBase();
1247330f729Sjoerg   }
1257330f729Sjoerg 
1267330f729Sjoerg   // Find the active field of the union.
1277330f729Sjoerg   Record *R = U.getRecord();
1287330f729Sjoerg   assert(R && R->isUnion() && "Not a union");
1297330f729Sjoerg   const FieldDecl *ActiveField = nullptr;
1307330f729Sjoerg   for (unsigned I = 0, N = R->getNumFields(); I < N; ++I) {
1317330f729Sjoerg     const Pointer &Field = U.atField(R->getField(I)->Offset);
1327330f729Sjoerg     if (Field.isActive()) {
1337330f729Sjoerg       ActiveField = Field.getField();
1347330f729Sjoerg       break;
1357330f729Sjoerg     }
1367330f729Sjoerg   }
1377330f729Sjoerg 
1387330f729Sjoerg   const SourceInfo &Loc = S.Current->getSource(OpPC);
1397330f729Sjoerg   S.FFDiag(Loc, diag::note_constexpr_access_inactive_union_member)
1407330f729Sjoerg       << AK << InactiveField << !ActiveField << ActiveField;
1417330f729Sjoerg   return false;
1427330f729Sjoerg }
1437330f729Sjoerg 
CheckTemporary(InterpState & S,CodePtr OpPC,const Pointer & Ptr,AccessKinds AK)1447330f729Sjoerg static bool CheckTemporary(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
1457330f729Sjoerg                            AccessKinds AK) {
1467330f729Sjoerg   if (auto ID = Ptr.getDeclID()) {
1477330f729Sjoerg     if (!Ptr.isStaticTemporary())
1487330f729Sjoerg       return true;
1497330f729Sjoerg 
1507330f729Sjoerg     if (Ptr.getDeclDesc()->getType().isConstQualified())
1517330f729Sjoerg       return true;
1527330f729Sjoerg 
1537330f729Sjoerg     if (S.P.getCurrentDecl() == ID)
1547330f729Sjoerg       return true;
1557330f729Sjoerg 
1567330f729Sjoerg     const SourceInfo &E = S.Current->getSource(OpPC);
1577330f729Sjoerg     S.FFDiag(E, diag::note_constexpr_access_static_temporary, 1) << AK;
1587330f729Sjoerg     S.Note(Ptr.getDeclLoc(), diag::note_constexpr_temporary_here);
1597330f729Sjoerg     return false;
1607330f729Sjoerg   }
1617330f729Sjoerg   return true;
1627330f729Sjoerg }
1637330f729Sjoerg 
CheckGlobal(InterpState & S,CodePtr OpPC,const Pointer & Ptr)1647330f729Sjoerg static bool CheckGlobal(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
1657330f729Sjoerg   if (auto ID = Ptr.getDeclID()) {
1667330f729Sjoerg     if (!Ptr.isStatic())
1677330f729Sjoerg       return true;
1687330f729Sjoerg 
1697330f729Sjoerg     if (S.P.getCurrentDecl() == ID)
1707330f729Sjoerg       return true;
1717330f729Sjoerg 
1727330f729Sjoerg     S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_modify_global);
1737330f729Sjoerg     return false;
1747330f729Sjoerg   }
1757330f729Sjoerg   return true;
1767330f729Sjoerg }
1777330f729Sjoerg 
1787330f729Sjoerg namespace clang {
1797330f729Sjoerg namespace interp {
1807330f729Sjoerg 
CheckExtern(InterpState & S,CodePtr OpPC,const Pointer & Ptr)1817330f729Sjoerg bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
1827330f729Sjoerg   if (!Ptr.isExtern())
1837330f729Sjoerg     return true;
1847330f729Sjoerg 
1857330f729Sjoerg   if (!S.checkingPotentialConstantExpression()) {
1867330f729Sjoerg     auto *VD = Ptr.getDeclDesc()->asValueDecl();
1877330f729Sjoerg     const SourceInfo &Loc = S.Current->getSource(OpPC);
1887330f729Sjoerg     S.FFDiag(Loc, diag::note_constexpr_ltor_non_constexpr, 1) << VD;
1897330f729Sjoerg     S.Note(VD->getLocation(), diag::note_declared_at);
1907330f729Sjoerg   }
1917330f729Sjoerg   return false;
1927330f729Sjoerg }
1937330f729Sjoerg 
CheckArray(InterpState & S,CodePtr OpPC,const Pointer & Ptr)1947330f729Sjoerg bool CheckArray(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
1957330f729Sjoerg   if (!Ptr.isUnknownSizeArray())
1967330f729Sjoerg     return true;
1977330f729Sjoerg   const SourceInfo &E = S.Current->getSource(OpPC);
1987330f729Sjoerg   S.FFDiag(E, diag::note_constexpr_unsized_array_indexed);
1997330f729Sjoerg   return false;
2007330f729Sjoerg }
2017330f729Sjoerg 
CheckLive(InterpState & S,CodePtr OpPC,const Pointer & Ptr,AccessKinds AK)2027330f729Sjoerg bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
2037330f729Sjoerg                AccessKinds AK) {
2047330f729Sjoerg   const auto &Src = S.Current->getSource(OpPC);
2057330f729Sjoerg   if (Ptr.isZero()) {
2067330f729Sjoerg 
2077330f729Sjoerg     if (Ptr.isField())
2087330f729Sjoerg       S.FFDiag(Src, diag::note_constexpr_null_subobject) << CSK_Field;
2097330f729Sjoerg     else
2107330f729Sjoerg       S.FFDiag(Src, diag::note_constexpr_access_null) << AK;
2117330f729Sjoerg 
2127330f729Sjoerg     return false;
2137330f729Sjoerg   }
2147330f729Sjoerg 
2157330f729Sjoerg   if (!Ptr.isLive()) {
2167330f729Sjoerg     bool IsTemp = Ptr.isTemporary();
2177330f729Sjoerg 
2187330f729Sjoerg     S.FFDiag(Src, diag::note_constexpr_lifetime_ended, 1) << AK << !IsTemp;
2197330f729Sjoerg 
2207330f729Sjoerg     if (IsTemp)
2217330f729Sjoerg       S.Note(Ptr.getDeclLoc(), diag::note_constexpr_temporary_here);
2227330f729Sjoerg     else
2237330f729Sjoerg       S.Note(Ptr.getDeclLoc(), diag::note_declared_at);
2247330f729Sjoerg 
2257330f729Sjoerg     return false;
2267330f729Sjoerg   }
2277330f729Sjoerg 
2287330f729Sjoerg   return true;
2297330f729Sjoerg }
2307330f729Sjoerg 
CheckNull(InterpState & S,CodePtr OpPC,const Pointer & Ptr,CheckSubobjectKind CSK)2317330f729Sjoerg bool CheckNull(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
2327330f729Sjoerg                CheckSubobjectKind CSK) {
2337330f729Sjoerg   if (!Ptr.isZero())
2347330f729Sjoerg     return true;
2357330f729Sjoerg   const SourceInfo &Loc = S.Current->getSource(OpPC);
2367330f729Sjoerg   S.FFDiag(Loc, diag::note_constexpr_null_subobject) << CSK;
2377330f729Sjoerg   return false;
2387330f729Sjoerg }
2397330f729Sjoerg 
CheckRange(InterpState & S,CodePtr OpPC,const Pointer & Ptr,AccessKinds AK)2407330f729Sjoerg bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
2417330f729Sjoerg                 AccessKinds AK) {
2427330f729Sjoerg   if (!Ptr.isOnePastEnd())
2437330f729Sjoerg     return true;
2447330f729Sjoerg   const SourceInfo &Loc = S.Current->getSource(OpPC);
2457330f729Sjoerg   S.FFDiag(Loc, diag::note_constexpr_access_past_end) << AK;
2467330f729Sjoerg   return false;
2477330f729Sjoerg }
2487330f729Sjoerg 
CheckRange(InterpState & S,CodePtr OpPC,const Pointer & Ptr,CheckSubobjectKind CSK)2497330f729Sjoerg bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
2507330f729Sjoerg                 CheckSubobjectKind CSK) {
2517330f729Sjoerg   if (!Ptr.isElementPastEnd())
2527330f729Sjoerg     return true;
2537330f729Sjoerg   const SourceInfo &Loc = S.Current->getSource(OpPC);
2547330f729Sjoerg   S.FFDiag(Loc, diag::note_constexpr_past_end_subobject) << CSK;
2557330f729Sjoerg   return false;
2567330f729Sjoerg }
2577330f729Sjoerg 
CheckConst(InterpState & S,CodePtr OpPC,const Pointer & Ptr)2587330f729Sjoerg bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
2597330f729Sjoerg   assert(Ptr.isLive() && "Pointer is not live");
2607330f729Sjoerg   if (!Ptr.isConst()) {
2617330f729Sjoerg     return true;
2627330f729Sjoerg   }
2637330f729Sjoerg 
2647330f729Sjoerg   const QualType Ty = Ptr.getType();
2657330f729Sjoerg   const SourceInfo &Loc = S.Current->getSource(OpPC);
2667330f729Sjoerg   S.FFDiag(Loc, diag::note_constexpr_modify_const_type) << Ty;
2677330f729Sjoerg   return false;
2687330f729Sjoerg }
2697330f729Sjoerg 
CheckMutable(InterpState & S,CodePtr OpPC,const Pointer & Ptr)2707330f729Sjoerg bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
2717330f729Sjoerg   assert(Ptr.isLive() && "Pointer is not live");
2727330f729Sjoerg   if (!Ptr.isMutable()) {
2737330f729Sjoerg     return true;
2747330f729Sjoerg   }
2757330f729Sjoerg 
2767330f729Sjoerg   const SourceInfo &Loc = S.Current->getSource(OpPC);
2777330f729Sjoerg   const FieldDecl *Field = Ptr.getField();
2787330f729Sjoerg   S.FFDiag(Loc, diag::note_constexpr_access_mutable, 1) << AK_Read << Field;
2797330f729Sjoerg   S.Note(Field->getLocation(), diag::note_declared_at);
2807330f729Sjoerg   return false;
2817330f729Sjoerg }
2827330f729Sjoerg 
CheckLoad(InterpState & S,CodePtr OpPC,const Pointer & Ptr)2837330f729Sjoerg bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
2847330f729Sjoerg   if (!CheckLive(S, OpPC, Ptr, AK_Read))
2857330f729Sjoerg     return false;
2867330f729Sjoerg   if (!CheckExtern(S, OpPC, Ptr))
2877330f729Sjoerg     return false;
2887330f729Sjoerg   if (!CheckRange(S, OpPC, Ptr, AK_Read))
2897330f729Sjoerg     return false;
2907330f729Sjoerg   if (!CheckInitialized(S, OpPC, Ptr, AK_Read))
2917330f729Sjoerg     return false;
2927330f729Sjoerg   if (!CheckActive(S, OpPC, Ptr, AK_Read))
2937330f729Sjoerg     return false;
2947330f729Sjoerg   if (!CheckTemporary(S, OpPC, Ptr, AK_Read))
2957330f729Sjoerg     return false;
2967330f729Sjoerg   if (!CheckMutable(S, OpPC, Ptr))
2977330f729Sjoerg     return false;
2987330f729Sjoerg   return true;
2997330f729Sjoerg }
3007330f729Sjoerg 
CheckStore(InterpState & S,CodePtr OpPC,const Pointer & Ptr)3017330f729Sjoerg bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
3027330f729Sjoerg   if (!CheckLive(S, OpPC, Ptr, AK_Assign))
3037330f729Sjoerg     return false;
3047330f729Sjoerg   if (!CheckExtern(S, OpPC, Ptr))
3057330f729Sjoerg     return false;
3067330f729Sjoerg   if (!CheckRange(S, OpPC, Ptr, AK_Assign))
3077330f729Sjoerg     return false;
3087330f729Sjoerg   if (!CheckGlobal(S, OpPC, Ptr))
3097330f729Sjoerg     return false;
3107330f729Sjoerg   if (!CheckConst(S, OpPC, Ptr))
3117330f729Sjoerg     return false;
3127330f729Sjoerg   return true;
3137330f729Sjoerg }
3147330f729Sjoerg 
CheckInvoke(InterpState & S,CodePtr OpPC,const Pointer & Ptr)3157330f729Sjoerg bool CheckInvoke(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
3167330f729Sjoerg   if (!CheckLive(S, OpPC, Ptr, AK_MemberCall))
3177330f729Sjoerg     return false;
3187330f729Sjoerg   if (!CheckExtern(S, OpPC, Ptr))
3197330f729Sjoerg     return false;
3207330f729Sjoerg   if (!CheckRange(S, OpPC, Ptr, AK_MemberCall))
3217330f729Sjoerg     return false;
3227330f729Sjoerg   return true;
3237330f729Sjoerg }
3247330f729Sjoerg 
CheckInit(InterpState & S,CodePtr OpPC,const Pointer & Ptr)3257330f729Sjoerg bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
3267330f729Sjoerg   if (!CheckLive(S, OpPC, Ptr, AK_Assign))
3277330f729Sjoerg     return false;
3287330f729Sjoerg   if (!CheckRange(S, OpPC, Ptr, AK_Assign))
3297330f729Sjoerg     return false;
3307330f729Sjoerg   return true;
3317330f729Sjoerg }
3327330f729Sjoerg 
CheckCallable(InterpState & S,CodePtr OpPC,Function * F)3337330f729Sjoerg bool CheckCallable(InterpState &S, CodePtr OpPC, Function *F) {
3347330f729Sjoerg   const SourceLocation &Loc = S.Current->getLocation(OpPC);
3357330f729Sjoerg 
3367330f729Sjoerg   if (F->isVirtual()) {
337*e038c9c4Sjoerg     if (!S.getLangOpts().CPlusPlus20) {
3387330f729Sjoerg       S.CCEDiag(Loc, diag::note_constexpr_virtual_call);
3397330f729Sjoerg       return false;
3407330f729Sjoerg     }
3417330f729Sjoerg   }
3427330f729Sjoerg 
3437330f729Sjoerg   if (!F->isConstexpr()) {
3447330f729Sjoerg     if (S.getLangOpts().CPlusPlus11) {
3457330f729Sjoerg       const FunctionDecl *DiagDecl = F->getDecl();
3467330f729Sjoerg 
3477330f729Sjoerg       // If this function is not constexpr because it is an inherited
3487330f729Sjoerg       // non-constexpr constructor, diagnose that directly.
3497330f729Sjoerg       auto *CD = dyn_cast<CXXConstructorDecl>(DiagDecl);
3507330f729Sjoerg       if (CD && CD->isInheritingConstructor()) {
3517330f729Sjoerg         auto *Inherited = CD->getInheritedConstructor().getConstructor();
3527330f729Sjoerg         if (!Inherited->isConstexpr())
3537330f729Sjoerg           DiagDecl = CD = Inherited;
3547330f729Sjoerg       }
3557330f729Sjoerg 
3567330f729Sjoerg       // FIXME: If DiagDecl is an implicitly-declared special member function
3577330f729Sjoerg       // or an inheriting constructor, we should be much more explicit about why
3587330f729Sjoerg       // it's not constexpr.
3597330f729Sjoerg       if (CD && CD->isInheritingConstructor())
3607330f729Sjoerg         S.FFDiag(Loc, diag::note_constexpr_invalid_inhctor, 1)
3617330f729Sjoerg           << CD->getInheritedConstructor().getConstructor()->getParent();
3627330f729Sjoerg       else
3637330f729Sjoerg         S.FFDiag(Loc, diag::note_constexpr_invalid_function, 1)
3647330f729Sjoerg           << DiagDecl->isConstexpr() << (bool)CD << DiagDecl;
3657330f729Sjoerg       S.Note(DiagDecl->getLocation(), diag::note_declared_at);
3667330f729Sjoerg     } else {
3677330f729Sjoerg       S.FFDiag(Loc, diag::note_invalid_subexpr_in_const_expr);
3687330f729Sjoerg     }
3697330f729Sjoerg     return false;
3707330f729Sjoerg   }
3717330f729Sjoerg 
3727330f729Sjoerg   return true;
3737330f729Sjoerg }
3747330f729Sjoerg 
CheckThis(InterpState & S,CodePtr OpPC,const Pointer & This)3757330f729Sjoerg bool CheckThis(InterpState &S, CodePtr OpPC, const Pointer &This) {
3767330f729Sjoerg   if (!This.isZero())
3777330f729Sjoerg     return true;
3787330f729Sjoerg 
3797330f729Sjoerg   const SourceInfo &Loc = S.Current->getSource(OpPC);
3807330f729Sjoerg 
3817330f729Sjoerg   bool IsImplicit = false;
3827330f729Sjoerg   if (auto *E = dyn_cast_or_null<CXXThisExpr>(Loc.asExpr()))
3837330f729Sjoerg     IsImplicit = E->isImplicit();
3847330f729Sjoerg 
3857330f729Sjoerg   if (S.getLangOpts().CPlusPlus11)
3867330f729Sjoerg     S.FFDiag(Loc, diag::note_constexpr_this) << IsImplicit;
3877330f729Sjoerg   else
3887330f729Sjoerg     S.FFDiag(Loc);
3897330f729Sjoerg 
3907330f729Sjoerg   return false;
3917330f729Sjoerg }
3927330f729Sjoerg 
CheckPure(InterpState & S,CodePtr OpPC,const CXXMethodDecl * MD)3937330f729Sjoerg bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD) {
3947330f729Sjoerg   if (!MD->isPure())
3957330f729Sjoerg     return true;
3967330f729Sjoerg   const SourceInfo &E = S.Current->getSource(OpPC);
3977330f729Sjoerg   S.FFDiag(E, diag::note_constexpr_pure_virtual_call, 1) << MD;
3987330f729Sjoerg   S.Note(MD->getLocation(), diag::note_declared_at);
3997330f729Sjoerg   return false;
4007330f729Sjoerg }
Interpret(InterpState & S,APValue & Result)4017330f729Sjoerg bool Interpret(InterpState &S, APValue &Result) {
4027330f729Sjoerg   CodePtr PC = S.Current->getPC();
4037330f729Sjoerg 
4047330f729Sjoerg   for (;;) {
4057330f729Sjoerg     auto Op = PC.read<Opcode>();
4067330f729Sjoerg     CodePtr OpPC = PC;
4077330f729Sjoerg 
4087330f729Sjoerg     switch (Op) {
4097330f729Sjoerg #define GET_INTERP
4107330f729Sjoerg #include "Opcodes.inc"
4117330f729Sjoerg #undef GET_INTERP
4127330f729Sjoerg     }
4137330f729Sjoerg   }
4147330f729Sjoerg }
4157330f729Sjoerg 
4167330f729Sjoerg } // namespace interp
4177330f729Sjoerg } // namespace clang
418