2022-12-28 12:08:29 +01:00
|
|
|
//===------- Interp.cpp - Interpreter for the constexpr VM ------*- C++ -*-===//
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
//
|
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "Interp.h"
|
|
|
|
#include <limits>
|
|
|
|
#include <vector>
|
|
|
|
#include "Function.h"
|
|
|
|
#include "InterpFrame.h"
|
|
|
|
#include "InterpStack.h"
|
|
|
|
#include "Opcode.h"
|
|
|
|
#include "PrimType.h"
|
|
|
|
#include "Program.h"
|
|
|
|
#include "State.h"
|
|
|
|
#include "clang/AST/ASTContext.h"
|
|
|
|
#include "clang/AST/ASTDiagnostic.h"
|
|
|
|
#include "clang/AST/CXXInheritance.h"
|
|
|
|
#include "clang/AST/Expr.h"
|
|
|
|
#include "clang/AST/ExprCXX.h"
|
|
|
|
#include "llvm/ADT/APSInt.h"
|
|
|
|
|
|
|
|
using namespace clang;
|
|
|
|
using namespace clang::interp;
|
|
|
|
|
|
|
|
static bool RetValue(InterpState &S, CodePtr &Pt, APValue &Result) {
|
|
|
|
llvm::report_fatal_error("Interpreter cannot return values");
|
|
|
|
}
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Jmp, Jt, Jf
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
static bool Jmp(InterpState &S, CodePtr &PC, int32_t Offset) {
|
|
|
|
PC += Offset;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool Jt(InterpState &S, CodePtr &PC, int32_t Offset) {
|
|
|
|
if (S.Stk.pop<bool>()) {
|
|
|
|
PC += Offset;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool Jf(InterpState &S, CodePtr &PC, int32_t Offset) {
|
|
|
|
if (!S.Stk.pop<bool>()) {
|
|
|
|
PC += Offset;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool CheckActive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
|
|
|
|
AccessKinds AK) {
|
|
|
|
if (Ptr.isActive())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// Get the inactive field descriptor.
|
|
|
|
const FieldDecl *InactiveField = Ptr.getField();
|
|
|
|
|
|
|
|
// Walk up the pointer chain to find the union which is not active.
|
|
|
|
Pointer U = Ptr.getBase();
|
|
|
|
while (!U.isActive()) {
|
|
|
|
U = U.getBase();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find the active field of the union.
|
2023-05-02 11:21:11 +02:00
|
|
|
const Record *R = U.getRecord();
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
assert(R && R->isUnion() && "Not a union");
|
|
|
|
const FieldDecl *ActiveField = nullptr;
|
|
|
|
for (unsigned I = 0, N = R->getNumFields(); I < N; ++I) {
|
|
|
|
const Pointer &Field = U.atField(R->getField(I)->Offset);
|
|
|
|
if (Field.isActive()) {
|
|
|
|
ActiveField = Field.getField();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const SourceInfo &Loc = S.Current->getSource(OpPC);
|
|
|
|
S.FFDiag(Loc, diag::note_constexpr_access_inactive_union_member)
|
|
|
|
<< AK << InactiveField << !ActiveField << ActiveField;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool CheckTemporary(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
|
|
|
|
AccessKinds AK) {
|
|
|
|
if (auto ID = Ptr.getDeclID()) {
|
|
|
|
if (!Ptr.isStaticTemporary())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (Ptr.getDeclDesc()->getType().isConstQualified())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (S.P.getCurrentDecl() == ID)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
const SourceInfo &E = S.Current->getSource(OpPC);
|
|
|
|
S.FFDiag(E, diag::note_constexpr_access_static_temporary, 1) << AK;
|
|
|
|
S.Note(Ptr.getDeclLoc(), diag::note_constexpr_temporary_here);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool CheckGlobal(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
|
|
|
|
if (auto ID = Ptr.getDeclID()) {
|
|
|
|
if (!Ptr.isStatic())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (S.P.getCurrentDecl() == ID)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_modify_global);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace clang {
|
|
|
|
namespace interp {
|
2023-10-24 12:33:29 +02:00
|
|
|
static void popArg(InterpState &S, const Expr *Arg) {
|
|
|
|
PrimType Ty = S.getContext().classify(Arg->getType()).value_or(PT_Ptr);
|
|
|
|
TYPE_SWITCH(Ty, S.Stk.discard<T>());
|
|
|
|
}
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
|
2023-10-24 12:33:29 +02:00
|
|
|
void cleanupAfterFunctionCall(InterpState &S, CodePtr OpPC) {
|
|
|
|
assert(S.Current);
|
|
|
|
const Function *CurFunc = S.Current->getFunction();
|
|
|
|
assert(CurFunc);
|
|
|
|
|
|
|
|
if (S.Current->Caller && CurFunc->isVariadic()) {
|
|
|
|
// CallExpr we're look for is at the return PC of the current function, i.e.
|
|
|
|
// in the caller.
|
|
|
|
// This code path should be executed very rarely.
|
|
|
|
const auto *CE =
|
|
|
|
cast<CallExpr>(S.Current->Caller->getExpr(S.Current->getRetPC()));
|
|
|
|
unsigned FixedParams = CurFunc->getNumParams();
|
|
|
|
int32_t ArgsToPop = CE->getNumArgs() - FixedParams;
|
|
|
|
assert(ArgsToPop >= 0);
|
|
|
|
for (int32_t I = ArgsToPop - 1; I >= 0; --I) {
|
|
|
|
const Expr *A = CE->getArg(FixedParams + I);
|
|
|
|
popArg(S, A);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// And in any case, remove the fixed parameters (the non-variadic ones)
|
|
|
|
// at the end.
|
|
|
|
S.Current->popArgs();
|
2023-07-28 21:01:05 +02:00
|
|
|
}
|
|
|
|
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
|
|
|
|
if (!Ptr.isExtern())
|
|
|
|
return true;
|
|
|
|
|
2023-10-07 16:00:19 +02:00
|
|
|
if (!S.checkingPotentialConstantExpression() && S.getLangOpts().CPlusPlus) {
|
2023-06-19 08:57:50 +02:00
|
|
|
const auto *VD = Ptr.getDeclDesc()->asValueDecl();
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
const SourceInfo &Loc = S.Current->getSource(OpPC);
|
|
|
|
S.FFDiag(Loc, diag::note_constexpr_ltor_non_constexpr, 1) << VD;
|
|
|
|
S.Note(VD->getLocation(), diag::note_declared_at);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CheckArray(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
|
|
|
|
if (!Ptr.isUnknownSizeArray())
|
|
|
|
return true;
|
|
|
|
const SourceInfo &E = S.Current->getSource(OpPC);
|
|
|
|
S.FFDiag(E, diag::note_constexpr_unsized_array_indexed);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
|
|
|
|
AccessKinds AK) {
|
|
|
|
if (Ptr.isZero()) {
|
2022-10-31 12:58:27 +01:00
|
|
|
const auto &Src = S.Current->getSource(OpPC);
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
|
|
|
|
if (Ptr.isField())
|
|
|
|
S.FFDiag(Src, diag::note_constexpr_null_subobject) << CSK_Field;
|
|
|
|
else
|
|
|
|
S.FFDiag(Src, diag::note_constexpr_access_null) << AK;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!Ptr.isLive()) {
|
2022-10-31 12:58:27 +01:00
|
|
|
const auto &Src = S.Current->getSource(OpPC);
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
bool IsTemp = Ptr.isTemporary();
|
|
|
|
|
|
|
|
S.FFDiag(Src, diag::note_constexpr_lifetime_ended, 1) << AK << !IsTemp;
|
|
|
|
|
|
|
|
if (IsTemp)
|
|
|
|
S.Note(Ptr.getDeclLoc(), diag::note_constexpr_temporary_here);
|
|
|
|
else
|
|
|
|
S.Note(Ptr.getDeclLoc(), diag::note_declared_at);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2023-10-26 15:15:25 +02:00
|
|
|
bool CheckDummy(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
|
2023-10-26 16:15:29 +02:00
|
|
|
return !Ptr.isZero() && !Ptr.isDummy();
|
2023-10-26 15:15:25 +02:00
|
|
|
}
|
|
|
|
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
bool CheckNull(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
|
|
|
|
CheckSubobjectKind CSK) {
|
|
|
|
if (!Ptr.isZero())
|
|
|
|
return true;
|
|
|
|
const SourceInfo &Loc = S.Current->getSource(OpPC);
|
|
|
|
S.FFDiag(Loc, diag::note_constexpr_null_subobject) << CSK;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
|
|
|
|
AccessKinds AK) {
|
|
|
|
if (!Ptr.isOnePastEnd())
|
|
|
|
return true;
|
|
|
|
const SourceInfo &Loc = S.Current->getSource(OpPC);
|
|
|
|
S.FFDiag(Loc, diag::note_constexpr_access_past_end) << AK;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
|
|
|
|
CheckSubobjectKind CSK) {
|
|
|
|
if (!Ptr.isElementPastEnd())
|
|
|
|
return true;
|
|
|
|
const SourceInfo &Loc = S.Current->getSource(OpPC);
|
|
|
|
S.FFDiag(Loc, diag::note_constexpr_past_end_subobject) << CSK;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-04-25 14:30:28 +02:00
|
|
|
bool CheckSubobject(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
|
|
|
|
CheckSubobjectKind CSK) {
|
2023-04-24 16:45:16 +02:00
|
|
|
if (!Ptr.isOnePastEnd())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
const SourceInfo &Loc = S.Current->getSource(OpPC);
|
|
|
|
S.FFDiag(Loc, diag::note_constexpr_past_end_subobject) << CSK;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
|
|
|
|
assert(Ptr.isLive() && "Pointer is not live");
|
2022-10-26 11:20:13 +02:00
|
|
|
if (!Ptr.isConst())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// The This pointer is writable in constructors and destructors,
|
|
|
|
// even if isConst() returns true.
|
|
|
|
if (const Function *Func = S.Current->getFunction();
|
|
|
|
Func && (Func->isConstructor() || Func->isDestructor()) &&
|
|
|
|
Ptr.block() == S.Current->getThis().block()) {
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
const QualType Ty = Ptr.getType();
|
|
|
|
const SourceInfo &Loc = S.Current->getSource(OpPC);
|
|
|
|
S.FFDiag(Loc, diag::note_constexpr_modify_const_type) << Ty;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
|
|
|
|
assert(Ptr.isLive() && "Pointer is not live");
|
|
|
|
if (!Ptr.isMutable()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
const SourceInfo &Loc = S.Current->getSource(OpPC);
|
|
|
|
const FieldDecl *Field = Ptr.getField();
|
2019-09-29 05:08:46 +00:00
|
|
|
S.FFDiag(Loc, diag::note_constexpr_access_mutable, 1) << AK_Read << Field;
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
S.Note(Field->getLocation(), diag::note_declared_at);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-05-04 15:31:24 +02:00
|
|
|
bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
|
|
|
|
AccessKinds AK) {
|
|
|
|
if (Ptr.isInitialized())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (!S.checkingPotentialConstantExpression()) {
|
2023-09-11 07:03:18 +02:00
|
|
|
S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_uninit)
|
|
|
|
<< AK << /*uninitialized=*/true << S.Current->getRange(OpPC);
|
2023-05-04 15:31:24 +02:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
|
2023-10-26 15:15:25 +02:00
|
|
|
if (!CheckDummy(S, OpPC, Ptr))
|
|
|
|
return false;
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
if (!CheckLive(S, OpPC, Ptr, AK_Read))
|
|
|
|
return false;
|
|
|
|
if (!CheckExtern(S, OpPC, Ptr))
|
|
|
|
return false;
|
|
|
|
if (!CheckRange(S, OpPC, Ptr, AK_Read))
|
|
|
|
return false;
|
|
|
|
if (!CheckInitialized(S, OpPC, Ptr, AK_Read))
|
|
|
|
return false;
|
|
|
|
if (!CheckActive(S, OpPC, Ptr, AK_Read))
|
|
|
|
return false;
|
|
|
|
if (!CheckTemporary(S, OpPC, Ptr, AK_Read))
|
|
|
|
return false;
|
|
|
|
if (!CheckMutable(S, OpPC, Ptr))
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
|
|
|
|
if (!CheckLive(S, OpPC, Ptr, AK_Assign))
|
|
|
|
return false;
|
|
|
|
if (!CheckExtern(S, OpPC, Ptr))
|
|
|
|
return false;
|
|
|
|
if (!CheckRange(S, OpPC, Ptr, AK_Assign))
|
|
|
|
return false;
|
|
|
|
if (!CheckGlobal(S, OpPC, Ptr))
|
|
|
|
return false;
|
|
|
|
if (!CheckConst(S, OpPC, Ptr))
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CheckInvoke(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
|
|
|
|
if (!CheckLive(S, OpPC, Ptr, AK_MemberCall))
|
|
|
|
return false;
|
|
|
|
if (!CheckExtern(S, OpPC, Ptr))
|
|
|
|
return false;
|
|
|
|
if (!CheckRange(S, OpPC, Ptr, AK_MemberCall))
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
|
|
|
|
if (!CheckLive(S, OpPC, Ptr, AK_Assign))
|
|
|
|
return false;
|
|
|
|
if (!CheckRange(S, OpPC, Ptr, AK_Assign))
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-10-28 10:31:47 +02:00
|
|
|
bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) {
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
|
2023-06-19 08:45:07 +02:00
|
|
|
if (F->isVirtual() && !S.getLangOpts().CPlusPlus20) {
|
|
|
|
const SourceLocation &Loc = S.Current->getLocation(OpPC);
|
|
|
|
S.CCEDiag(Loc, diag::note_constexpr_virtual_call);
|
|
|
|
return false;
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!F->isConstexpr()) {
|
2022-12-28 09:34:47 +01:00
|
|
|
// Don't emit anything if we're checking for a potential constant
|
|
|
|
// expression. That will happen later when actually executing.
|
|
|
|
if (S.checkingPotentialConstantExpression())
|
|
|
|
return false;
|
|
|
|
|
2022-10-28 10:31:47 +02:00
|
|
|
const SourceLocation &Loc = S.Current->getLocation(OpPC);
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
if (S.getLangOpts().CPlusPlus11) {
|
|
|
|
const FunctionDecl *DiagDecl = F->getDecl();
|
|
|
|
|
|
|
|
// If this function is not constexpr because it is an inherited
|
|
|
|
// non-constexpr constructor, diagnose that directly.
|
2023-06-19 08:57:50 +02:00
|
|
|
const auto *CD = dyn_cast<CXXConstructorDecl>(DiagDecl);
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
if (CD && CD->isInheritingConstructor()) {
|
2023-06-19 08:57:50 +02:00
|
|
|
const auto *Inherited = CD->getInheritedConstructor().getConstructor();
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
if (!Inherited->isConstexpr())
|
|
|
|
DiagDecl = CD = Inherited;
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: If DiagDecl is an implicitly-declared special member function
|
|
|
|
// or an inheriting constructor, we should be much more explicit about why
|
|
|
|
// it's not constexpr.
|
|
|
|
if (CD && CD->isInheritingConstructor())
|
|
|
|
S.FFDiag(Loc, diag::note_constexpr_invalid_inhctor, 1)
|
|
|
|
<< CD->getInheritedConstructor().getConstructor()->getParent();
|
|
|
|
else
|
|
|
|
S.FFDiag(Loc, diag::note_constexpr_invalid_function, 1)
|
|
|
|
<< DiagDecl->isConstexpr() << (bool)CD << DiagDecl;
|
|
|
|
S.Note(DiagDecl->getLocation(), diag::note_declared_at);
|
|
|
|
} else {
|
|
|
|
S.FFDiag(Loc, diag::note_invalid_subexpr_in_const_expr);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2023-04-17 15:23:37 +02:00
|
|
|
bool CheckCallDepth(InterpState &S, CodePtr OpPC) {
|
|
|
|
if ((S.Current->getDepth() + 1) > S.getLangOpts().ConstexprCallDepth) {
|
|
|
|
S.FFDiag(S.Current->getSource(OpPC),
|
|
|
|
diag::note_constexpr_depth_limit_exceeded)
|
|
|
|
<< S.getLangOpts().ConstexprCallDepth;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
bool CheckThis(InterpState &S, CodePtr OpPC, const Pointer &This) {
|
|
|
|
if (!This.isZero())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
const SourceInfo &Loc = S.Current->getSource(OpPC);
|
|
|
|
|
|
|
|
bool IsImplicit = false;
|
2023-06-19 08:57:50 +02:00
|
|
|
if (const auto *E = dyn_cast_if_present<CXXThisExpr>(Loc.asExpr()))
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
IsImplicit = E->isImplicit();
|
|
|
|
|
|
|
|
if (S.getLangOpts().CPlusPlus11)
|
|
|
|
S.FFDiag(Loc, diag::note_constexpr_this) << IsImplicit;
|
|
|
|
else
|
|
|
|
S.FFDiag(Loc);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD) {
|
|
|
|
if (!MD->isPure())
|
|
|
|
return true;
|
|
|
|
const SourceInfo &E = S.Current->getSource(OpPC);
|
|
|
|
S.FFDiag(E, diag::note_constexpr_pure_virtual_call, 1) << MD;
|
|
|
|
S.Note(MD->getLocation(), diag::note_declared_at);
|
|
|
|
return false;
|
|
|
|
}
|
2022-08-19 13:45:11 +02:00
|
|
|
|
2022-10-27 11:37:11 +02:00
|
|
|
static void DiagnoseUninitializedSubobject(InterpState &S, const SourceInfo &SI,
|
2023-05-24 21:21:23 +09:00
|
|
|
const FieldDecl *SubObjDecl) {
|
|
|
|
assert(SubObjDecl && "Subobject declaration does not exist");
|
2023-10-27 14:11:27 +09:00
|
|
|
S.FFDiag(SI, diag::note_constexpr_uninitialized)
|
|
|
|
<< /*(name)*/ 1 << SubObjDecl;
|
2023-05-24 21:21:23 +09:00
|
|
|
S.Note(SubObjDecl->getLocation(),
|
|
|
|
diag::note_constexpr_subobject_declared_here);
|
2022-10-27 11:37:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool CheckFieldsInitialized(InterpState &S, CodePtr OpPC,
|
|
|
|
const Pointer &BasePtr, const Record *R);
|
|
|
|
|
|
|
|
static bool CheckArrayInitialized(InterpState &S, CodePtr OpPC,
|
|
|
|
const Pointer &BasePtr,
|
|
|
|
const ConstantArrayType *CAT) {
|
|
|
|
bool Result = true;
|
|
|
|
size_t NumElems = CAT->getSize().getZExtValue();
|
|
|
|
QualType ElemType = CAT->getElementType();
|
|
|
|
|
2023-02-05 11:03:48 +01:00
|
|
|
if (ElemType->isRecordType()) {
|
2022-10-27 11:37:11 +02:00
|
|
|
const Record *R = BasePtr.getElemRecord();
|
|
|
|
for (size_t I = 0; I != NumElems; ++I) {
|
|
|
|
Pointer ElemPtr = BasePtr.atIndex(I).narrow();
|
|
|
|
Result &= CheckFieldsInitialized(S, OpPC, ElemPtr, R);
|
|
|
|
}
|
2023-06-19 08:57:50 +02:00
|
|
|
} else if (const auto *ElemCAT = dyn_cast<ConstantArrayType>(ElemType)) {
|
2022-10-27 11:37:11 +02:00
|
|
|
for (size_t I = 0; I != NumElems; ++I) {
|
|
|
|
Pointer ElemPtr = BasePtr.atIndex(I).narrow();
|
|
|
|
Result &= CheckArrayInitialized(S, OpPC, ElemPtr, ElemCAT);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (size_t I = 0; I != NumElems; ++I) {
|
|
|
|
if (!BasePtr.atIndex(I).isInitialized()) {
|
2023-05-24 21:21:23 +09:00
|
|
|
DiagnoseUninitializedSubobject(S, S.Current->getSource(OpPC),
|
|
|
|
BasePtr.getField());
|
2022-10-27 11:37:11 +02:00
|
|
|
Result = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2022-10-25 17:34:31 +02:00
|
|
|
static bool CheckFieldsInitialized(InterpState &S, CodePtr OpPC,
|
|
|
|
const Pointer &BasePtr, const Record *R) {
|
|
|
|
assert(R);
|
|
|
|
bool Result = true;
|
|
|
|
// Check all fields of this record are initialized.
|
|
|
|
for (const Record::Field &F : R->fields()) {
|
|
|
|
Pointer FieldPtr = BasePtr.atField(F.Offset);
|
2022-10-27 11:37:11 +02:00
|
|
|
QualType FieldType = F.Decl->getType();
|
2022-10-25 17:34:31 +02:00
|
|
|
|
|
|
|
if (FieldType->isRecordType()) {
|
|
|
|
Result &= CheckFieldsInitialized(S, OpPC, FieldPtr, FieldPtr.getRecord());
|
2023-10-26 13:53:54 +02:00
|
|
|
} else if (FieldType->isIncompleteArrayType()) {
|
|
|
|
// Nothing to do here.
|
2022-10-25 17:34:31 +02:00
|
|
|
} else if (FieldType->isArrayType()) {
|
2022-10-27 11:37:11 +02:00
|
|
|
const auto *CAT =
|
|
|
|
cast<ConstantArrayType>(FieldType->getAsArrayTypeUnsafe());
|
|
|
|
Result &= CheckArrayInitialized(S, OpPC, FieldPtr, CAT);
|
2022-10-25 17:34:31 +02:00
|
|
|
} else if (!FieldPtr.isInitialized()) {
|
2023-05-24 21:21:23 +09:00
|
|
|
DiagnoseUninitializedSubobject(S, S.Current->getSource(OpPC), F.Decl);
|
2022-10-25 17:34:31 +02:00
|
|
|
Result = false;
|
|
|
|
}
|
|
|
|
}
|
2022-12-28 11:43:26 +01:00
|
|
|
|
|
|
|
// Check Fields in all bases
|
|
|
|
for (const Record::Base &B : R->bases()) {
|
2023-02-07 08:20:59 +01:00
|
|
|
Pointer P = BasePtr.atField(B.Offset);
|
2023-10-03 06:46:31 +02:00
|
|
|
if (!P.isInitialized()) {
|
|
|
|
S.FFDiag(BasePtr.getDeclDesc()->asDecl()->getLocation(),
|
|
|
|
diag::note_constexpr_uninitialized_base)
|
|
|
|
<< B.Desc->getType();
|
|
|
|
return false;
|
|
|
|
}
|
2022-12-28 11:43:26 +01:00
|
|
|
Result &= CheckFieldsInitialized(S, OpPC, P, B.R);
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: Virtual bases
|
|
|
|
|
2022-10-25 17:34:31 +02:00
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CheckCtorCall(InterpState &S, CodePtr OpPC, const Pointer &This) {
|
|
|
|
assert(!This.isZero());
|
2023-06-21 19:03:01 +09:00
|
|
|
if (const Record *R = This.getRecord())
|
|
|
|
return CheckFieldsInitialized(S, OpPC, This, R);
|
|
|
|
const auto *CAT =
|
|
|
|
cast<ConstantArrayType>(This.getType()->getAsArrayTypeUnsafe());
|
|
|
|
return CheckArrayInitialized(S, OpPC, This, CAT);
|
2022-10-25 17:34:31 +02:00
|
|
|
}
|
|
|
|
|
2023-05-19 11:12:05 +02:00
|
|
|
bool CheckPotentialReinterpretCast(InterpState &S, CodePtr OpPC,
|
|
|
|
const Pointer &Ptr) {
|
|
|
|
if (!S.inConstantContext())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
const SourceInfo &E = S.Current->getSource(OpPC);
|
|
|
|
S.CCEDiag(E, diag::note_constexpr_invalid_cast)
|
2023-06-19 07:56:52 +02:00
|
|
|
<< 2 << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC);
|
2023-05-19 11:12:05 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-07-28 08:07:51 +02:00
|
|
|
bool CheckFloatResult(InterpState &S, CodePtr OpPC, const Floating &Result,
|
|
|
|
APFloat::opStatus Status) {
|
|
|
|
const SourceInfo &E = S.Current->getSource(OpPC);
|
|
|
|
|
|
|
|
// [expr.pre]p4:
|
|
|
|
// If during the evaluation of an expression, the result is not
|
|
|
|
// mathematically defined [...], the behavior is undefined.
|
|
|
|
// FIXME: C++ rules require us to not conform to IEEE 754 here.
|
|
|
|
if (Result.isNan()) {
|
|
|
|
S.CCEDiag(E, diag::note_constexpr_float_arithmetic)
|
|
|
|
<< /*NaN=*/true << S.Current->getRange(OpPC);
|
|
|
|
return S.noteUndefinedBehavior();
|
|
|
|
}
|
|
|
|
|
2023-01-25 14:51:16 +01:00
|
|
|
// In a constant context, assume that any dynamic rounding mode or FP
|
|
|
|
// exception state matches the default floating-point environment.
|
|
|
|
if (S.inConstantContext())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
FPOptions FPO = E.asExpr()->getFPFeaturesInEffect(S.Ctx.getLangOpts());
|
|
|
|
|
|
|
|
if ((Status & APFloat::opInexact) &&
|
|
|
|
FPO.getRoundingMode() == llvm::RoundingMode::Dynamic) {
|
|
|
|
// Inexact result means that it depends on rounding mode. If the requested
|
|
|
|
// mode is dynamic, the evaluation cannot be made in compile time.
|
|
|
|
S.FFDiag(E, diag::note_constexpr_dynamic_rounding);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((Status != APFloat::opOK) &&
|
|
|
|
(FPO.getRoundingMode() == llvm::RoundingMode::Dynamic ||
|
|
|
|
FPO.getExceptionMode() != LangOptions::FPE_Ignore ||
|
|
|
|
FPO.getAllowFEnvAccess())) {
|
|
|
|
S.FFDiag(E, diag::note_constexpr_float_arithmetic_strict);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((Status & APFloat::opStatus::opInvalidOp) &&
|
|
|
|
FPO.getExceptionMode() != LangOptions::FPE_Ignore) {
|
|
|
|
// There is no usefully definable result.
|
|
|
|
S.FFDiag(E);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2023-07-28 08:37:41 +02:00
|
|
|
/// We aleady know the given DeclRefExpr is invalid for some reason,
|
|
|
|
/// now figure out why and print appropriate diagnostics.
|
|
|
|
bool CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR) {
|
|
|
|
const ValueDecl *D = DR->getDecl();
|
|
|
|
const SourceInfo &E = S.Current->getSource(OpPC);
|
|
|
|
|
|
|
|
if (isa<ParmVarDecl>(D)) {
|
2023-10-24 09:28:30 +02:00
|
|
|
if (S.getLangOpts().CPlusPlus11) {
|
|
|
|
S.FFDiag(E, diag::note_constexpr_function_param_value_unknown) << D;
|
|
|
|
S.Note(D->getLocation(), diag::note_declared_at) << D->getSourceRange();
|
|
|
|
} else {
|
|
|
|
S.FFDiag(E);
|
|
|
|
}
|
2023-07-28 08:37:41 +02:00
|
|
|
} else if (const auto *VD = dyn_cast<VarDecl>(D)) {
|
|
|
|
if (!VD->getType().isConstQualified()) {
|
|
|
|
S.FFDiag(E,
|
|
|
|
VD->getType()->isIntegralOrEnumerationType()
|
|
|
|
? diag::note_constexpr_ltor_non_const_int
|
|
|
|
: diag::note_constexpr_ltor_non_constexpr,
|
|
|
|
1)
|
|
|
|
<< VD;
|
|
|
|
S.Note(VD->getLocation(), diag::note_declared_at) << VD->getSourceRange();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// const, but no initializer.
|
|
|
|
if (!VD->getAnyInitializer()) {
|
|
|
|
S.FFDiag(E, diag::note_constexpr_var_init_unknown, 1) << VD;
|
|
|
|
S.Note(VD->getLocation(), diag::note_declared_at) << VD->getSourceRange();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
bool Interpret(InterpState &S, APValue &Result) {
|
2022-08-19 13:45:11 +02:00
|
|
|
// The current stack frame when we started Interpret().
|
|
|
|
// This is being used by the ops to determine wheter
|
|
|
|
// to return from this function and thus terminate
|
|
|
|
// interpretation.
|
|
|
|
const InterpFrame *StartFrame = S.Current;
|
2022-08-05 13:57:39 +02:00
|
|
|
assert(!S.Current->isRoot());
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
CodePtr PC = S.Current->getPC();
|
|
|
|
|
2022-08-05 13:57:39 +02:00
|
|
|
// Empty program.
|
|
|
|
if (!PC)
|
|
|
|
return true;
|
|
|
|
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
for (;;) {
|
|
|
|
auto Op = PC.read<Opcode>();
|
|
|
|
CodePtr OpPC = PC;
|
|
|
|
|
|
|
|
switch (Op) {
|
|
|
|
#define GET_INTERP
|
|
|
|
#include "Opcodes.inc"
|
|
|
|
#undef GET_INTERP
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace interp
|
|
|
|
} // namespace clang
|