PR7769: Fix references to anonymous structs/unions in base classes in
offsetof expressions.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@110327 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 6799da1..80274e1 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -6940,22 +6940,27 @@
       Diag(MemberDecl->getLocation(), diag::note_bitfield_decl);
       return ExprError();
     }
-      
+
+    RecordDecl *Parent = MemberDecl->getParent();
+    bool AnonStructUnion = Parent->isAnonymousStructOrUnion();
+    if (AnonStructUnion) {
+      do {
+        Parent = cast<RecordDecl>(Parent->getParent());
+      } while (Parent->isAnonymousStructOrUnion());
+    }
+
     // If the member was found in a base class, introduce OffsetOfNodes for
     // the base class indirections.
     CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
                        /*DetectVirtual=*/false);
-    if (IsDerivedFrom(CurrentType, 
-                      Context.getTypeDeclType(MemberDecl->getParent()), 
-                      Paths)) {
+    if (IsDerivedFrom(CurrentType, Context.getTypeDeclType(Parent), Paths)) {
       CXXBasePath &Path = Paths.front();
       for (CXXBasePath::iterator B = Path.begin(), BEnd = Path.end();
            B != BEnd; ++B)
         Comps.push_back(OffsetOfNode(B->Base));
     }
-    
-    if (cast<RecordDecl>(MemberDecl->getDeclContext())->
-                                                isAnonymousStructOrUnion()) {
+
+    if (AnonStructUnion) {
       llvm::SmallVector<FieldDecl*, 4> Path;
       BuildAnonymousStructUnionMemberPath(MemberDecl, Path);
       unsigned n = Path.size();
diff --git a/test/SemaCXX/offsetof.cpp b/test/SemaCXX/offsetof.cpp
index 639d7fa..17cee62 100644
--- a/test/SemaCXX/offsetof.cpp
+++ b/test/SemaCXX/offsetof.cpp
@@ -53,3 +53,16 @@
 int derived1[__builtin_offsetof(Derived2, x) == 0? 1 : -1];
 int derived2[__builtin_offsetof(Derived2, y)  == 4? 1 : -1];
 int derived3[__builtin_offsetof(Derived2, z)  == 8? 1 : -1];
+
+// offsetof referring to anonymous struct in base.
+// PR7769
+struct foo {
+    struct {
+        int x;
+    };
+};
+
+struct bar : public foo  {
+};
+
+int anonstruct[__builtin_offsetof(bar, x) == 0 ? 1 : -1];