Index: clang/lib/AST/Interp/Interp.cpp =================================================================== --- clang/lib/AST/Interp/Interp.cpp +++ clang/lib/AST/Interp/Interp.cpp @@ -261,6 +261,14 @@ return true; } + const Function *Func = S.Current->getFunction(); + if (Func && Func->isConstructor()) { + // The This pointer is writable in constructors, even if + // isConst() returns true. + if (Ptr.block() == S.Current->getThis().block()) + return true; + } + const QualType Ty = Ptr.getType(); const SourceInfo &Loc = S.Current->getSource(OpPC); S.FFDiag(Loc, diag::note_constexpr_modify_const_type) << Ty; Index: clang/lib/AST/Interp/Pointer.h =================================================================== --- clang/lib/AST/Interp/Pointer.h +++ clang/lib/AST/Interp/Pointer.h @@ -282,6 +282,8 @@ /// Returns the number of elements. unsigned getNumElems() const { return getSize() / elemSize(); } + Block *block() const { return Pointee; } + /// Returns the index into an array. int64_t getIndex() const { if (isElementPastEnd()) Index: clang/test/AST/Interp/cxx20.cpp =================================================================== --- clang/test/AST/Interp/cxx20.cpp +++ clang/test/AST/Interp/cxx20.cpp @@ -113,3 +113,20 @@ // ref-error {{must be initialized by a constant expression}} \ // ref-note {{subobject of type 'int' is not initialized}} }; + +namespace ConstThis { + class Foo { + const int T = 12; // expected-note {{declared const here}} \ + // ref-note {{declared const here}} + int a; + public: + constexpr Foo() { + this->a = 10; + T = 13; // expected-error {{cannot assign to non-static data member 'T' with const-qualified type}} \ + // ref-error {{cannot assign to non-static data member 'T' with const-qualified type}} + } + }; + constexpr Foo F; // expected-error {{must be initialized by a constant expression}} \ + // ref-error {{must be initialized by a constant expression}} + +};