Skip to content

Commit 3ea55d3

Browse files
authored
[clang][bytecode] Add a source location to destructor calls (#110121)
The added test case is still diagnosed differently, but I'm not sure which version is better.
1 parent 3e0d31c commit 3ea55d3

File tree

5 files changed

+46
-14
lines changed

5 files changed

+46
-14
lines changed

clang/lib/AST/ByteCode/Compiler.cpp

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5293,7 +5293,7 @@ bool Compiler<Emitter>::compileDestructor(const CXXDestructorDecl *Dtor) {
52935293
if (!D->isPrimitive() && !D->isPrimitiveArray()) {
52945294
if (!this->emitGetPtrField(Field.Offset, SourceInfo{}))
52955295
return false;
5296-
if (!this->emitDestruction(D))
5296+
if (!this->emitDestruction(D, SourceInfo{}))
52975297
return false;
52985298
if (!this->emitPopPtr(SourceInfo{}))
52995299
return false;
@@ -5307,7 +5307,7 @@ bool Compiler<Emitter>::compileDestructor(const CXXDestructorDecl *Dtor) {
53075307

53085308
if (!this->emitGetPtrBase(Base.Offset, SourceInfo{}))
53095309
return false;
5310-
if (!this->emitRecordDestruction(Base.R))
5310+
if (!this->emitRecordDestruction(Base.R, {}))
53115311
return false;
53125312
if (!this->emitPopPtr(SourceInfo{}))
53135313
return false;
@@ -6148,7 +6148,7 @@ bool Compiler<Emitter>::emitComplexComparison(const Expr *LHS, const Expr *RHS,
61486148
/// on the stack.
61496149
/// Emit destruction of record types (or arrays of record types).
61506150
template <class Emitter>
6151-
bool Compiler<Emitter>::emitRecordDestruction(const Record *R) {
6151+
bool Compiler<Emitter>::emitRecordDestruction(const Record *R, SourceInfo Loc) {
61526152
assert(R);
61536153
assert(!R->isAnonymousUnion());
61546154
const CXXDestructorDecl *Dtor = R->getDestructor();
@@ -6161,15 +6161,16 @@ bool Compiler<Emitter>::emitRecordDestruction(const Record *R) {
61616161
return false;
61626162
assert(DtorFunc->hasThisPointer());
61636163
assert(DtorFunc->getNumParams() == 1);
6164-
if (!this->emitDupPtr(SourceInfo{}))
6164+
if (!this->emitDupPtr(Loc))
61656165
return false;
6166-
return this->emitCall(DtorFunc, 0, SourceInfo{});
6166+
return this->emitCall(DtorFunc, 0, Loc);
61676167
}
61686168
/// When calling this, we have a pointer of the local-to-destroy
61696169
/// on the stack.
61706170
/// Emit destruction of record types (or arrays of record types).
61716171
template <class Emitter>
6172-
bool Compiler<Emitter>::emitDestruction(const Descriptor *Desc) {
6172+
bool Compiler<Emitter>::emitDestruction(const Descriptor *Desc,
6173+
SourceInfo Loc) {
61736174
assert(Desc);
61746175
assert(!Desc->isPrimitive());
61756176
assert(!Desc->isPrimitiveArray());
@@ -6193,13 +6194,13 @@ bool Compiler<Emitter>::emitDestruction(const Descriptor *Desc) {
61936194
}
61946195

61956196
for (ssize_t I = Desc->getNumElems() - 1; I >= 0; --I) {
6196-
if (!this->emitConstUint64(I, SourceInfo{}))
6197+
if (!this->emitConstUint64(I, Loc))
61976198
return false;
6198-
if (!this->emitArrayElemPtrUint64(SourceInfo{}))
6199+
if (!this->emitArrayElemPtrUint64(Loc))
61996200
return false;
6200-
if (!this->emitDestruction(ElemDesc))
6201+
if (!this->emitDestruction(ElemDesc, Loc))
62016202
return false;
6202-
if (!this->emitPopPtr(SourceInfo{}))
6203+
if (!this->emitPopPtr(Loc))
62036204
return false;
62046205
}
62056206
return true;
@@ -6209,7 +6210,7 @@ bool Compiler<Emitter>::emitDestruction(const Descriptor *Desc) {
62096210
if (Desc->ElemRecord->isAnonymousUnion())
62106211
return true;
62116212

6212-
return this->emitRecordDestruction(Desc->ElemRecord);
6213+
return this->emitRecordDestruction(Desc->ElemRecord, Loc);
62136214
}
62146215

62156216
namespace clang {

clang/lib/AST/ByteCode/Compiler.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -364,8 +364,8 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,
364364
bool emitComplexBoolCast(const Expr *E);
365365
bool emitComplexComparison(const Expr *LHS, const Expr *RHS,
366366
const BinaryOperator *E);
367-
bool emitRecordDestruction(const Record *R);
368-
bool emitDestruction(const Descriptor *Desc);
367+
bool emitRecordDestruction(const Record *R, SourceInfo Loc);
368+
bool emitDestruction(const Descriptor *Desc, SourceInfo Loc);
369369
unsigned collectBaseOffset(const QualType BaseType,
370370
const QualType DerivedType);
371371
bool emitLambdaStaticInvokerBody(const CXXMethodDecl *MD);
@@ -540,7 +540,7 @@ template <class Emitter> class LocalScope : public VariableScope<Emitter> {
540540
if (!this->Ctx->emitGetPtrLocal(Local.Offset, E))
541541
return false;
542542

543-
if (!this->Ctx->emitDestruction(Local.Desc))
543+
if (!this->Ctx->emitDestruction(Local.Desc, Local.Desc->getLoc()))
544544
return false;
545545

546546
if (!this->Ctx->emitPopPtr(E))

clang/lib/AST/ByteCode/Descriptor.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "Pointer.h"
1616
#include "PrimType.h"
1717
#include "Record.h"
18+
#include "Source.h"
1819

1920
using namespace clang;
2021
using namespace clang::interp;
@@ -423,6 +424,14 @@ SourceLocation Descriptor::getLocation() const {
423424
llvm_unreachable("Invalid descriptor type");
424425
}
425426

427+
SourceInfo Descriptor::getLoc() const {
428+
if (const auto *D = Source.dyn_cast<const Decl *>())
429+
return SourceInfo(D);
430+
if (const auto *E = Source.dyn_cast<const Expr *>())
431+
return SourceInfo(E);
432+
llvm_unreachable("Invalid descriptor type");
433+
}
434+
426435
bool Descriptor::isUnion() const { return isRecord() && ElemRecord->isUnion(); }
427436

428437
InitMap::InitMap(unsigned N)

clang/lib/AST/ByteCode/Descriptor.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ namespace clang {
2121
namespace interp {
2222
class Block;
2323
class Record;
24+
class SourceInfo;
2425
struct InitMap;
2526
struct Descriptor;
2627
enum PrimType : unsigned;
@@ -194,6 +195,7 @@ struct Descriptor final {
194195
QualType getType() const;
195196
QualType getElemQualType() const;
196197
SourceLocation getLocation() const;
198+
SourceInfo getLoc() const;
197199

198200
const Decl *asDecl() const { return Source.dyn_cast<const Decl *>(); }
199201
const Expr *asExpr() const { return Source.dyn_cast<const Expr *>(); }

clang/test/AST/ByteCode/cxx23.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,3 +269,23 @@ namespace AnonUnionDtor {
269269

270270
void bar() { foo(); }
271271
}
272+
273+
/// FIXME: The two interpreters disagree about there to diagnose the non-constexpr destructor call.
274+
namespace NonLiteralDtorInParam {
275+
class NonLiteral { // all20-note {{is not an aggregate and has no constexpr constructors other than copy or move constructors}}
276+
public:
277+
NonLiteral() {}
278+
~NonLiteral() {} // all23-note {{declared here}}
279+
};
280+
constexpr int F2(NonLiteral N) { // all20-error {{constexpr function's 1st parameter type 'NonLiteral' is not a literal type}} \
281+
// ref23-note {{non-constexpr function '~NonLiteral' cannot be used in a constant expression}}
282+
return 8;
283+
}
284+
285+
286+
void test() {
287+
NonLiteral L;
288+
constexpr auto D = F2(L); // all23-error {{must be initialized by a constant expression}} \
289+
// expected23-note {{non-constexpr function '~NonLiteral' cannot be used in a constant expression}}
290+
}
291+
}

0 commit comments

Comments
 (0)