Skip to content

Commit dc7c3c2

Browse files
authored
[clang][bytecode] Disable location tracking for implicit field inits (#150190)
1 parent 940f37a commit dc7c3c2

File tree

13 files changed

+74
-9
lines changed

13 files changed

+74
-9
lines changed

clang/lib/AST/ByteCode/ByteCodeEmitter.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,9 @@ bool ByteCodeEmitter::emitOp(Opcode Op, const Tys &...Args,
216216
// The opcode is followed by arguments. The source info is
217217
// attached to the address after the opcode.
218218
emit(P, Code, Op, Success);
219-
if (SI)
219+
if (LocOverride)
220+
SrcMap.emplace_back(Code.size(), *LocOverride);
221+
else if (SI)
220222
SrcMap.emplace_back(Code.size(), SI);
221223

222224
(..., emit(P, Code, Args, Success));

clang/lib/AST/ByteCode/ByteCodeEmitter.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ class ByteCodeEmitter {
7373
ParamOffset LambdaThisCapture{0, false};
7474
/// Local descriptors.
7575
llvm::SmallVector<SmallVector<Local, 8>, 2> Descriptors;
76+
std::optional<SourceInfo> LocOverride = std::nullopt;
7677

7778
private:
7879
/// Current compilation context.

clang/lib/AST/ByteCode/Compiler.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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;

clang/lib/AST/ByteCode/Compiler.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ template <class Emitter> class LoopScope;
4040
template <class Emitter> class LabelScope;
4141
template <class Emitter> class SwitchScope;
4242
template <class Emitter> class StmtExprScope;
43+
template <class Emitter> class LocOverrideScope;
4344

4445
template <class Emitter> class Compiler;
4546
struct InitLink {
@@ -333,6 +334,7 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,
333334
friend class LabelScope<Emitter>;
334335
friend class SwitchScope<Emitter>;
335336
friend class StmtExprScope<Emitter>;
337+
friend class LocOverrideScope<Emitter>;
336338

337339
/// Emits a zero initializer.
338340
bool visitZeroInitializer(PrimType T, QualType QT, const Expr *E);

clang/lib/AST/ByteCode/EvalEmitter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ EvaluationResult EvalEmitter::interpretDecl(const VarDecl *VD,
5353
bool CheckFullyInitialized) {
5454
this->CheckFullyInitialized = CheckFullyInitialized;
5555
S.EvaluatingDecl = VD;
56+
S.setEvalLocation(VD->getLocation());
5657
EvalResult.setSource(VD);
5758

5859
if (const Expr *Init = VD->getAnyInitializer()) {

clang/lib/AST/ByteCode/EvalEmitter.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ class EvalEmitter : public SourceMapper {
9595
ParamOffset LambdaThisCapture{0, false};
9696
/// Local descriptors.
9797
llvm::SmallVector<SmallVector<Local, 8>, 2> Descriptors;
98+
std::optional<SourceInfo> LocOverride = std::nullopt;
9899

99100
private:
100101
/// Current compilation context.

clang/lib/AST/ByteCode/InterpFrame.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,17 @@ SourceRange InterpFrame::getCallRange() const {
202202
return NullRange;
203203
return S.EvalLocation;
204204
}
205-
return S.getRange(Caller->Func, RetPC - sizeof(uintptr_t));
205+
206+
// Move up to the frame that has a valid location for the caller.
207+
for (const InterpFrame *C = this; C; C = C->Caller) {
208+
if (!C->RetPC)
209+
continue;
210+
SourceRange CallRange =
211+
S.getRange(C->Caller->Func, C->RetPC - sizeof(uintptr_t));
212+
if (CallRange.isValid())
213+
return CallRange;
214+
}
215+
return S.EvalLocation;
206216
}
207217

208218
const FunctionDecl *InterpFrame::getCallee() const {

clang/lib/AST/ByteCode/State.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ void State::addCallStack(unsigned Limit) {
131131
const Frame *Bottom = getBottomFrame();
132132
for (const Frame *F = Top; F != Bottom; F = F->getCaller(), ++CallIdx) {
133133
SourceRange CallRange = F->getCallRange();
134+
assert(CallRange.isValid());
134135

135136
// Skip this call?
136137
if (CallIdx >= SkipStart && CallIdx < SkipEnd) {

clang/test/AST/ByteCode/lifetimes.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@ struct S {
3131
// expected-note {{read of temporary whose lifetime has ended}}
3232
};
3333
constexpr int k1 = S().t; // both-error {{must be initialized by a constant expression}} \
34-
// ref-note {{in call to}} \
35-
// expected-note {{in call to}}
34+
// both-note {{in call to}}
3635

3736

3837
namespace MoveFnWorks {

clang/test/AST/ByteCode/mutable.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,11 @@ namespace MutableInConst {
6666
static_assert(mutableInConst() == 1, "");
6767
}
6868
#endif
69+
70+
struct D { mutable int y; }; // both-note {{declared here}}
71+
constexpr D d1 = { 1 };
72+
constexpr D d2 = d1; // both-error {{must be initialized by a constant expression}} \
73+
// both-note {{read of mutable member 'y}} \
74+
// both-note {{in call to}}
75+
76+

0 commit comments

Comments
 (0)