@@ -13664,10 +13664,11 @@ void Sema::DiagnoseSelfMove(const Expr *LHSExpr, const Expr *RHSExpr,
1366413664
1366513665//===--- Layout compatibility ----------------------------------------------//
1366613666
13667- static bool isLayoutCompatible(ASTContext &C, QualType T1, QualType T2);
13667+ static bool isLayoutCompatible(const ASTContext &C, QualType T1, QualType T2);
1366813668
1366913669/// Check if two enumeration types are layout-compatible.
13670- static bool isLayoutCompatible(ASTContext &C, EnumDecl *ED1, EnumDecl *ED2) {
13670+ static bool isLayoutCompatible(const ASTContext &C, const EnumDecl *ED1,
13671+ const EnumDecl *ED2) {
1367113672 // C++11 [dcl.enum] p8:
1367213673 // Two enumeration types are layout-compatible if they have the same
1367313674 // underlying type.
@@ -13678,8 +13679,8 @@ static bool isLayoutCompatible(ASTContext &C, EnumDecl *ED1, EnumDecl *ED2) {
1367813679/// Check if two fields are layout-compatible.
1367913680/// Can be used on union members, which are exempt from alignment requirement
1368013681/// of common initial sequence.
13681- static bool isLayoutCompatible(ASTContext &C, FieldDecl *Field1,
13682- FieldDecl *Field2,
13682+ static bool isLayoutCompatible(const ASTContext &C, const FieldDecl *Field1,
13683+ const FieldDecl *Field2,
1368313684 bool AreUnionMembers = false) {
1368413685 [[maybe_unused]] const Type *Field1Parent =
1368513686 Field1->getParent()->getTypeForDecl();
@@ -13722,60 +13723,33 @@ static bool isLayoutCompatible(ASTContext &C, FieldDecl *Field1,
1372213723
1372313724/// Check if two standard-layout structs are layout-compatible.
1372413725/// (C++11 [class.mem] p17)
13725- static bool isLayoutCompatibleStruct(ASTContext &C, RecordDecl *RD1,
13726- RecordDecl *RD2) {
13727- // If both records are C++ classes, check that base classes match.
13728- if (const CXXRecordDecl *D1CXX = dyn_cast<CXXRecordDecl>(RD1)) {
13729- // If one of records is a CXXRecordDecl we are in C++ mode,
13730- // thus the other one is a CXXRecordDecl, too.
13731- const CXXRecordDecl *D2CXX = cast<CXXRecordDecl>(RD2);
13732- // Check number of base classes.
13733- if (D1CXX->getNumBases() != D2CXX->getNumBases())
13734- return false;
13726+ static bool isLayoutCompatibleStruct(const ASTContext &C, const RecordDecl *RD1,
13727+ const RecordDecl *RD2) {
13728+ // Get to the class where the fields are declared
13729+ if (const CXXRecordDecl *D1CXX = dyn_cast<CXXRecordDecl>(RD1))
13730+ RD1 = D1CXX->getStandardLayoutBaseWithFields();
1373513731
13736- // Check the base classes.
13737- for (CXXRecordDecl::base_class_const_iterator
13738- Base1 = D1CXX->bases_begin(),
13739- BaseEnd1 = D1CXX->bases_end(),
13740- Base2 = D2CXX->bases_begin();
13741- Base1 != BaseEnd1;
13742- ++Base1, ++Base2) {
13743- if (!isLayoutCompatible(C, Base1->getType(), Base2->getType()))
13744- return false;
13745- }
13746- } else if (const CXXRecordDecl *D2CXX = dyn_cast<CXXRecordDecl>(RD2)) {
13747- // If only RD2 is a C++ class, it should have zero base classes.
13748- if (D2CXX->getNumBases() > 0)
13749- return false;
13750- }
13732+ if (const CXXRecordDecl *D2CXX = dyn_cast<CXXRecordDecl>(RD2))
13733+ RD2 = D2CXX->getStandardLayoutBaseWithFields();
1375113734
1375213735 // Check the fields.
13753- RecordDecl::field_iterator Field2 = RD2->field_begin(),
13754- Field2End = RD2->field_end(),
13755- Field1 = RD1->field_begin(),
13756- Field1End = RD1->field_end();
13757- for ( ; Field1 != Field1End && Field2 != Field2End; ++Field1, ++Field2) {
13758- if (!isLayoutCompatible(C, *Field1, *Field2))
13759- return false;
13760- }
13761- if (Field1 != Field1End || Field2 != Field2End)
13762- return false;
13763-
13764- return true;
13736+ return llvm::equal(RD1->fields(), RD2->fields(),
13737+ [&C](const FieldDecl *F1, const FieldDecl *F2) -> bool {
13738+ return isLayoutCompatible(C, F1, F2);
13739+ });
1376513740}
1376613741
1376713742/// Check if two standard-layout unions are layout-compatible.
1376813743/// (C++11 [class.mem] p18)
13769- static bool isLayoutCompatibleUnion(ASTContext &C, RecordDecl *RD1,
13770- RecordDecl *RD2) {
13771- llvm::SmallPtrSet<FieldDecl *, 8> UnmatchedFields;
13744+ static bool isLayoutCompatibleUnion(const ASTContext &C, const RecordDecl *RD1,
13745+ const RecordDecl *RD2) {
13746+ llvm::SmallPtrSet<const FieldDecl *, 8> UnmatchedFields;
1377213747 for (auto *Field2 : RD2->fields())
1377313748 UnmatchedFields.insert(Field2);
1377413749
1377513750 for (auto *Field1 : RD1->fields()) {
13776- llvm::SmallPtrSet<FieldDecl *, 8>::iterator
13777- I = UnmatchedFields.begin(),
13778- E = UnmatchedFields.end();
13751+ auto I = UnmatchedFields.begin();
13752+ auto E = UnmatchedFields.end();
1377913753
1378013754 for ( ; I != E; ++I) {
1378113755 if (isLayoutCompatible(C, Field1, *I, /*IsUnionMember=*/true)) {
@@ -13792,8 +13766,8 @@ static bool isLayoutCompatibleUnion(ASTContext &C, RecordDecl *RD1,
1379213766 return UnmatchedFields.empty();
1379313767}
1379413768
13795- static bool isLayoutCompatible(ASTContext &C, RecordDecl *RD1,
13796- RecordDecl *RD2) {
13769+ static bool isLayoutCompatible(const ASTContext &C, const RecordDecl *RD1,
13770+ const RecordDecl *RD2) {
1379713771 if (RD1->isUnion() != RD2->isUnion())
1379813772 return false;
1379913773
@@ -13804,7 +13778,7 @@ static bool isLayoutCompatible(ASTContext &C, RecordDecl *RD1,
1380413778}
1380513779
1380613780/// Check if two types are layout-compatible in C++11 sense.
13807- static bool isLayoutCompatible(ASTContext &C, QualType T1, QualType T2) {
13781+ static bool isLayoutCompatible(const ASTContext &C, QualType T1, QualType T2) {
1380813782 if (T1.isNull() || T2.isNull())
1380913783 return false;
1381013784
0 commit comments