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
This commit is contained in:
Eli Friedman 2010-08-05 10:11:36 +00:00
Родитель 0027d2bb24
Коммит 19410a7e8f
2 изменённых файлов: 25 добавлений и 7 удалений

Просмотреть файл

@ -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<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();

Просмотреть файл

@ -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];