diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 6799da1ab6..80274e1a6b 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -6940,22 +6940,27 @@ Sema::OwningExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc, Diag(MemberDecl->getLocation(), diag::note_bitfield_decl); return ExprError(); } - + + RecordDecl *Parent = MemberDecl->getParent(); + bool AnonStructUnion = Parent->isAnonymousStructOrUnion(); + if (AnonStructUnion) { + do { + Parent = cast(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(MemberDecl->getDeclContext())-> - isAnonymousStructOrUnion()) { + + if (AnonStructUnion) { llvm::SmallVector Path; BuildAnonymousStructUnionMemberPath(MemberDecl, Path); unsigned n = Path.size(); diff --git a/test/SemaCXX/offsetof.cpp b/test/SemaCXX/offsetof.cpp index 639d7faa8e..17cee62d16 100644 --- a/test/SemaCXX/offsetof.cpp +++ b/test/SemaCXX/offsetof.cpp @@ -53,3 +53,16 @@ struct Derived2 : public Base1, public Base2 { 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];