summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEli Friedman <eli.friedman@gmail.com>2009-07-21 19:28:10 +0000
committerEli Friedman <eli.friedman@gmail.com>2009-07-21 19:28:10 +0000
commit952c15dd52a004861edea256479ad80de3148263 (patch)
treee920b3d3cb21c138d1b8fdf5de053ecc9646c496
parentc9ec735aa8871078ca9d9b53f1131103fc1a41b5 (diff)
downloadbcm5719-llvm-952c15dd52a004861edea256479ad80de3148263.tar.gz
bcm5719-llvm-952c15dd52a004861edea256479ad80de3148263.zip
Misc fixes for -Wreorder:
1. Make it work correctly with anonymous unions. 2. Don't compute it if the warning isn't enabled. 3. Optimize the algorithm slightly to make it linear time in the case where we don't produce any warnings. llvm-svn: 76630
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp62
-rw-r--r--clang/test/SemaCXX/warn-reorder-ctor-initialization.cpp15
2 files changed, 53 insertions, 24 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index c62858ac730..cb62debfe95 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -774,6 +774,29 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD,
IdLoc);
}
+static void *GetKeyForTopLevelField(FieldDecl *Field) {
+ // For anonymous unions, use the class declaration as the key.
+ if (const RecordType *RT = Field->getType()->getAsRecordType()) {
+ if (RT->getDecl()->isAnonymousStructOrUnion())
+ return static_cast<void *>(RT->getDecl());
+ }
+ return static_cast<void *>(Field);
+}
+
+static void *GetKeyForMember(CXXBaseOrMemberInitializer *Member) {
+ // For fields injected into the class via declaration of an anonymous union,
+ // use its anonymous union class declaration as the unique key.
+ if (FieldDecl *Field = Member->getMember()) {
+ if (Field->getDeclContext()->isRecord()) {
+ RecordDecl *RD = cast<RecordDecl>(Field->getDeclContext());
+ if (RD->isAnonymousStructOrUnion())
+ return static_cast<void *>(RD);
+ }
+ return static_cast<void *>(Field);
+ }
+ return static_cast<RecordType *>(Member->getBaseClass());
+}
+
void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl,
SourceLocation ColonLoc,
MemInitTy **MemInits, unsigned NumMemInits) {
@@ -792,13 +815,7 @@ void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl,
for (unsigned i = 0; i < NumMemInits; i++) {
CXXBaseOrMemberInitializer *Member =
static_cast<CXXBaseOrMemberInitializer*>(MemInits[i]);
- void *KeyToMember = Member->getBaseOrMember();
- // For fields injected into the class via declaration of an anonymous union,
- // use its anonymous union class declaration as the unique key.
- if (FieldDecl *Field = Member->getMember())
- if (Field->getDeclContext()->isRecord() &&
- cast<RecordDecl>(Field->getDeclContext())->isAnonymousStructOrUnion())
- KeyToMember = static_cast<void *>(Field->getDeclContext());
+ void *KeyToMember = GetKeyForMember(Member);
CXXBaseOrMemberInitializer *&PrevMember = Members[KeyToMember];
if (!PrevMember) {
PrevMember = Member;
@@ -823,6 +840,11 @@ void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl,
Constructor->setBaseOrMemberInitializers(Context,
reinterpret_cast<CXXBaseOrMemberInitializer **>(MemInits),
NumMemInits);
+ }
+ if (!err && (Diags.getDiagnosticLevel(diag::warn_base_initialized)
+ != Diagnostic::Ignored ||
+ Diags.getDiagnosticLevel(diag::warn_field_initialized)
+ != Diagnostic::Ignored)) {
// 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.
llvm::SmallVector<const void*, 32> AllBaseOrMembers;
@@ -846,7 +868,7 @@ void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl,
for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
E = ClassDecl->field_end(); Field != E; ++Field)
- AllBaseOrMembers.push_back(*Field);
+ AllBaseOrMembers.push_back(GetKeyForTopLevelField(*Field));
int Last = AllBaseOrMembers.size();
int curIndex = 0;
@@ -854,19 +876,13 @@ void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl,
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])
+ void *MemberInCtorList = GetKeyForMember(Member);
+
+ for (; curIndex < Last; curIndex++)
+ if (MemberInCtorList == AllBaseOrMembers[curIndex])
break;
- if (j == Last) {
- if (!PrevMember)
- continue;
+ if (curIndex == Last) {
+ assert(PrevMember && "Member not in member list?!");
// Initializer as specified in ctor-initializer list is out of order.
// Issue a warning diagnostic.
if (PrevMember->isBaseInitializer()) {
@@ -893,11 +909,11 @@ void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl,
diag::note_fieldorbase_initialized_here) << 1
<< BaseClass->getDesugaredType(true);
}
+ for (curIndex = 0; curIndex < Last; curIndex++)
+ if (MemberInCtorList == AllBaseOrMembers[curIndex])
+ break;
}
PrevMember = Member;
- for (curIndex=0; curIndex < Last; curIndex++)
- if (MemberInCtorList == AllBaseOrMembers[curIndex])
- break;
}
}
}
diff --git a/clang/test/SemaCXX/warn-reorder-ctor-initialization.cpp b/clang/test/SemaCXX/warn-reorder-ctor-initialization.cpp
index 107c89355e6..a1990329ace 100644
--- a/clang/test/SemaCXX/warn-reorder-ctor-initialization.cpp
+++ b/clang/test/SemaCXX/warn-reorder-ctor-initialization.cpp
@@ -73,4 +73,17 @@ struct X : public virtual A, virtual V, public virtual B {
// expected-note {{base 'struct V'}}
};
-
+class Anon {
+ int c; union {int a,b;}; int d;
+ Anon() : c(10), b(1), d(2) {}
+};
+class Anon2 {
+ int c; union {int a,b;}; int d;
+ Anon2() : c(2),
+ d(10), // expected-warning {{member 'd' will be initialized after}}
+ b(1) {} // expected-note {{field b}}
+};
+class Anon3 {
+ union {int a,b;};
+ Anon3() : b(1) {}
+};
OpenPOWER on IntegriCloud