@@ -13706,10 +13706,11 @@ void Sema::DiagnoseSelfMove(const Expr *LHSExpr, const Expr *RHSExpr,
13706
13706
13707
13707
//===--- Layout compatibility ----------------------------------------------//
13708
13708
13709
- static bool isLayoutCompatible(ASTContext &C, QualType T1, QualType T2);
13709
+ static bool isLayoutCompatible(const ASTContext &C, QualType T1, QualType T2);
13710
13710
13711
13711
/// Check if two enumeration types are layout-compatible.
13712
- static bool isLayoutCompatible(ASTContext &C, EnumDecl *ED1, EnumDecl *ED2) {
13712
+ static bool isLayoutCompatible(const ASTContext &C, const EnumDecl *ED1,
13713
+ const EnumDecl *ED2) {
13713
13714
// C++11 [dcl.enum] p8:
13714
13715
// Two enumeration types are layout-compatible if they have the same
13715
13716
// underlying type.
@@ -13720,8 +13721,8 @@ static bool isLayoutCompatible(ASTContext &C, EnumDecl *ED1, EnumDecl *ED2) {
13720
13721
/// Check if two fields are layout-compatible.
13721
13722
/// Can be used on union members, which are exempt from alignment requirement
13722
13723
/// of common initial sequence.
13723
- static bool isLayoutCompatible(ASTContext &C, FieldDecl *Field1,
13724
- FieldDecl *Field2,
13724
+ static bool isLayoutCompatible(const ASTContext &C, const FieldDecl *Field1,
13725
+ const FieldDecl *Field2,
13725
13726
bool AreUnionMembers = false) {
13726
13727
[[maybe_unused]] const Type *Field1Parent =
13727
13728
Field1->getParent()->getTypeForDecl();
@@ -13764,60 +13765,33 @@ static bool isLayoutCompatible(ASTContext &C, FieldDecl *Field1,
13764
13765
13765
13766
/// Check if two standard-layout structs are layout-compatible.
13766
13767
/// (C++11 [class.mem] p17)
13767
- static bool isLayoutCompatibleStruct(ASTContext &C, RecordDecl *RD1,
13768
- RecordDecl *RD2) {
13769
- // If both records are C++ classes, check that base classes match.
13770
- if (const CXXRecordDecl *D1CXX = dyn_cast<CXXRecordDecl>(RD1)) {
13771
- // If one of records is a CXXRecordDecl we are in C++ mode,
13772
- // thus the other one is a CXXRecordDecl, too.
13773
- const CXXRecordDecl *D2CXX = cast<CXXRecordDecl>(RD2);
13774
- // Check number of base classes.
13775
- if (D1CXX->getNumBases() != D2CXX->getNumBases())
13776
- return false;
13768
+ static bool isLayoutCompatibleStruct(const ASTContext &C, const RecordDecl *RD1,
13769
+ const RecordDecl *RD2) {
13770
+ // Get to the class where the fields are declared
13771
+ if (const CXXRecordDecl *D1CXX = dyn_cast<CXXRecordDecl>(RD1))
13772
+ RD1 = D1CXX->getStandardLayoutBaseWithFields();
13777
13773
13778
- // Check the base classes.
13779
- for (CXXRecordDecl::base_class_const_iterator
13780
- Base1 = D1CXX->bases_begin(),
13781
- BaseEnd1 = D1CXX->bases_end(),
13782
- Base2 = D2CXX->bases_begin();
13783
- Base1 != BaseEnd1;
13784
- ++Base1, ++Base2) {
13785
- if (!isLayoutCompatible(C, Base1->getType(), Base2->getType()))
13786
- return false;
13787
- }
13788
- } else if (const CXXRecordDecl *D2CXX = dyn_cast<CXXRecordDecl>(RD2)) {
13789
- // If only RD2 is a C++ class, it should have zero base classes.
13790
- if (D2CXX->getNumBases() > 0)
13791
- return false;
13792
- }
13774
+ if (const CXXRecordDecl *D2CXX = dyn_cast<CXXRecordDecl>(RD2))
13775
+ RD2 = D2CXX->getStandardLayoutBaseWithFields();
13793
13776
13794
13777
// Check the fields.
13795
- RecordDecl::field_iterator Field2 = RD2->field_begin(),
13796
- Field2End = RD2->field_end(),
13797
- Field1 = RD1->field_begin(),
13798
- Field1End = RD1->field_end();
13799
- for ( ; Field1 != Field1End && Field2 != Field2End; ++Field1, ++Field2) {
13800
- if (!isLayoutCompatible(C, *Field1, *Field2))
13801
- return false;
13802
- }
13803
- if (Field1 != Field1End || Field2 != Field2End)
13804
- return false;
13805
-
13806
- return true;
13778
+ return llvm::equal(RD1->fields(), RD2->fields(),
13779
+ [&C](const FieldDecl *F1, const FieldDecl *F2) -> bool {
13780
+ return isLayoutCompatible(C, F1, F2);
13781
+ });
13807
13782
}
13808
13783
13809
13784
/// Check if two standard-layout unions are layout-compatible.
13810
13785
/// (C++11 [class.mem] p18)
13811
- static bool isLayoutCompatibleUnion(ASTContext &C, RecordDecl *RD1,
13812
- RecordDecl *RD2) {
13813
- llvm::SmallPtrSet<FieldDecl *, 8> UnmatchedFields;
13786
+ static bool isLayoutCompatibleUnion(const ASTContext &C, const RecordDecl *RD1,
13787
+ const RecordDecl *RD2) {
13788
+ llvm::SmallPtrSet<const FieldDecl *, 8> UnmatchedFields;
13814
13789
for (auto *Field2 : RD2->fields())
13815
13790
UnmatchedFields.insert(Field2);
13816
13791
13817
13792
for (auto *Field1 : RD1->fields()) {
13818
- llvm::SmallPtrSet<FieldDecl *, 8>::iterator
13819
- I = UnmatchedFields.begin(),
13820
- E = UnmatchedFields.end();
13793
+ auto I = UnmatchedFields.begin();
13794
+ auto E = UnmatchedFields.end();
13821
13795
13822
13796
for ( ; I != E; ++I) {
13823
13797
if (isLayoutCompatible(C, Field1, *I, /*IsUnionMember=*/true)) {
@@ -13834,8 +13808,8 @@ static bool isLayoutCompatibleUnion(ASTContext &C, RecordDecl *RD1,
13834
13808
return UnmatchedFields.empty();
13835
13809
}
13836
13810
13837
- static bool isLayoutCompatible(ASTContext &C, RecordDecl *RD1,
13838
- RecordDecl *RD2) {
13811
+ static bool isLayoutCompatible(const ASTContext &C, const RecordDecl *RD1,
13812
+ const RecordDecl *RD2) {
13839
13813
if (RD1->isUnion() != RD2->isUnion())
13840
13814
return false;
13841
13815
@@ -13846,7 +13820,7 @@ static bool isLayoutCompatible(ASTContext &C, RecordDecl *RD1,
13846
13820
}
13847
13821
13848
13822
/// Check if two types are layout-compatible in C++11 sense.
13849
- static bool isLayoutCompatible(ASTContext &C, QualType T1, QualType T2) {
13823
+ static bool isLayoutCompatible(const ASTContext &C, QualType T1, QualType T2) {
13850
13824
if (T1.isNull() || T2.isNull())
13851
13825
return false;
13852
13826
0 commit comments