[clang] f926e19 - Reapply "[clang][Interp] Fix init chain in local initializers"
Timm Bäder via cfe-commits
cfe-commits at lists.llvm.org
Fri Jul 5 03:16:33 PDT 2024
Author: Timm Bäder
Date: 2024-07-05T12:16:18+02:00
New Revision: f926e19aa9c0bdca3f05322e1b62562a9a3a05e2
URL: https://github.com/llvm/llvm-project/commit/f926e19aa9c0bdca3f05322e1b62562a9a3a05e2
DIFF: https://github.com/llvm/llvm-project/commit/f926e19aa9c0bdca3f05322e1b62562a9a3a05e2.diff
LOG: Reapply "[clang][Interp] Fix init chain in local initializers"
This reverts commit 2dda8a2650927e4b0fbb459507684455e196d9a9.
Added:
Modified:
clang/lib/AST/Interp/Compiler.cpp
clang/lib/AST/Interp/Compiler.h
clang/lib/AST/Interp/EvalEmitter.cpp
clang/lib/AST/Interp/Pointer.h
clang/test/AST/Interp/records.cpp
Removed:
################################################################################
diff --git a/clang/lib/AST/Interp/Compiler.cpp b/clang/lib/AST/Interp/Compiler.cpp
index 2fd20d8022126..2ada68f6bc756 100644
--- a/clang/lib/AST/Interp/Compiler.cpp
+++ b/clang/lib/AST/Interp/Compiler.cpp
@@ -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;
}
@@ -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))
@@ -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);
@@ -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));
@@ -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(
@@ -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;
@@ -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;
diff --git a/clang/lib/AST/Interp/Compiler.h b/clang/lib/AST/Interp/Compiler.h
index d28526c76fe13..1405abfc1a1e2 100644
--- a/clang/lib/AST/Interp/Compiler.h
+++ b/clang/lib/AST/Interp/Compiler.h
@@ -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}; }
@@ -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;
@@ -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;
diff --git a/clang/lib/AST/Interp/EvalEmitter.cpp b/clang/lib/AST/Interp/EvalEmitter.cpp
index 5d20a0b8182a9..acd1f2c673ce0 100644
--- a/clang/lib/AST/Interp/EvalEmitter.cpp
+++ b/clang/lib/AST/Interp/EvalEmitter.cpp
@@ -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();
diff --git a/clang/lib/AST/Interp/Pointer.h b/clang/lib/AST/Interp/Pointer.h
index fdd921050fd80..7785da1d68f63 100644
--- a/clang/lib/AST/Interp/Pointer.h
+++ b/clang/lib/AST/Interp/Pointer.h
@@ -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);
}
diff --git a/clang/test/AST/Interp/records.cpp b/clang/test/AST/Interp/records.cpp
index 9f341f5bc6d1d..1554e54275598 100644
--- a/clang/test/AST/Interp/records.cpp
+++ b/clang/test/AST/Interp/records.cpp
@@ -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, "");
+}
More information about the cfe-commits
mailing list