diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index f68422c6eb01d..1243380ca8a6b 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -5432,8 +5432,7 @@ bool Compiler::VisitCXXThisExpr(const CXXThisExpr *E) { unsigned EndIndex = 0; // Find the init list. for (StartIndex = InitStack.size() - 1; StartIndex > 0; --StartIndex) { - if (InitStack[StartIndex].Kind == InitLink::K_InitList || - InitStack[StartIndex].Kind == InitLink::K_This) { + if (InitStack[StartIndex].Kind == InitLink::K_DIE) { EndIndex = StartIndex; --StartIndex; break; @@ -5446,7 +5445,8 @@ bool Compiler::VisitCXXThisExpr(const CXXThisExpr *E) { continue; if (InitStack[StartIndex].Kind != InitLink::K_Field && - InitStack[StartIndex].Kind != InitLink::K_Elem) + InitStack[StartIndex].Kind != InitLink::K_Elem && + InitStack[StartIndex].Kind != InitLink::K_DIE) break; } @@ -5457,7 +5457,8 @@ bool Compiler::VisitCXXThisExpr(const CXXThisExpr *E) { // Emit the instructions. for (unsigned I = StartIndex; I != (EndIndex + 1); ++I) { - if (InitStack[I].Kind == InitLink::K_InitList) + if (InitStack[I].Kind == InitLink::K_InitList || + InitStack[I].Kind == InitLink::K_DIE) continue; if (!InitStack[I].template emit(this, E)) return false; @@ -6328,8 +6329,8 @@ bool Compiler::compileConstructor(const CXXConstructorDecl *Ctor) { unsigned FirstLinkOffset = R->getField(cast(IFD->chain()[0]))->Offset; - InitStackScope ISS(this, isa(InitExpr)); InitLinkScope ILS(this, InitLink::Field(FirstLinkOffset)); + InitStackScope ISS(this, isa(InitExpr)); if (!emitFieldInitializer(NestedField, NestedFieldOffset, InitExpr, IsUnion)) return false; diff --git a/clang/lib/AST/ByteCode/Compiler.h b/clang/lib/AST/ByteCode/Compiler.h index 5c46f75af4da3..0c6cab9276531 100644 --- a/clang/lib/AST/ByteCode/Compiler.h +++ b/clang/lib/AST/ByteCode/Compiler.h @@ -52,12 +52,14 @@ struct InitLink { K_Decl = 3, K_Elem = 5, K_RVO = 6, - K_InitList = 7 + K_InitList = 7, + K_DIE = 8, }; static InitLink This() { return InitLink{K_This}; } static InitLink InitList() { return InitLink{K_InitList}; } static InitLink RVO() { return InitLink{K_RVO}; } + static InitLink DIE() { return InitLink{K_DIE}; } static InitLink Field(unsigned Offset) { InitLink IL{K_Field}; IL.Offset = Offset; @@ -668,22 +670,29 @@ template class InitLinkScope final { ~InitLinkScope() { this->Ctx->InitStack.pop_back(); } -private: +public: Compiler *Ctx; }; template class InitStackScope final { public: InitStackScope(Compiler *Ctx, bool Active) - : Ctx(Ctx), OldValue(Ctx->InitStackActive) { + : Ctx(Ctx), OldValue(Ctx->InitStackActive), Active(Active) { Ctx->InitStackActive = Active; + if (Active) + Ctx->InitStack.push_back(InitLink::DIE()); } - ~InitStackScope() { this->Ctx->InitStackActive = OldValue; } + ~InitStackScope() { + this->Ctx->InitStackActive = OldValue; + if (Active) + Ctx->InitStack.pop_back(); + } private: Compiler *Ctx; bool OldValue; + bool Active; }; } // namespace interp diff --git a/clang/test/AST/ByteCode/cxx14.cpp b/clang/test/AST/ByteCode/cxx14.cpp index 9622311e100cb..57cb42ea4a98b 100644 --- a/clang/test/AST/ByteCode/cxx14.cpp +++ b/clang/test/AST/ByteCode/cxx14.cpp @@ -7,3 +7,24 @@ constexpr int(*null_ptr)() = nullptr; constexpr int test4 = (*null_ptr)(); // both-error {{must be initialized by a constant expression}} \ // both-note {{evaluates to a null function pointer}} +struct E { + int n = 0; + struct { + void *x = this; + }; + void *y = this; +}; +constexpr E e1 = E(); +static_assert(e1.x != e1.y, ""); +constexpr E e2 = E{0}; +static_assert(e2.x != e2.y, ""); + +struct S { + int &&a = 2; + int b[1]{a}; +}; +constexpr int foo() { + S s{12}; + return s.b[0]; +} +static_assert(foo() == 12, "");