@@ -185,6 +185,31 @@ template <class Emitter> class StmtExprScope final {
185185 bool OldFlag;
186186};
187187
188+ // / When generating code for e.g. implicit field initializers in constructors,
189+ // / we don't have anything to point to in case the initializer causes an error.
190+ // / In that case, we need to disable location tracking for the initializer so
191+ // / we later point to the call range instead.
192+ template <class Emitter > class LocOverrideScope final {
193+ public:
194+ LocOverrideScope (Compiler<Emitter> *Ctx, SourceInfo NewValue,
195+ bool Enabled = true )
196+ : Ctx(Ctx), OldFlag(Ctx->LocOverride), Enabled(Enabled) {
197+
198+ if (Enabled)
199+ Ctx->LocOverride = NewValue;
200+ }
201+
202+ ~LocOverrideScope () {
203+ if (Enabled)
204+ Ctx->LocOverride = OldFlag;
205+ }
206+
207+ private:
208+ Compiler<Emitter> *Ctx;
209+ std::optional<SourceInfo> OldFlag;
210+ bool Enabled;
211+ };
212+
188213} // namespace interp
189214} // namespace clang
190215
@@ -6017,6 +6042,8 @@ bool Compiler<Emitter>::compileConstructor(const CXXConstructorDecl *Ctor) {
60176042 bool IsUnion = R->isUnion ();
60186043
60196044 if (IsUnion && Ctor->isCopyOrMoveConstructor ()) {
6045+ LocOverrideScope<Emitter> LOS (this , SourceInfo{});
6046+
60206047 if (R->getNumFields () == 0 )
60216048 return this ->emitRetVoid (Ctor);
60226049 // union copy and move ctors are special.
@@ -6043,6 +6070,11 @@ bool Compiler<Emitter>::compileConstructor(const CXXConstructorDecl *Ctor) {
60436070 if (const FieldDecl *Member = Init->getMember ()) {
60446071 const Record::Field *F = R->getField (Member);
60456072
6073+ LocOverrideScope<Emitter> LOS (this , SourceInfo{},
6074+ !Init->isWritten () &&
6075+ !Init->isInClassMemberInitializer () &&
6076+ (!isa<CXXConstructExpr>(InitExpr) ||
6077+ Member->isAnonymousStructOrUnion ()));
60466078 if (!emitFieldInitializer (F, F->Offset , InitExpr, IsUnion))
60476079 return false ;
60486080 } else if (const Type *Base = Init->getBaseClass ()) {
@@ -6071,6 +6103,10 @@ bool Compiler<Emitter>::compileConstructor(const CXXConstructorDecl *Ctor) {
60716103 if (!this ->emitFinishInitPop (InitExpr))
60726104 return false ;
60736105 } else if (const IndirectFieldDecl *IFD = Init->getIndirectMember ()) {
6106+ LocOverrideScope<Emitter> LOS (this , SourceInfo{},
6107+ !Init->isWritten () &&
6108+ !Init->isInClassMemberInitializer () &&
6109+ !isa<CXXConstructExpr>(InitExpr));
60746110
60756111 assert (IFD->getChainingSize () >= 2 );
60766112
@@ -6149,6 +6185,8 @@ bool Compiler<Emitter>::compileDestructor(const CXXDestructorDecl *Dtor) {
61496185
61506186 assert (R);
61516187 if (!R->isUnion ()) {
6188+
6189+ LocOverrideScope<Emitter> LOS (this , SourceInfo{});
61526190 // First, destroy all fields.
61536191 for (const Record::Field &Field : llvm::reverse (R->fields ())) {
61546192 const Descriptor *D = Field.Desc ;
0 commit comments