Sema check on out of order object initialization of
class object's base and members under -Wreorder flag.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@75168 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index e27b822..b942c9c 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -819,10 +819,77 @@
<< 0;
err = true;
}
- if (!err)
+ if (!err) {
Constructor->setBaseOrMemberInitializers(Context,
reinterpret_cast<CXXBaseOrMemberInitializer **>(MemInits),
NumMemInits);
+ // Also issue warning if order of ctor-initializer list does not match order
+ // of 1) base class declarations and 2) order of non-static data members.
+ // FIXME. proper handling in the presense of virtual base class.
+ llvm::SmallVector<const void*, 32> AllBaseOrMembers;
+
+ CXXRecordDecl *ClassDecl
+ = cast<CXXRecordDecl>(Constructor->getDeclContext());
+ for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
+ E = ClassDecl->bases_end(); Base != E; ++Base)
+ AllBaseOrMembers.push_back(Base->getType()->getAsRecordType());
+
+ for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
+ E = ClassDecl->field_end(); Field != E; ++Field)
+ AllBaseOrMembers.push_back(*Field);
+
+ int Last = AllBaseOrMembers.size();
+ int curIndex = 0;
+ CXXBaseOrMemberInitializer *PrevMember = 0;
+ for (unsigned i = 0; i < NumMemInits; i++) {
+ CXXBaseOrMemberInitializer *Member =
+ static_cast<CXXBaseOrMemberInitializer*>(MemInits[i]);
+ void *MemberInCtorList;
+ if (Member->isBaseInitializer())
+ MemberInCtorList = Member->getBaseClass();
+ else
+ MemberInCtorList = Member->getMember();
+
+ int j;
+ for (j = curIndex; j < Last; j++)
+ if (MemberInCtorList == AllBaseOrMembers[j])
+ break;
+ if (j == Last) {
+ if (!PrevMember)
+ continue;
+ // Initializer as specified in ctor-initializer list is out of order.
+ // Issue a warning diagnostic.
+ if (PrevMember->isBaseInitializer()) {
+ // Diagnostics is for an initialized base class.
+ Type *BaseClass = PrevMember->getBaseClass();
+ Diag(PrevMember->getSourceLocation(),
+ diag::warn_base_initialized)
+ << BaseClass->getDesugaredType(true);
+ }
+ else {
+ FieldDecl *Field = PrevMember->getMember();
+ Diag(PrevMember->getSourceLocation(),
+ diag::warn_field_initialized)
+ << Field->getNameAsString();
+ }
+ // Also the note!
+ if (FieldDecl *Field = Member->getMember())
+ Diag(Member->getSourceLocation(),
+ diag::note_fieldorbase_initialized_here) << 0
+ << Field->getNameAsString();
+ else {
+ Type *BaseClass = Member->getBaseClass();
+ Diag(Member->getSourceLocation(),
+ diag::note_fieldorbase_initialized_here) << 1
+ << BaseClass->getDesugaredType(true);
+ }
+ }
+ PrevMember = Member;
+ for (curIndex=0; curIndex < Last; curIndex++)
+ if (MemberInCtorList == AllBaseOrMembers[curIndex])
+ break;
+ }
+ }
}
namespace {