[clang] 25d6123 - [clang][Interp] Make sure we have a variable scope for initializers
Timm Bäder via cfe-commits
cfe-commits at lists.llvm.org
Thu Apr 13 06:35:46 PDT 2023
Author: Timm Bäder
Date: 2023-04-13T15:35:30+02:00
New Revision: 25d6123854d16370463ba884e750f303d09e9001
URL: https://github.com/llvm/llvm-project/commit/25d6123854d16370463ba884e750f303d09e9001
DIFF: https://github.com/llvm/llvm-project/commit/25d6123854d16370463ba884e750f303d09e9001.diff
LOG: [clang][Interp] Make sure we have a variable scope for initializers
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
Added:
Modified:
clang/lib/AST/Interp/ByteCodeStmtGen.cpp
clang/test/AST/Interp/records.cpp
Removed:
################################################################################
diff --git a/clang/lib/AST/Interp/ByteCodeStmtGen.cpp b/clang/lib/AST/Interp/ByteCodeStmtGen.cpp
index 2c53900111d9b..e20b714120e8d 100644
--- a/clang/lib/AST/Interp/ByteCodeStmtGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeStmtGen.cpp
@@ -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);
diff --git a/clang/test/AST/Interp/records.cpp b/clang/test/AST/Interp/records.cpp
index 39eb65c13342f..745a30bec33bd 100644
--- a/clang/test/AST/Interp/records.cpp
+++ b/clang/test/AST/Interp/records.cpp
@@ -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;};
More information about the cfe-commits
mailing list