Skip to content

Commit a4b39f6

Browse files
committed
[clang][Interp] Lazily visit const-qualified static data members in C++
1 parent 192be3c commit a4b39f6

File tree

2 files changed

+22
-1
lines changed

2 files changed

+22
-1
lines changed

clang/lib/AST/Interp/ByteCodeExprGen.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3306,7 +3306,8 @@ bool ByteCodeExprGen<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) {
33063306
if (Ctx.getLangOpts().CPlusPlus) {
33073307
if (const auto *VD = dyn_cast<VarDecl>(D)) {
33083308
// Visit local const variables like normal.
3309-
if (VD->isLocalVarDecl() && VD->getType().isConstQualified()) {
3309+
if ((VD->isLocalVarDecl() || VD->isStaticDataMember()) &&
3310+
VD->getType().isConstQualified()) {
33103311
if (!this->visitVarDecl(VD))
33113312
return false;
33123313
// Retry.

clang/test/AST/Interp/records.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1244,3 +1244,23 @@ struct HasNonConstExprMemInit {
12441244
int x = f(); // both-note {{non-constexpr function}}
12451245
constexpr HasNonConstExprMemInit() {} // both-error {{never produces a constant expression}}
12461246
};
1247+
1248+
namespace {
1249+
template <class Tp, Tp v>
1250+
struct integral_constant {
1251+
static const Tp value = v;
1252+
};
1253+
1254+
template <class Tp, Tp v>
1255+
const Tp integral_constant<Tp, v>::value;
1256+
1257+
typedef integral_constant<bool, true> true_type;
1258+
typedef integral_constant<bool, false> false_type;
1259+
1260+
/// This might look innocent, but we get an evaluateAsInitializer call for the
1261+
/// static bool member before evaluating the first static_assert, but we do NOT
1262+
/// get such a call for the second one. So the second one needs to lazily visit
1263+
/// the data member itself.
1264+
static_assert(true_type::value, "");
1265+
static_assert(true_type::value, "");
1266+
}

0 commit comments

Comments
 (0)