Skip to content

Commit 92ac46e

Browse files
committed
[clang][Interp] Handle CXXParenListInitExprs
Differential Revision: https://reviews.llvm.org/D156047
1 parent 98d28e9 commit 92ac46e

File tree

4 files changed

+88
-52
lines changed

4 files changed

+88
-52
lines changed

clang/lib/AST/Interp/ByteCodeExprGen.cpp

Lines changed: 69 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,58 @@ bool ByteCodeExprGen<Emitter>::VisitArraySubscriptExpr(
511511
return this->emitArrayElemPtrPop(IndexT, E);
512512
}
513513

514+
template <class Emitter>
515+
bool ByteCodeExprGen<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
516+
const Expr *E) {
517+
assert(E->getType()->isRecordType());
518+
const Record *R = getRecord(E->getType());
519+
520+
unsigned InitIndex = 0;
521+
for (const Expr *Init : Inits) {
522+
if (!this->emitDupPtr(E))
523+
return false;
524+
525+
if (std::optional<PrimType> T = classify(Init)) {
526+
const Record::Field *FieldToInit = R->getField(InitIndex);
527+
if (!this->visit(Init))
528+
return false;
529+
if (!this->emitInitField(*T, FieldToInit->Offset, E))
530+
return false;
531+
if (!this->emitPopPtr(E))
532+
return false;
533+
++InitIndex;
534+
} else {
535+
// Initializer for a direct base class.
536+
if (const Record::Base *B = R->getBase(Init->getType())) {
537+
if (!this->emitGetPtrBasePop(B->Offset, Init))
538+
return false;
539+
540+
if (!this->visitInitializer(Init))
541+
return false;
542+
543+
if (!this->emitPopPtr(E))
544+
return false;
545+
// Base initializers don't increase InitIndex, since they don't count
546+
// into the Record's fields.
547+
} else {
548+
const Record::Field *FieldToInit = R->getField(InitIndex);
549+
// Non-primitive case. Get a pointer to the field-to-initialize
550+
// on the stack and recurse into visitInitializer().
551+
if (!this->emitGetPtrField(FieldToInit->Offset, Init))
552+
return false;
553+
554+
if (!this->visitInitializer(Init))
555+
return false;
556+
557+
if (!this->emitPopPtr(E))
558+
return false;
559+
++InitIndex;
560+
}
561+
}
562+
}
563+
return true;
564+
}
565+
514566
template <class Emitter>
515567
bool ByteCodeExprGen<Emitter>::VisitInitListExpr(const InitListExpr *E) {
516568
// Handle discarding first.
@@ -530,56 +582,8 @@ bool ByteCodeExprGen<Emitter>::VisitInitListExpr(const InitListExpr *E) {
530582
}
531583

532584
QualType T = E->getType();
533-
if (T->isRecordType()) {
534-
const Record *R = getRecord(T);
535-
536-
unsigned InitIndex = 0;
537-
for (const Expr *Init : E->inits()) {
538-
if (!this->emitDupPtr(E))
539-
return false;
540-
541-
if (std::optional<PrimType> T = classify(Init)) {
542-
const Record::Field *FieldToInit = R->getField(InitIndex);
543-
if (!this->visit(Init))
544-
return false;
545-
546-
if (!this->emitInitField(*T, FieldToInit->Offset, E))
547-
return false;
548-
549-
if (!this->emitPopPtr(E))
550-
return false;
551-
++InitIndex;
552-
} else {
553-
// Initializer for a direct base class.
554-
if (const Record::Base *B = R->getBase(Init->getType())) {
555-
if (!this->emitGetPtrBasePop(B->Offset, Init))
556-
return false;
557-
558-
if (!this->visitInitializer(Init))
559-
return false;
560-
561-
if (!this->emitPopPtr(E))
562-
return false;
563-
// Base initializers don't increase InitIndex, since they don't count
564-
// into the Record's fields.
565-
} else {
566-
const Record::Field *FieldToInit = R->getField(InitIndex);
567-
// Non-primitive case. Get a pointer to the field-to-initialize
568-
// on the stack and recurse into visitInitializer().
569-
if (!this->emitGetPtrField(FieldToInit->Offset, Init))
570-
return false;
571-
572-
if (!this->visitInitializer(Init))
573-
return false;
574-
575-
if (!this->emitPopPtr(E))
576-
return false;
577-
++InitIndex;
578-
}
579-
}
580-
}
581-
return true;
582-
}
585+
if (T->isRecordType())
586+
return this->visitInitList(E->inits(), E);
583587

584588
if (T->isArrayType()) {
585589
// FIXME: Array fillers.
@@ -612,6 +616,21 @@ bool ByteCodeExprGen<Emitter>::VisitInitListExpr(const InitListExpr *E) {
612616
return false;
613617
}
614618

619+
template <class Emitter>
620+
bool ByteCodeExprGen<Emitter>::VisitCXXParenListInitExpr(
621+
const CXXParenListInitExpr *E) {
622+
if (DiscardResult) {
623+
for (const Expr *Init : E->getInitExprs()) {
624+
if (!this->discard(Init))
625+
return false;
626+
}
627+
return true;
628+
}
629+
630+
assert(E->getType()->isRecordType());
631+
return this->visitInitList(E->getInitExprs(), E);
632+
}
633+
615634
template <class Emitter>
616635
bool ByteCodeExprGen<Emitter>::VisitSubstNonTypeTemplateParmExpr(
617636
const SubstNonTypeTemplateParmExpr *E) {

clang/lib/AST/Interp/ByteCodeExprGen.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
8080
bool VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *E);
8181
bool VisitArraySubscriptExpr(const ArraySubscriptExpr *E);
8282
bool VisitInitListExpr(const InitListExpr *E);
83+
bool VisitCXXParenListInitExpr(const CXXParenListInitExpr *E);
8384
bool VisitConstantExpr(const ConstantExpr *E);
8485
bool VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *E);
8586
bool VisitMemberExpr(const MemberExpr *E);
@@ -199,6 +200,8 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
199200
return this->emitPopPtr(I);
200201
}
201202

203+
bool visitInitList(ArrayRef<const Expr *> Inits, const Expr *E);
204+
202205
/// Creates a local primitive value.
203206
unsigned allocateLocalPrimitive(DeclTy &&Decl, PrimType Ty, bool IsConst,
204207
bool IsExtended = false);

clang/test/AST/Interp/records.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -941,7 +941,7 @@ namespace TemporaryObjectExpr {
941941
static_assert(foo(F()) == 0, "");
942942
}
943943

944-
namespace ZeroInit {
944+
namespace ZeroInit {
945945
struct F {
946946
int a;
947947
};
@@ -1052,3 +1052,17 @@ namespace ZeroInit {
10521052
};
10531053
#endif
10541054
}
1055+
1056+
#if __cplusplus >= 202002L
1057+
namespace ParenInit {
1058+
struct A {
1059+
int a;
1060+
};
1061+
1062+
struct B : A {
1063+
int b;
1064+
};
1065+
1066+
constexpr B b(A(1),2);
1067+
}
1068+
#endif

clang/test/SemaCXX/source_location.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
// RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -fms-extensions -DMS -fexceptions -verify %s
55
// RUN: %clang_cc1 -std=c++2a -fcxx-exceptions -fms-extensions -DMS -DUSE_CONSTEVAL -fexceptions -verify %s
66
//
7-
/// FIXME: The -DPAREN_INIT one is missing for the new interpreter.
87
// RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -fexceptions -fexperimental-new-constant-interpreter -DNEW_INTERP -verify %s
98
// RUN: %clang_cc1 -std=c++2a -fcxx-exceptions -DUSE_CONSTEVAL -fexceptions -fexperimental-new-constant-interpreter -DNEW_INTERP -verify %s
9+
// RUN: %clang_cc1 -std=c++2b -fcxx-exceptions -DUSE_CONSTEVAL -DPAREN_INIT -fexceptions -fexperimental-new-constant-interpreter -DNEW_INTERP -verify %s
1010
// RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -fms-extensions -DMS -fexceptions -fexperimental-new-constant-interpreter -DNEW_INTERP -verify %s
1111
// RUN: %clang_cc1 -std=c++2a -fcxx-exceptions -fms-extensions -DMS -DUSE_CONSTEVAL -fexceptions -fexperimental-new-constant-interpreter -DNEW_INTERP -verify %s
1212
// expected-no-diagnostics

0 commit comments

Comments
 (0)