Skip to content

Commit 27ed9b4

Browse files
committed
[clang][Interp][NFC] Move ctor compilation to compileConstructor
In preparation for having a similar function for destructors.
1 parent 558d7ad commit 27ed9b4

File tree

2 files changed

+88
-76
lines changed

2 files changed

+88
-76
lines changed

clang/lib/AST/Interp/Compiler.cpp

Lines changed: 87 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -4733,9 +4733,8 @@ bool Compiler<Emitter>::checkLiteralType(const Expr *E) {
47334733
}
47344734

47354735
template <class Emitter>
4736-
bool Compiler<Emitter>::visitFunc(const FunctionDecl *F) {
4737-
// Classify the return type.
4738-
ReturnType = this->classify(F->getReturnType());
4736+
bool Compiler<Emitter>::compileConstructor(const CXXConstructorDecl *Ctor) {
4737+
assert(!ReturnType);
47394738

47404739
auto emitFieldInitializer = [&](const Record::Field *F, unsigned FieldOffset,
47414740
const Expr *InitExpr) -> bool {
@@ -4763,102 +4762,114 @@ bool Compiler<Emitter>::visitFunc(const FunctionDecl *F) {
47634762
return this->emitFinishInitPop(InitExpr);
47644763
};
47654764

4766-
// Emit custom code if this is a lambda static invoker.
4767-
if (const auto *MD = dyn_cast<CXXMethodDecl>(F);
4768-
MD && MD->isLambdaStaticInvoker())
4769-
return this->emitLambdaStaticInvokerBody(MD);
4765+
const RecordDecl *RD = Ctor->getParent();
4766+
const Record *R = this->getRecord(RD);
4767+
if (!R)
4768+
return false;
47704769

4771-
// Constructor. Set up field initializers.
4772-
if (const auto *Ctor = dyn_cast<CXXConstructorDecl>(F)) {
4773-
const RecordDecl *RD = Ctor->getParent();
4774-
const Record *R = this->getRecord(RD);
4775-
if (!R)
4770+
if (R->isUnion() && Ctor->isCopyOrMoveConstructor()) {
4771+
// union copy and move ctors are special.
4772+
assert(cast<CompoundStmt>(Ctor->getBody())->body_empty());
4773+
if (!this->emitThis(Ctor))
47764774
return false;
47774775

4778-
if (R->isUnion() && Ctor->isCopyOrMoveConstructor()) {
4779-
// union copy and move ctors are special.
4780-
assert(cast<CompoundStmt>(Ctor->getBody())->body_empty());
4781-
if (!this->emitThis(Ctor))
4782-
return false;
4776+
auto PVD = Ctor->getParamDecl(0);
4777+
ParamOffset PO = this->Params[PVD]; // Must exist.
47834778

4784-
auto PVD = Ctor->getParamDecl(0);
4785-
ParamOffset PO = this->Params[PVD]; // Must exist.
4779+
if (!this->emitGetParam(PT_Ptr, PO.Offset, Ctor))
4780+
return false;
47864781

4787-
if (!this->emitGetParam(PT_Ptr, PO.Offset, Ctor))
4788-
return false;
4782+
return this->emitMemcpy(Ctor) && this->emitPopPtr(Ctor) &&
4783+
this->emitRetVoid(Ctor);
4784+
}
47894785

4790-
return this->emitMemcpy(Ctor) && this->emitPopPtr(Ctor) &&
4791-
this->emitRetVoid(Ctor);
4792-
}
4786+
InitLinkScope<Emitter> InitScope(this, InitLink::This());
4787+
for (const auto *Init : Ctor->inits()) {
4788+
// Scope needed for the initializers.
4789+
BlockScope<Emitter> Scope(this);
47934790

4794-
InitLinkScope<Emitter> InitScope(this, InitLink::This());
4795-
for (const auto *Init : Ctor->inits()) {
4796-
// Scope needed for the initializers.
4797-
BlockScope<Emitter> Scope(this);
4791+
const Expr *InitExpr = Init->getInit();
4792+
if (const FieldDecl *Member = Init->getMember()) {
4793+
const Record::Field *F = R->getField(Member);
47984794

4799-
const Expr *InitExpr = Init->getInit();
4800-
if (const FieldDecl *Member = Init->getMember()) {
4801-
const Record::Field *F = R->getField(Member);
4795+
if (!emitFieldInitializer(F, F->Offset, InitExpr))
4796+
return false;
4797+
} else if (const Type *Base = Init->getBaseClass()) {
4798+
const auto *BaseDecl = Base->getAsCXXRecordDecl();
4799+
assert(BaseDecl);
48024800

4803-
if (!emitFieldInitializer(F, F->Offset, InitExpr))
4801+
if (Init->isBaseVirtual()) {
4802+
assert(R->getVirtualBase(BaseDecl));
4803+
if (!this->emitGetPtrThisVirtBase(BaseDecl, InitExpr))
48044804
return false;
4805-
} else if (const Type *Base = Init->getBaseClass()) {
4806-
const auto *BaseDecl = Base->getAsCXXRecordDecl();
4807-
assert(BaseDecl);
4808-
4809-
if (Init->isBaseVirtual()) {
4810-
assert(R->getVirtualBase(BaseDecl));
4811-
if (!this->emitGetPtrThisVirtBase(BaseDecl, InitExpr))
4812-
return false;
4813-
4814-
} else {
4815-
// Base class initializer.
4816-
// Get This Base and call initializer on it.
4817-
const Record::Base *B = R->getBase(BaseDecl);
4818-
assert(B);
4819-
if (!this->emitGetPtrThisBase(B->Offset, InitExpr))
4820-
return false;
4821-
}
48224805

4823-
if (!this->visitInitializer(InitExpr))
4824-
return false;
4825-
if (!this->emitFinishInitPop(InitExpr))
4806+
} else {
4807+
// Base class initializer.
4808+
// Get This Base and call initializer on it.
4809+
const Record::Base *B = R->getBase(BaseDecl);
4810+
assert(B);
4811+
if (!this->emitGetPtrThisBase(B->Offset, InitExpr))
48264812
return false;
4827-
} else if (const IndirectFieldDecl *IFD = Init->getIndirectMember()) {
4828-
assert(IFD->getChainingSize() >= 2);
4813+
}
48294814

4830-
unsigned NestedFieldOffset = 0;
4831-
const Record::Field *NestedField = nullptr;
4832-
for (const NamedDecl *ND : IFD->chain()) {
4833-
const auto *FD = cast<FieldDecl>(ND);
4834-
const Record *FieldRecord =
4835-
this->P.getOrCreateRecord(FD->getParent());
4836-
assert(FieldRecord);
4815+
if (!this->visitInitializer(InitExpr))
4816+
return false;
4817+
if (!this->emitFinishInitPop(InitExpr))
4818+
return false;
4819+
} else if (const IndirectFieldDecl *IFD = Init->getIndirectMember()) {
4820+
assert(IFD->getChainingSize() >= 2);
48374821

4838-
NestedField = FieldRecord->getField(FD);
4839-
assert(NestedField);
4822+
unsigned NestedFieldOffset = 0;
4823+
const Record::Field *NestedField = nullptr;
4824+
for (const NamedDecl *ND : IFD->chain()) {
4825+
const auto *FD = cast<FieldDecl>(ND);
4826+
const Record *FieldRecord = this->P.getOrCreateRecord(FD->getParent());
4827+
assert(FieldRecord);
48404828

4841-
NestedFieldOffset += NestedField->Offset;
4842-
}
4829+
NestedField = FieldRecord->getField(FD);
48434830
assert(NestedField);
48444831

4845-
if (!emitFieldInitializer(NestedField, NestedFieldOffset, InitExpr))
4846-
return false;
4847-
} else {
4848-
assert(Init->isDelegatingInitializer());
4849-
if (!this->emitThis(InitExpr))
4850-
return false;
4851-
if (!this->visitInitializer(Init->getInit()))
4852-
return false;
4853-
if (!this->emitPopPtr(InitExpr))
4854-
return false;
4832+
NestedFieldOffset += NestedField->Offset;
48554833
}
4834+
assert(NestedField);
48564835

4857-
if (!Scope.destroyLocals())
4836+
if (!emitFieldInitializer(NestedField, NestedFieldOffset, InitExpr))
4837+
return false;
4838+
} else {
4839+
assert(Init->isDelegatingInitializer());
4840+
if (!this->emitThis(InitExpr))
4841+
return false;
4842+
if (!this->visitInitializer(Init->getInit()))
4843+
return false;
4844+
if (!this->emitPopPtr(InitExpr))
48584845
return false;
48594846
}
4847+
4848+
if (!Scope.destroyLocals())
4849+
return false;
48604850
}
48614851

4852+
if (const auto *Body = Ctor->getBody())
4853+
if (!visitStmt(Body))
4854+
return false;
4855+
4856+
return this->emitRetVoid(SourceInfo{});
4857+
}
4858+
4859+
template <class Emitter>
4860+
bool Compiler<Emitter>::visitFunc(const FunctionDecl *F) {
4861+
// Classify the return type.
4862+
ReturnType = this->classify(F->getReturnType());
4863+
4864+
if (const auto *Ctor = dyn_cast<CXXConstructorDecl>(F))
4865+
return this->compileConstructor(Ctor);
4866+
4867+
// Emit custom code if this is a lambda static invoker.
4868+
if (const auto *MD = dyn_cast<CXXMethodDecl>(F);
4869+
MD && MD->isLambdaStaticInvoker())
4870+
return this->emitLambdaStaticInvokerBody(MD);
4871+
4872+
// Regular functions.
48624873
if (const auto *Body = F->getBody())
48634874
if (!visitStmt(Body))
48644875
return false;

clang/lib/AST/Interp/Compiler.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,7 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,
357357
unsigned collectBaseOffset(const QualType BaseType,
358358
const QualType DerivedType);
359359
bool emitLambdaStaticInvokerBody(const CXXMethodDecl *MD);
360+
bool compileConstructor(const CXXConstructorDecl *Ctor);
360361

361362
bool checkLiteralType(const Expr *E);
362363

0 commit comments

Comments
 (0)