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 "Function.h"
|
|
|
|
#include "InterpFrame.h"
|
2024-02-25 14:03:47 +01:00
|
|
|
#include "InterpShared.h"
|
[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
|
|
|
#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"
|
2024-05-23 13:10:13 +02:00
|
|
|
#include "clang/AST/DeclObjC.h"
|
[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
|
|
|
#include "clang/AST/Expr.h"
|
|
|
|
#include "clang/AST/ExprCXX.h"
|
|
|
|
#include "llvm/ADT/APSInt.h"
|
2024-02-25 14:03:47 +01:00
|
|
|
#include <limits>
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
using namespace clang;
|
[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
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2024-04-11 17:53:57 +02:00
|
|
|
static void diagnoseMissingInitializer(InterpState &S, CodePtr OpPC,
|
|
|
|
const ValueDecl *VD) {
|
|
|
|
const SourceInfo &E = S.Current->getSource(OpPC);
|
|
|
|
S.FFDiag(E, diag::note_constexpr_var_init_unknown, 1) << VD;
|
|
|
|
S.Note(VD->getLocation(), diag::note_declared_at) << VD->getSourceRange();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void diagnoseNonConstVariable(InterpState &S, CodePtr OpPC,
|
|
|
|
const ValueDecl *VD);
|
|
|
|
static bool diagnoseUnknownDecl(InterpState &S, CodePtr OpPC,
|
|
|
|
const ValueDecl *D) {
|
|
|
|
const SourceInfo &E = S.Current->getSource(OpPC);
|
|
|
|
|
|
|
|
if (isa<ParmVarDecl>(D)) {
|
|
|
|
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);
|
|
|
|
}
|
2024-05-21 12:55:02 +02:00
|
|
|
return false;
|
2024-04-11 17:53:57 +02:00
|
|
|
}
|
2024-05-21 12:55:02 +02:00
|
|
|
|
|
|
|
if (!D->getType().isConstQualified())
|
|
|
|
diagnoseNonConstVariable(S, OpPC, D);
|
|
|
|
else if (const auto *VD = dyn_cast<VarDecl>(D);
|
|
|
|
VD && !VD->getAnyInitializer())
|
|
|
|
diagnoseMissingInitializer(S, OpPC, VD);
|
|
|
|
|
2024-04-11 17:53:57 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-01-13 05:51:03 +01:00
|
|
|
static void diagnoseNonConstVariable(InterpState &S, CodePtr OpPC,
|
|
|
|
const ValueDecl *VD) {
|
|
|
|
if (!S.getLangOpts().CPlusPlus)
|
|
|
|
return;
|
|
|
|
|
|
|
|
const SourceInfo &Loc = S.Current->getSource(OpPC);
|
2024-04-11 17:53:57 +02:00
|
|
|
if (const auto *VarD = dyn_cast<VarDecl>(VD);
|
|
|
|
VarD && VarD->getType().isConstQualified() &&
|
|
|
|
!VarD->getAnyInitializer()) {
|
|
|
|
diagnoseMissingInitializer(S, OpPC, VD);
|
|
|
|
return;
|
|
|
|
}
|
2024-01-18 15:15:05 +01:00
|
|
|
|
2024-05-23 13:10:13 +02:00
|
|
|
// Rather random, but this is to match the diagnostic output of the current
|
|
|
|
// interpreter.
|
|
|
|
if (isa<ObjCIvarDecl>(VD))
|
|
|
|
return;
|
|
|
|
|
2024-04-11 17:53:57 +02:00
|
|
|
if (VD->getType()->isIntegralOrEnumerationType()) {
|
2024-01-18 15:15:05 +01:00
|
|
|
S.FFDiag(Loc, diag::note_constexpr_ltor_non_const_int, 1) << VD;
|
2024-04-11 17:53:57 +02:00
|
|
|
S.Note(VD->getLocation(), diag::note_declared_at);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
S.FFDiag(Loc,
|
|
|
|
S.getLangOpts().CPlusPlus11 ? diag::note_constexpr_ltor_non_constexpr
|
|
|
|
: diag::note_constexpr_ltor_non_integral,
|
|
|
|
1)
|
|
|
|
<< VD << VD->getType();
|
2024-01-13 05:51:03 +01:00
|
|
|
S.Note(VD->getLocation(), diag::note_declared_at);
|
|
|
|
}
|
|
|
|
|
[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
|
|
|
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) {
|
2024-01-31 15:57:23 +01:00
|
|
|
PrimType Ty = S.getContext().classify(Arg).value_or(PT_Ptr);
|
2023-10-24 12:33:29 +02:00
|
|
|
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);
|
|
|
|
|
2023-11-17 16:13:23 +01:00
|
|
|
if (CurFunc->isUnevaluatedBuiltin())
|
|
|
|
return;
|
|
|
|
|
2024-01-11 09:02:24 +01:00
|
|
|
// Some builtin functions require us to only look at the call site, since
|
|
|
|
// the classified parameter types do not match.
|
|
|
|
if (CurFunc->isBuiltin()) {
|
|
|
|
const auto *CE =
|
|
|
|
cast<CallExpr>(S.Current->Caller->getExpr(S.Current->getRetPC()));
|
|
|
|
for (int32_t I = CE->getNumArgs() - 1; I >= 0; --I) {
|
|
|
|
const Expr *A = CE->getArg(I);
|
|
|
|
popArg(S, A);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-10-24 12:33:29 +02:00
|
|
|
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.
|
2024-02-14 15:29:47 +01:00
|
|
|
unsigned NumVarArgs;
|
|
|
|
const Expr *const *Args = nullptr;
|
|
|
|
unsigned NumArgs = 0;
|
|
|
|
const Expr *CallSite = S.Current->Caller->getExpr(S.Current->getRetPC());
|
|
|
|
if (const auto *CE = dyn_cast<CallExpr>(CallSite)) {
|
|
|
|
Args = CE->getArgs();
|
|
|
|
NumArgs = CE->getNumArgs();
|
|
|
|
} else if (const auto *CE = dyn_cast<CXXConstructExpr>(CallSite)) {
|
|
|
|
Args = CE->getArgs();
|
|
|
|
NumArgs = CE->getNumArgs();
|
|
|
|
} else
|
|
|
|
assert(false && "Can't get arguments from that expression type");
|
|
|
|
|
|
|
|
assert(NumArgs >= CurFunc->getNumWrittenParams());
|
|
|
|
NumVarArgs = NumArgs - CurFunc->getNumWrittenParams();
|
|
|
|
for (unsigned I = 0; I != NumVarArgs; ++I) {
|
|
|
|
const Expr *A = Args[NumArgs - 1 - I];
|
2023-10-24 12:33:29 +02:00
|
|
|
popArg(S, A);
|
|
|
|
}
|
|
|
|
}
|
2024-02-14 15:29:47 +01:00
|
|
|
|
2023-10-24 12:33:29 +02:00
|
|
|
// 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;
|
|
|
|
|
2024-04-11 17:53:57 +02:00
|
|
|
if (Ptr.isInitialized())
|
|
|
|
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();
|
2024-01-13 05:51:03 +01:00
|
|
|
diagnoseNonConstVariable(S, OpPC, VD);
|
[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 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;
|
|
|
|
}
|
|
|
|
|
2024-01-13 05:51:03 +01:00
|
|
|
bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc) {
|
|
|
|
assert(Desc);
|
2024-01-18 15:15:05 +01:00
|
|
|
|
|
|
|
auto IsConstType = [&S](const VarDecl *VD) -> bool {
|
|
|
|
if (VD->isConstexpr())
|
|
|
|
return true;
|
|
|
|
|
2024-03-15 15:50:42 +01:00
|
|
|
QualType T = VD->getType();
|
2024-01-18 15:15:05 +01:00
|
|
|
if (S.getLangOpts().CPlusPlus && !S.getLangOpts().CPlusPlus11)
|
2024-05-14 16:41:28 +02:00
|
|
|
return (T->isSignedIntegerOrEnumerationType() ||
|
|
|
|
T->isUnsignedIntegerOrEnumerationType()) &&
|
|
|
|
T.isConstQualified();
|
2024-01-18 15:15:05 +01:00
|
|
|
|
|
|
|
if (T.isConstQualified())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (const auto *RT = T->getAs<ReferenceType>())
|
|
|
|
return RT->getPointeeType().isConstQualified();
|
|
|
|
|
|
|
|
if (const auto *PT = T->getAs<PointerType>())
|
|
|
|
return PT->getPointeeType().isConstQualified();
|
|
|
|
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
2024-05-14 16:41:28 +02:00
|
|
|
if (const auto *D = Desc->asVarDecl();
|
|
|
|
D && D->hasGlobalStorage() && !IsConstType(D)) {
|
|
|
|
diagnoseNonConstVariable(S, OpPC, D);
|
|
|
|
return S.inConstantContext();
|
2024-01-13 05:51:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool CheckConstant(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
|
2024-04-10 12:53:54 +02:00
|
|
|
if (Ptr.isIntegralPointer())
|
|
|
|
return true;
|
2024-01-13 05:51:03 +01:00
|
|
|
return CheckConstant(S, OpPC, Ptr.getDeclDesc());
|
|
|
|
}
|
|
|
|
|
[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;
|
|
|
|
}
|
|
|
|
|
2024-06-06 11:17:48 +02:00
|
|
|
bool CheckDowncast(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
|
|
|
|
uint32_t Offset) {
|
|
|
|
uint32_t MinOffset = Ptr.getDeclDesc()->getMetadataSize();
|
|
|
|
uint32_t PtrOffset = Ptr.getByteOffset();
|
|
|
|
|
|
|
|
// We subtract Offset from PtrOffset. The result must be at least
|
|
|
|
// MinOffset.
|
|
|
|
if (Offset < PtrOffset && (PtrOffset - Offset) >= MinOffset)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
const auto *E = cast<CastExpr>(S.Current->getExpr(OpPC));
|
|
|
|
QualType TargetQT = E->getType()->getPointeeType();
|
|
|
|
QualType MostDerivedQT = Ptr.getDeclPtr().getType();
|
|
|
|
|
|
|
|
S.CCEDiag(E, diag::note_constexpr_invalid_downcast)
|
|
|
|
<< MostDerivedQT << TargetQT;
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2024-04-10 12:53:54 +02:00
|
|
|
if (!Ptr.isBlockPointer())
|
|
|
|
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
|
|
|
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) {
|
2024-02-20 13:56:57 +01:00
|
|
|
assert(Ptr.isLive());
|
|
|
|
|
2023-05-04 15:31:24 +02:00
|
|
|
if (Ptr.isInitialized())
|
|
|
|
return true;
|
|
|
|
|
2024-02-21 08:12:31 +01:00
|
|
|
if (const auto *VD = Ptr.getDeclDesc()->asVarDecl();
|
|
|
|
VD && VD->hasGlobalStorage()) {
|
|
|
|
const SourceInfo &Loc = S.Current->getSource(OpPC);
|
2024-04-11 17:53:57 +02:00
|
|
|
if (VD->getAnyInitializer()) {
|
|
|
|
S.FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
|
|
|
|
S.Note(VD->getLocation(), diag::note_declared_at);
|
|
|
|
} else {
|
|
|
|
diagnoseMissingInitializer(S, OpPC, VD);
|
|
|
|
}
|
|
|
|
return false;
|
2024-02-21 08:12:31 +01:00
|
|
|
}
|
2024-04-11 17:53:57 +02:00
|
|
|
|
2023-05-04 15:31:24 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2024-01-31 08:03:37 +01:00
|
|
|
bool CheckGlobalInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
|
|
|
|
if (Ptr.isInitialized())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
assert(S.getLangOpts().CPlusPlus);
|
|
|
|
const auto *VD = cast<VarDecl>(Ptr.getDeclDesc()->asValueDecl());
|
|
|
|
if ((!VD->hasConstantInitialization() &&
|
|
|
|
VD->mightBeUsableInConstantExpressions(S.getCtx())) ||
|
|
|
|
(S.getLangOpts().OpenCL && !S.getLangOpts().CPlusPlus11 &&
|
|
|
|
!VD->hasICEInitializer(S.getCtx()))) {
|
|
|
|
const SourceInfo &Loc = S.Current->getSource(OpPC);
|
|
|
|
S.FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
|
|
|
|
S.Note(VD->getLocation(), diag::note_declared_at);
|
|
|
|
}
|
|
|
|
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) {
|
|
|
|
if (!CheckLive(S, OpPC, Ptr, AK_Read))
|
|
|
|
return false;
|
2024-01-13 05:51:03 +01:00
|
|
|
if (!CheckConstant(S, OpPC, Ptr))
|
|
|
|
return false;
|
|
|
|
|
2024-05-24 16:23:56 +02:00
|
|
|
if (!CheckDummy(S, OpPC, Ptr, AK_Read))
|
2024-01-08 08:33:15 +01: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
|
|
|
if (!CheckExtern(S, OpPC, Ptr))
|
|
|
|
return false;
|
|
|
|
if (!CheckRange(S, OpPC, Ptr, AK_Read))
|
|
|
|
return false;
|
|
|
|
if (!CheckActive(S, OpPC, Ptr, AK_Read))
|
|
|
|
return false;
|
2024-05-22 14:35:43 +02:00
|
|
|
if (!CheckInitialized(S, OpPC, Ptr, AK_Read))
|
|
|
|
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 (!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;
|
2024-05-24 16:23:56 +02:00
|
|
|
if (!CheckDummy(S, OpPC, Ptr, AK_Assign))
|
2024-02-01 12:51:43 +01: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
|
|
|
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;
|
2024-06-06 11:17:48 +02:00
|
|
|
if (!Ptr.isDummy()) {
|
|
|
|
if (!CheckExtern(S, OpPC, Ptr))
|
|
|
|
return false;
|
|
|
|
if (!CheckRange(S, OpPC, Ptr, AK_MemberCall))
|
|
|
|
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
|
|
|
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
|
|
|
}
|
|
|
|
|
2024-06-06 19:40:43 +02:00
|
|
|
if (!F->isConstexpr() || !F->hasBody()) {
|
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();
|
|
|
|
|
2024-02-23 10:52:28 +01:00
|
|
|
// Invalid decls have been diagnosed before.
|
|
|
|
if (DiagDecl->isInvalidDecl())
|
|
|
|
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 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.
|
2023-12-13 12:14:53 +01:00
|
|
|
if (CD && CD->isInheritingConstructor()) {
|
[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.FFDiag(Loc, diag::note_constexpr_invalid_inhctor, 1)
|
|
|
|
<< CD->getInheritedConstructor().getConstructor()->getParent();
|
2023-12-13 12:14:53 +01:00
|
|
|
S.Note(DiagDecl->getLocation(), diag::note_declared_at);
|
|
|
|
} else {
|
|
|
|
// Don't emit anything if the function isn't defined and we're checking
|
|
|
|
// for a constant expression. It might be defined at the point we're
|
|
|
|
// actually calling it.
|
2024-03-15 16:22:38 +01:00
|
|
|
bool IsExtern = DiagDecl->getStorageClass() == SC_Extern;
|
|
|
|
if (!DiagDecl->isDefined() && !IsExtern &&
|
|
|
|
S.checkingPotentialConstantExpression())
|
2023-12-13 12:14:53 +01:00
|
|
|
return false;
|
|
|
|
|
2024-06-06 19:40:43 +02:00
|
|
|
// If the declaration is defined, declared 'constexpr' _and_ has a body,
|
|
|
|
// the below diagnostic doesn't add anything useful.
|
|
|
|
if (DiagDecl->isDefined() && DiagDecl->isConstexpr() &&
|
|
|
|
DiagDecl->hasBody())
|
2024-02-15 20:03:10 +01: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
|
|
|
S.FFDiag(Loc, diag::note_constexpr_invalid_function, 1)
|
|
|
|
<< DiagDecl->isConstexpr() << (bool)CD << DiagDecl;
|
2023-12-13 12:14:53 +01:00
|
|
|
S.Note(DiagDecl->getLocation(), diag::note_declared_at);
|
|
|
|
}
|
[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
|
|
|
} 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) {
|
2024-01-18 15:30:58 +01:00
|
|
|
if (!MD->isPureVirtual())
|
[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 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
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2024-02-28 18:09:39 +01: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();
|
|
|
|
return diagnoseUnknownDecl(S, OpPC, D);
|
|
|
|
}
|
|
|
|
|
2024-05-24 16:23:56 +02:00
|
|
|
bool CheckDummy(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
|
|
|
|
AccessKinds AK) {
|
2024-02-28 18:09:39 +01:00
|
|
|
if (!Ptr.isDummy())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
const Descriptor *Desc = Ptr.getDeclDesc();
|
|
|
|
const ValueDecl *D = Desc->asValueDecl();
|
|
|
|
if (!D)
|
|
|
|
return false;
|
|
|
|
|
2024-05-24 16:23:56 +02:00
|
|
|
if (AK == AK_Read || AK == AK_Increment || AK == AK_Decrement)
|
|
|
|
return diagnoseUnknownDecl(S, OpPC, D);
|
|
|
|
|
|
|
|
assert(AK == AK_Assign);
|
|
|
|
if (S.getLangOpts().CPlusPlus11) {
|
|
|
|
const SourceInfo &E = S.Current->getSource(OpPC);
|
|
|
|
S.FFDiag(E, diag::note_constexpr_modify_global);
|
|
|
|
}
|
|
|
|
return false;
|
2024-02-28 18:09:39 +01:00
|
|
|
}
|
|
|
|
|
2024-02-25 14:03:47 +01:00
|
|
|
bool CheckNonNullArgs(InterpState &S, CodePtr OpPC, const Function *F,
|
|
|
|
const CallExpr *CE, unsigned ArgSize) {
|
|
|
|
auto Args = llvm::ArrayRef(CE->getArgs(), CE->getNumArgs());
|
|
|
|
auto NonNullArgs = collectNonNullArgs(F->getDecl(), Args);
|
|
|
|
unsigned Offset = 0;
|
|
|
|
unsigned Index = 0;
|
|
|
|
for (const Expr *Arg : Args) {
|
|
|
|
if (NonNullArgs[Index] && Arg->getType()->isPointerType()) {
|
|
|
|
const Pointer &ArgPtr = S.Stk.peek<Pointer>(ArgSize - Offset);
|
|
|
|
if (ArgPtr.isZero()) {
|
|
|
|
const SourceLocation &Loc = S.Current->getLocation(OpPC);
|
|
|
|
S.CCEDiag(Loc, diag::note_non_null_attribute_failed);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Offset += align(primSize(S.Ctx.classify(Arg).value_or(PT_Ptr)));
|
|
|
|
++Index;
|
|
|
|
}
|
|
|
|
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 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
|