Index: lib/Sema/SemaChecking.cpp =================================================================== --- lib/Sema/SemaChecking.cpp +++ lib/Sema/SemaChecking.cpp @@ -11016,7 +11016,7 @@ } void Sema::DiscardMisalignedMemberAddress(const Type *T, Expr *E) { - if (!T->isPointerType()) + if (!T->isPointerType() && !T->isIntegerType()) return; if (isa(E) && cast(E)->getOpcode() == UO_AddrOf) { @@ -11025,7 +11025,9 @@ auto MA = std::find(MisalignedMembers.begin(), MisalignedMembers.end(), MisalignedMember(Op)); if (MA != MisalignedMembers.end() && - Context.getTypeAlignInChars(T->getPointeeType()) <= MA->Alignment) + (T->isIntegerType() || + (T->isPointerType() && + Context.getTypeAlignInChars(T->getPointeeType()) <= MA->Alignment))) MisalignedMembers.erase(MA); } } @@ -11034,7 +11036,9 @@ void Sema::RefersToMemberWithReducedAlignment( Expr *E, std::function Action) { + // return; const auto *ME = dyn_cast(E); + CharUnits RequiredAlignment; while (ME && isa(ME->getMemberDecl())) { QualType BaseType = ME->getBase()->getType(); if (ME->isArrow()) @@ -11042,17 +11046,25 @@ RecordDecl *RD = BaseType->getAs()->getDecl(); ValueDecl *MD = ME->getMemberDecl(); - bool ByteAligned = Context.getTypeAlignInChars(MD->getType()).isOne(); - if (ByteAligned) // Attribute packed does not have any effect. - break; + auto AlignField = Context.getTypeAlignInChars(MD->getType()); - if (!ByteAligned && - (RD->hasAttr() || (MD->hasAttr()))) { - CharUnits Alignment = std::min(Context.getTypeAlignInChars(MD->getType()), - Context.getTypeAlignInChars(BaseType)); - // Notify that this expression designates a member with reduced alignment - Action(E, RD, MD, Alignment); - break; + RequiredAlignment = std::max(RequiredAlignment, AlignField); + if (RD->hasAttr() || MD->hasAttr()) { + auto AlignRecord = Context.getTypeAlignInChars(BaseType); + if ((RequiredAlignment > AlignRecord) || + ((Context.toCharUnitsFromBits( + Context.getFieldOffset(cast(MD))) % + RequiredAlignment) != 0)) { + // If the struct or the field are packed + // - and the required alignment for the field is larger than the + // alignment of the record, or if not that + // - the offset of the field is misaligned to its required alignment + // then notify that this expression designates a member with reduced + // alignment. + CharUnits Alignment = std::min(AlignField, AlignRecord); + Action(E, RD, MD, Alignment); + break; + } } ME = dyn_cast(ME->getBase()); } Index: test/Sema/address-packed.c =================================================================== --- test/Sema/address-packed.c +++ test/Sema/address-packed.c @@ -26,6 +26,7 @@ struct Arguable *get_arguable(); void to_void(void *); +void to_intptr(intptr_t); void g0(void) { { @@ -41,16 +42,18 @@ f1((int *)(void *)&arguable.x); // no-warning to_void(&arguable.x); // no-warning - void *p = &arguable.x; // no-warning; + void *p = &arguable.x; // no-warning to_void(p); + to_intptr((intptr_t)p); // no-warning } { union UnionArguable arguable; f2(&arguable.c); // no-warning f1(&arguable.x); // expected-warning {{packed member 'x' of class or structure 'UnionArguable'}} - f1((int *)(void *)&arguable.x); // no-warning - to_void(&arguable.x); // no-warning + f1((int *)(void *)&arguable.x); // no-warning + to_void(&arguable.x); // no-warning + to_intptr((intptr_t)&arguable.x); // no-warning } { ArguableT arguable; @@ -58,8 +61,9 @@ f1(&arguable.x); // expected-warning {{packed member 'x' of class or structure 'Arguable'}} f2(&arguable.c1); // no-warning - f1((int *)(void *)&arguable.x); // no-warning - to_void(&arguable.x); // no-warning + f1((int *)(void *)&arguable.x); // no-warning + to_void(&arguable.x); // no-warning + to_intptr((intptr_t)&arguable.x); // no-warning } { struct Arguable *arguable = get_arguable(); @@ -67,8 +71,9 @@ f1(&arguable->x); // expected-warning {{packed member 'x' of class or structure 'Arguable'}} f2(&arguable->c1); // no-warning - f1((int *)(void *)&arguable->x); // no-warning - to_void(&arguable->c1); // no-warning + f1((int *)(void *)&arguable->x); // no-warning + to_void(&arguable->c1); // no-warning + to_intptr((intptr_t)&arguable->c1); // no-warning } { ArguableT *arguable = get_arguable(); @@ -76,8 +81,9 @@ f1(&(arguable->x)); // expected-warning {{packed member 'x' of class or structure 'Arguable'}} f2(&(arguable->c1)); // no-warning - f1((int *)(void *)&(arguable->x)); // no-warning - to_void(&(arguable->c1)); // no-warning + f1((int *)(void *)&(arguable->x)); // no-warning + to_void(&(arguable->c1)); // no-warning + to_intptr((intptr_t)&(arguable->c1)); // no-warning } } @@ -161,3 +167,18 @@ { return (struct AlignedTo2Bis*)&s->x; // no-warning } + +struct S6 { + int a; + int _; + int c; + char __; + int d; +} __attribute__((packed, aligned(16))) s6; + +void foo() +{ + f1(&s6.a); // no-warning + f1(&s6.c); // no-warning + f1(&s6.d); // expected-warning {{packed member 'd' of class or structure 'S6'}} +}