]> granicus.if.org Git - clang/commitdiff
Misc fixes for -Wreorder:
authorEli Friedman <eli.friedman@gmail.com>
Tue, 21 Jul 2009 19:28:10 +0000 (19:28 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Tue, 21 Jul 2009 19:28:10 +0000 (19:28 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@76630 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaDeclCXX.cpp
test/SemaCXX/warn-reorder-ctor-initialization.cpp

index c62858ac73028c0994343800bd38c95408570b73..cb62debfe958e0dfe85ef0fa804c8cf6dbc06db3 100644 (file)
@@ -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;
     }
   }
 }
index 107c89355e6738a882c7ca0ea1add5261dd499e8..a1990329acee985b207efcd2552a3e9be7fb98a5 100644 (file)
@@ -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) {}
+};