diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h --- a/clang/lib/AST/Interp/ByteCodeExprGen.h +++ b/clang/lib/AST/Interp/ByteCodeExprGen.h @@ -304,6 +304,9 @@ /// Flag inidicating if we're initializing an already created /// variable. This is set in visitInitializer(). bool Initializing = false; + + /// Flag indicating if we're initializing a global variable. + bool GlobalDecl = false; }; extern template class ByteCodeExprGen; diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -29,14 +29,20 @@ template class DeclScope final : public VariableScope { public: DeclScope(ByteCodeExprGen *Ctx, const ValueDecl *VD) - : VariableScope(Ctx), Scope(Ctx->P, VD) {} + : VariableScope(Ctx), Scope(Ctx->P, VD), + OldGlobalDecl(Ctx->GlobalDecl) { + Ctx->GlobalDecl = Context::shouldBeGloballyIndexed(VD); + } void addExtended(const Scope::Local &Local) override { return this->addLocal(Local); } + ~DeclScope() { this->Ctx->GlobalDecl = OldGlobalDecl; } + private: Program::DeclScope Scope; + bool OldGlobalDecl; }; /// Scope used to handle initialization methods. @@ -1198,21 +1204,30 @@ if (DiscardResult) return this->discard(SubExpr); + // When we're initializing a global variable *or* the storage duration of + // the temporary is explicitly static, create a global variable. std::optional SubExprT = classify(SubExpr); - if (E->getStorageDuration() == SD_Static) { + bool IsStatic = E->getStorageDuration() == SD_Static; + if (GlobalDecl || IsStatic) { std::optional GlobalIndex = P.createGlobal(E); if (!GlobalIndex) return false; const LifetimeExtendedTemporaryDecl *TempDecl = E->getLifetimeExtendedTemporaryDecl(); - assert(TempDecl); + if (IsStatic) + assert(TempDecl); if (SubExprT) { if (!this->visit(SubExpr)) return false; - if (!this->emitInitGlobalTemp(*SubExprT, *GlobalIndex, TempDecl, E)) - return false; + if (IsStatic) { + if (!this->emitInitGlobalTemp(*SubExprT, *GlobalIndex, TempDecl, E)) + return false; + } else { + if (!this->emitInitGlobal(*SubExprT, *GlobalIndex, E)) + return false; + } return this->emitGetPtrGlobal(*GlobalIndex, E); } @@ -1221,7 +1236,9 @@ return false; if (!this->visitInitializer(SubExpr)) return false; - return this->emitInitGlobalTempComp(TempDecl, E); + if (IsStatic) + return this->emitInitGlobalTempComp(TempDecl, E); + return true; } // For everyhing else, use local variables. diff --git a/clang/test/AST/Interp/records.cpp b/clang/test/AST/Interp/records.cpp --- a/clang/test/AST/Interp/records.cpp +++ b/clang/test/AST/Interp/records.cpp @@ -1064,6 +1064,22 @@ }; constexpr B b(A(1),2); + + + struct O { + int &&j; + }; + + /// Not constexpr! + O o1(0); + constinit O o2(0); // ref-error {{variable does not have a constant initializer}} \ + // ref-note {{required by 'constinit' specifier}} \ + // ref-note {{reference to temporary is not a constant expression}} \ + // ref-note {{temporary created here}} \ + // expected-error {{variable does not have a constant initializer}} \ + // expected-note {{required by 'constinit' specifier}} \ + // expected-note {{reference to temporary is not a constant expression}} \ + // expected-note {{temporary created here}} } #endif diff --git a/clang/test/SemaCXX/paren-list-agg-init.cpp b/clang/test/SemaCXX/paren-list-agg-init.cpp --- a/clang/test/SemaCXX/paren-list-agg-init.cpp +++ b/clang/test/SemaCXX/paren-list-agg-init.cpp @@ -1,4 +1,6 @@ // RUN: %clang_cc1 -verify -std=c++20 %s -fsyntax-only +// RUN: %clang_cc1 -verify -std=c++20 %s -fsyntax-only -fexperimental-new-constant-interpreter +// RUN: %clang_cc1 -verify=expected,beforecxx20 -Wc++20-extensions -std=c++20 %s -fsyntax-only -fexperimental-new-constant-interpreter // RUN: %clang_cc1 -verify=expected,beforecxx20 -Wc++20-extensions -std=c++20 %s -fsyntax-only struct A { // expected-note 4{{candidate constructor}}