Skip to content

Commit

Permalink
Reapply "[clang][Interp] Fix init chain in local initializers"
Browse files Browse the repository at this point in the history
This reverts commit 2dda8a2.
  • Loading branch information
tbaederr committed Jul 5, 2024
1 parent cc53b95 commit f926e19
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 5 deletions.
21 changes: 18 additions & 3 deletions clang/lib/AST/Interp/Compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,12 @@ bool InitLink::emit(Compiler<Emitter> *Ctx, const Expr *E) const {
case K_Field:
// We're assuming there's a base pointer on the stack already.
return Ctx->emitGetPtrFieldPop(Offset, E);
case K_Temp:
return Ctx->emitGetPtrLocal(Offset, E);
case K_Decl:
return Ctx->visitDeclRef(D, E);
default:
llvm_unreachable("Unhandled InitLink kind");
}
return true;
}
Expand Down Expand Up @@ -1330,6 +1334,7 @@ bool Compiler<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,

auto initCompositeField = [=](const Record::Field *FieldToInit,
const Expr *Init) -> bool {
InitLinkScope<Emitter> ILS(this, InitLink::Field(FieldToInit->Offset));
// Non-primitive case. Get a pointer to the field-to-initialize
// on the stack and recurse into visitInitializer().
if (!this->emitGetPtrField(FieldToInit->Offset, Init))
Expand Down Expand Up @@ -2271,6 +2276,7 @@ bool Compiler<Emitter>::VisitMaterializeTemporaryExpr(
const Expr *Inner = E->getSubExpr()->skipRValueSubobjectAdjustments();
if (std::optional<unsigned> LocalIndex =
allocateLocal(Inner, E->getExtendingDecl())) {
InitLinkScope<Emitter> ILS(this, InitLink::Temp(*LocalIndex));
if (!this->emitGetPtrLocal(*LocalIndex, E))
return false;
return this->visitInitializer(SubExpr);
Expand Down Expand Up @@ -2449,6 +2455,7 @@ bool Compiler<Emitter>::VisitCXXConstructExpr(const CXXConstructExpr *E) {

// Trivial copy/move constructor. Avoid copy.
if (Ctor->isDefaulted() && Ctor->isCopyOrMoveConstructor() &&
Ctor->isTrivial() &&
E->getArg(0)->isTemporaryObject(Ctx.getASTContext(),
T->getAsCXXRecordDecl()))
return this->visitInitializer(E->getArg(0));
Expand Down Expand Up @@ -3583,6 +3590,7 @@ VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD, bool Topleve
return !Init || (checkDecl() && initGlobal(*GlobalIndex));
} else {
VariableScope<Emitter> LocalScope(this, VD);
InitLinkScope<Emitter> ILS(this, InitLink::Decl(VD));

if (VarT) {
unsigned Offset = this->allocateLocalPrimitive(
Expand Down Expand Up @@ -3917,7 +3925,8 @@ bool Compiler<Emitter>::VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E) {
SourceLocScope<Emitter> SLS(this, E);

bool Old = InitStackActive;
InitStackActive = !isa<FunctionDecl>(E->getUsedContext());
InitStackActive =
!(E->getUsedContext()->getDeclKind() == Decl::CXXConstructor);
bool Result = this->delegate(E->getExpr());
InitStackActive = Old;
return Result;
Expand Down Expand Up @@ -3979,8 +3988,14 @@ bool Compiler<Emitter>::VisitCXXThisExpr(const CXXThisExpr *E) {
// currently being initialized. Here we emit the necessary instruction(s) for
// this scenario.
if (InitStackActive && !InitStack.empty()) {
for (const InitLink &IL : InitStack) {
if (!IL.emit<Emitter>(this, E))
unsigned StartIndex = 0;
for (StartIndex = InitStack.size() - 1; StartIndex > 0; --StartIndex) {
if (InitStack[StartIndex].Kind != InitLink::K_Field)
break;
}

for (unsigned I = StartIndex, N = InitStack.size(); I != N; ++I) {
if (!InitStack[I].emit<Emitter>(this, E))
return false;
}
return true;
Expand Down
9 changes: 7 additions & 2 deletions clang/lib/AST/Interp/Compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ struct InitLink {
enum {
K_This = 0,
K_Field = 1,
K_Decl = 2,
K_Temp = 2,
K_Decl = 3,
};

static InitLink This() { return InitLink{K_This}; }
Expand All @@ -56,6 +57,11 @@ struct InitLink {
IL.Offset = Offset;
return IL;
}
static InitLink Temp(unsigned Offset) {
InitLink IL{K_Temp};
IL.Offset = Offset;
return IL;
}
static InitLink Decl(const ValueDecl *D) {
InitLink IL{K_Decl};
IL.D = D;
Expand All @@ -66,7 +72,6 @@ struct InitLink {
template <class Emitter>
bool emit(Compiler<Emitter> *Ctx, const Expr *E) const;

private:
uint32_t Kind;
union {
unsigned Offset;
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/Interp/EvalEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ EvaluationResult EvalEmitter::interpretDecl(const VarDecl *VD,
bool CheckFullyInitialized) {
this->CheckFullyInitialized = CheckFullyInitialized;
S.EvaluatingDecl = VD;
EvalResult.setSource(VD);

if (const Expr *Init = VD->getAnyInitializer()) {
QualType T = VD->getType();
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/Interp/Pointer.h
Original file line number Diff line number Diff line change
Expand Up @@ -638,6 +638,7 @@ class Pointer {
/// Returns the embedded descriptor preceding a field.
InlineDescriptor *getInlineDesc() const {
assert(asBlockPointer().Base != sizeof(GlobalInlineDescriptor));
assert(asBlockPointer().Base <= asBlockPointer().Pointee->getSize());
return getDescriptor(asBlockPointer().Base);
}

Expand Down
12 changes: 12 additions & 0 deletions clang/test/AST/Interp/records.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1482,3 +1482,15 @@ namespace FloatAPValue {
ClassTemplateArgRefTemplate<ClassTemplateArgObj.Arg> ClassTemplateArgRefObj;
}
#endif

namespace LocalWithThisPtrInit {
struct S {
int i;
int *p = &i;
};
constexpr int foo() {
S s{2};
return *s.p;
}
static_assert(foo() == 2, "");
}

0 comments on commit f926e19

Please sign in to comment.