@@ -13664,10 +13664,11 @@ void Sema::DiagnoseSelfMove(const Expr *LHSExpr, const Expr *RHSExpr,
13664
13664
13665
13665
//===--- Layout compatibility ----------------------------------------------//
13666
13666
13667
- static bool isLayoutCompatible(ASTContext &C, QualType T1, QualType T2);
13667
+ static bool isLayoutCompatible(const ASTContext &C, QualType T1, QualType T2);
13668
13668
13669
13669
/// 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) {
13671
13672
// C++11 [dcl.enum] p8:
13672
13673
// Two enumeration types are layout-compatible if they have the same
13673
13674
// underlying type.
@@ -13678,8 +13679,8 @@ static bool isLayoutCompatible(ASTContext &C, EnumDecl *ED1, EnumDecl *ED2) {
13678
13679
/// Check if two fields are layout-compatible.
13679
13680
/// Can be used on union members, which are exempt from alignment requirement
13680
13681
/// 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,
13683
13684
bool AreUnionMembers = false) {
13684
13685
[[maybe_unused]] const Type *Field1Parent =
13685
13686
Field1->getParent()->getTypeForDecl();
@@ -13722,60 +13723,33 @@ static bool isLayoutCompatible(ASTContext &C, FieldDecl *Field1,
13722
13723
13723
13724
/// Check if two standard-layout structs are layout-compatible.
13724
13725
/// (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();
13735
13731
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();
13751
13734
13752
13735
// 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
+ });
13765
13740
}
13766
13741
13767
13742
/// Check if two standard-layout unions are layout-compatible.
13768
13743
/// (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;
13772
13747
for (auto *Field2 : RD2->fields())
13773
13748
UnmatchedFields.insert(Field2);
13774
13749
13775
13750
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();
13779
13753
13780
13754
for ( ; I != E; ++I) {
13781
13755
if (isLayoutCompatible(C, Field1, *I, /*IsUnionMember=*/true)) {
@@ -13792,8 +13766,8 @@ static bool isLayoutCompatibleUnion(ASTContext &C, RecordDecl *RD1,
13792
13766
return UnmatchedFields.empty();
13793
13767
}
13794
13768
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) {
13797
13771
if (RD1->isUnion() != RD2->isUnion())
13798
13772
return false;
13799
13773
@@ -13804,7 +13778,7 @@ static bool isLayoutCompatible(ASTContext &C, RecordDecl *RD1,
13804
13778
}
13805
13779
13806
13780
/// 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) {
13808
13782
if (T1.isNull() || T2.isNull())
13809
13783
return false;
13810
13784
0 commit comments