Improve -Wreorder to handle cases of anonymous class member ordering
authorDavid Blaikie <dblaikie@gmail.com>
Thu, 17 Jan 2013 08:49:22 +0000 (08:49 +0000)
committerDavid Blaikie <dblaikie@gmail.com>
Thu, 17 Jan 2013 08:49:22 +0000 (08:49 +0000)
llvm-svn: 172707

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

index c794d7e..61d8dfc 100644 (file)
@@ -3214,13 +3214,17 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, bool AnyErrors,
   return HadError;
 }
 
-static void *GetKeyForTopLevelField(FieldDecl *Field) {
-  // For anonymous unions, use the class declaration as the key.
+static void PopulateKeysForFields(FieldDecl *Field, SmallVectorImpl<const void*> &IdealInits) {
   if (const RecordType *RT = Field->getType()->getAs<RecordType>()) {
-    if (RT->getDecl()->isAnonymousStructOrUnion())
-      return RT->getDecl();
+    const RecordDecl *RD = RT->getDecl();
+    if (RD->isAnonymousStructOrUnion()) {
+      for (RecordDecl::field_iterator Field = RD->field_begin(),
+          E = RD->field_end(); Field != E; ++Field)
+        PopulateKeysForFields(*Field, IdealInits);
+      return;
+    }
   }
-  return Field;
+  IdealInits.push_back(Field);
 }
 
 static void *GetKeyForBase(ASTContext &Context, QualType BaseType) {
@@ -3232,26 +3236,7 @@ static void *GetKeyForMember(ASTContext &Context,
   if (!Member->isAnyMemberInitializer())
     return GetKeyForBase(Context, QualType(Member->getBaseClass(), 0));
     
-  // For fields injected into the class via declaration of an anonymous union,
-  // use its anonymous union class declaration as the unique key.
-  FieldDecl *Field = Member->getAnyMember();
-  // If the field is a member of an anonymous struct or union, our key
-  // is the anonymous record decl that's a direct child of the class.
-  RecordDecl *RD = Field->getParent();
-  if (RD->isAnonymousStructOrUnion()) {
-    while (true) {
-      RecordDecl *Parent = cast<RecordDecl>(RD->getDeclContext());
-      if (Parent->isAnonymousStructOrUnion())
-        RD = Parent;
-      else
-        break;
-    }
-      
-    return RD;
-  }
-
-  return Field;
+  return Member->getAnyMember();
 }
 
 static void DiagnoseBaseOrMemInitializerOrder(
@@ -3302,7 +3287,7 @@ static void DiagnoseBaseOrMemInitializerOrder(
     if (Field->isUnnamedBitfield())
       continue;
     
-    IdealInitKeys.push_back(GetKeyForTopLevelField(*Field));
+    PopulateKeysForFields(*Field, IdealInitKeys);
   }
   
   unsigned NumIdealInits = IdealInitKeys.size();
index 8c254e5..6d38ec9 100644 (file)
@@ -130,3 +130,14 @@ namespace PR7179 {
     };
   };
 }
+
+namespace test3 {
+  struct foo {
+    struct {
+      int a;
+      int b;
+    };
+    foo() : b(), a() { // expected-warning {{field 'b' will be initialized after field 'a'}}
+    }
+  };
+}