Skip to content

Commit

Permalink
[clang][Interp] Make sure we have a variable scope for initializers
Browse files Browse the repository at this point in the history
Otherwise, we run into an assertion when trying to use the current
variable scope while creating temporaries for constructor initializers.

Differential Revision: https://reviews.llvm.org/D147534
  • Loading branch information
tbaederr committed Apr 13, 2023
1 parent e07a421 commit 25d6123
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 0 deletions.
3 changes: 3 additions & 0 deletions clang/lib/AST/Interp/ByteCodeStmtGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ bool ByteCodeStmtGen<Emitter>::visitFunc(const FunctionDecl *F) {
return false;

for (const auto *Init : Ctor->inits()) {
// Scope needed for the initializers.
BlockScope<Emitter> Scope(this);

const Expr *InitExpr = Init->getInit();
if (const FieldDecl *Member = Init->getMember()) {
const Record::Field *F = R->getField(Member);
Expand Down
72 changes: 72 additions & 0 deletions clang/test/AST/Interp/records.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,78 @@ struct S {
constexpr S s;
static_assert(s.m() == 1, "");

namespace InitializerTemporaries {
class Bar {
private:
int a;

public:
constexpr Bar() : a(10) {}
constexpr int getA() const { return a; }
};

class Foo {
public:
int a;

constexpr Foo() : a(Bar().getA()) {}
};
constexpr Foo F;
static_assert(F.a == 10, "");


/// Needs constexpr destructors.
#if __cplusplus >= 202002L
/// Does
/// Arr[Pos] = Value;
/// ++Pos;
/// in its destructor.
class BitSetter {
private:
int *Arr;
int &Pos;
int Value;

public:
constexpr BitSetter(int *Arr, int &Pos, int Value) :
Arr(Arr), Pos(Pos), Value(Value) {}

constexpr int getValue() const { return 0; }
constexpr ~BitSetter() {
Arr[Pos] = Value;
++Pos;
}
};

class Test {
int a, b, c;
public:
constexpr Test(int *Arr, int &Pos) :
a(BitSetter(Arr, Pos, 1).getValue()),
b(BitSetter(Arr, Pos, 2).getValue()),
c(BitSetter(Arr, Pos, 3).getValue())
{}
};


constexpr int T(int Index) {
int Arr[] = {0, 0, 0};
int Pos = 0;

{
auto T = Test(Arr, Pos);
// End of scope, should destroy Test.
}

return Arr[Index];
}

static_assert(T(0) == 1);
static_assert(T(1) == 2);
static_assert(T(2) == 3);
#endif
}

#if __cplusplus >= 201703L
namespace BaseInit {
class _A {public: int a;};
Expand Down

0 comments on commit 25d6123

Please sign in to comment.