OK, actually, GCC is doing something a lot more clever here. Here's what seems to really be going on:
Packed members are modeled somewhat like bitfield members: a packed member lvalue is a different kind of lvalue to which a reference cannot be bound (like a bitfield). An attempt to bind a const / rvalue reference to such a member will create a temporary, copy the packed / bitfield member to the temporary, and then bind the reference to the temporary. If we want to follow GCC here (and I think we do -- this seems like a very sensible model), we should handle this case as an ObjectKind and generally apply the same semantic rules that we use for bitfields. On Thu, Jul 14, 2016 at 5:18 PM, Richard Smith <rich...@metafoo.co.uk> wrote: > It appears that GCC accepts that case. More generally, it looks like GCC > suppresses the warning when the reference is a function parameter (any > function, not just a copy constructor or similar). I'm not sure if that's > an intentional feature or a bug, but it should be pretty easy for us to be > compatible with, at least... > > On Thu, Jul 14, 2016 at 5:03 PM, Reid Kleckner <r...@google.com> wrote: > >> I wonder if GCC accepts this: >> >> In file included from ../../net/tools/quic/quic_epoll_clock_test.cc:7: >> In file included from >> ../../net/tools/quic/test_tools/mock_epoll_server.h:16: >> In file included from ../../net/tools/epoll_server/epoll_server.h:41: >> ../../build/linux/debian_wheezy_amd64-sysroot/usr/include/x86_64-linux-gnu/sys/epoll.h:89:8: >> error: binding reference to packed member 'data' of class or structure >> 'epoll_event' >> struct epoll_event >> ^~~~~~~~~~~ >> ../../build/linux/debian_wheezy_amd64-sysroot/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../include/c++/4.6/bits/stl_pair.h:267:14: >> note: in instantiation of function template specialization 'std::pair<long, >> epoll_event>::pair<long, epoll_event>' requested here >> return __pair_type(std::forward<_T1>(__x), std::forward<_T2>(__y)); >> ^ >> ../../net/tools/quic/test_tools/mock_epoll_server.h:69:30: note: in >> instantiation of function template specialization 'std::make_pair<long &, >> const epoll_event &>' requested here >> event_queue_.insert(std::make_pair(time_in_usec, ee)); >> >> On Thu, Jul 14, 2016 at 4:54 PM, Richard Smith <rich...@metafoo.co.uk> >> wrote: >> >>> On Thu, Jul 14, 2016 at 3:52 PM, Reid Kleckner via cfe-commits < >>> cfe-commits@lists.llvm.org> wrote: >>> >>>> Why did we upgrade the unaligned reference binding from a warning to an >>>> error? That will make it hard to roll this change out across many >>>> codebases. >>>> >>> >>> GCC has given an error on this since version 4.7. If there are cases >>> that GCC accepts and we reject, that sounds like a bug. >>> >>> >>>> On Thu, Jul 14, 2016 at 7:10 AM, Roger Ferrer Ibanez via cfe-commits < >>>> cfe-commits@lists.llvm.org> wrote: >>>> >>>>> Author: rogfer01 >>>>> Date: Thu Jul 14 09:10:43 2016 >>>>> New Revision: 275417 >>>>> >>>>> URL: http://llvm.org/viewvc/llvm-project?rev=275417&view=rev >>>>> Log: >>>>> Diagnose taking address and reference binding of packed members >>>>> >>>>> This patch implements PR#22821. >>>>> >>>>> Taking the address of a packed member is dangerous since the reduced >>>>> alignment of the pointee is lost. This can lead to memory alignment >>>>> faults in some architectures if the pointer value is dereferenced. >>>>> >>>>> This change adds a new warning to clang emitted when taking the address >>>>> of a packed member. A packed member is either a field/data member >>>>> declared as attribute((packed)) or belonging to a struct/class >>>>> declared as such. The associated flag is -Waddress-of-packed-member. >>>>> Conversions (either implicit or via a valid casting) to pointer types >>>>> with lower or equal alignment requirements (e.g. void* or char*) >>>>> silence the warning. >>>>> >>>>> This change also adds a new error diagnostic when the user attempts to >>>>> bind a reference to a packed member, regardless of the alignment. >>>>> >>>>> Differential Revision: https://reviews.llvm.org/D20561 >>>>> >>>>> >>>>> >>>>> Added: >>>>> cfe/trunk/test/Sema/address-packed-member-memops.c >>>>> cfe/trunk/test/Sema/address-packed.c >>>>> cfe/trunk/test/SemaCXX/address-packed-member-memops.cpp >>>>> cfe/trunk/test/SemaCXX/address-packed.cpp >>>>> Modified: >>>>> cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td >>>>> cfe/trunk/include/clang/Sema/Sema.h >>>>> cfe/trunk/lib/Sema/SemaCast.cpp >>>>> cfe/trunk/lib/Sema/SemaChecking.cpp >>>>> cfe/trunk/lib/Sema/SemaExpr.cpp >>>>> cfe/trunk/lib/Sema/SemaInit.cpp >>>>> >>>>> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td >>>>> URL: >>>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=275417&r1=275416&r2=275417&view=diff >>>>> >>>>> ============================================================================== >>>>> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) >>>>> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Jul 14 >>>>> 09:10:43 2016 >>>>> @@ -5425,6 +5425,11 @@ def warn_pointer_indirection_from_incomp >>>>> "dereference of type %1 that was reinterpret_cast from type %0 has >>>>> undefined " >>>>> "behavior">, >>>>> InGroup<UndefinedReinterpretCast>, DefaultIgnore; >>>>> +def warn_taking_address_of_packed_member : Warning< >>>>> + "taking address of packed member %0 of class or structure %q1 may >>>>> result in an unaligned pointer value">, >>>>> + InGroup<DiagGroup<"address-of-packed-member">>; >>>>> +def err_binding_reference_to_packed_member : Error< >>>>> + "binding reference to packed member %0 of class or structure %q1">; >>>>> >>>>> def err_objc_object_assignment : Error< >>>>> "cannot assign to class object (%0 invalid)">; >>>>> >>>>> Modified: cfe/trunk/include/clang/Sema/Sema.h >>>>> URL: >>>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=275417&r1=275416&r2=275417&view=diff >>>>> >>>>> ============================================================================== >>>>> --- cfe/trunk/include/clang/Sema/Sema.h (original) >>>>> +++ cfe/trunk/include/clang/Sema/Sema.h Thu Jul 14 09:10:43 2016 >>>>> @@ -9518,6 +9518,10 @@ private: >>>>> void CheckArgumentWithTypeTag(const ArgumentWithTypeTagAttr *Attr, >>>>> const Expr * const *ExprArgs); >>>>> >>>>> + /// \brief Check if we are taking the address of a packed field >>>>> + /// as this may be a problem if the pointer value is dereferenced. >>>>> + void CheckAddressOfPackedMember(Expr *rhs); >>>>> + >>>>> /// \brief The parser's current scope. >>>>> /// >>>>> /// The parser maintains this state here. >>>>> @@ -9596,6 +9600,51 @@ public: >>>>> // Emitting members of dllexported classes is delayed until the >>>>> class >>>>> // (including field initializers) is fully parsed. >>>>> SmallVector<CXXRecordDecl*, 4> DelayedDllExportClasses; >>>>> + >>>>> +private: >>>>> + /// \brief Helper class that collects misaligned member >>>>> designations and >>>>> + /// their location info for delayed diagnostics. >>>>> + struct MisalignedMember { >>>>> + Expr *E; >>>>> + RecordDecl *RD; >>>>> + ValueDecl *MD; >>>>> + CharUnits Alignment; >>>>> + >>>>> + MisalignedMember() : E(), RD(), MD(), Alignment() {} >>>>> + MisalignedMember(Expr *E, RecordDecl *RD, ValueDecl *MD, >>>>> + CharUnits Alignment) >>>>> + : E(E), RD(RD), MD(MD), Alignment(Alignment) {} >>>>> + explicit MisalignedMember(Expr *E) >>>>> + : MisalignedMember(E, nullptr, nullptr, CharUnits()) {} >>>>> + >>>>> + bool operator==(const MisalignedMember &m) { return this->E == >>>>> m.E; } >>>>> + }; >>>>> + /// \brief Small set of gathered accesses to potentially misaligned >>>>> members >>>>> + /// due to the packed attribute. >>>>> + SmallVector<MisalignedMember, 4> MisalignedMembers; >>>>> + >>>>> + /// \brief Adds an expression to the set of gathered misaligned >>>>> members. >>>>> + void AddPotentialMisalignedMembers(Expr *E, RecordDecl *RD, >>>>> ValueDecl *MD, >>>>> + CharUnits Alignment); >>>>> + >>>>> +public: >>>>> + /// \brief Diagnoses the current set of gathered accesses. This >>>>> typically >>>>> + /// happens at full expression level. The set is cleared after >>>>> emitting the >>>>> + /// diagnostics. >>>>> + void DiagnoseMisalignedMembers(); >>>>> + >>>>> + /// \brief This function checks if the expression is in the sef of >>>>> potentially >>>>> + /// misaligned members and it is converted to some pointer type T >>>>> with lower >>>>> + /// or equal alignment requirements. If so it removes it. This is >>>>> used when >>>>> + /// we do not want to diagnose such misaligned access (e.g. in >>>>> conversions to void*). >>>>> + void DiscardMisalignedMemberAddress(const Type *T, Expr *E); >>>>> + >>>>> + /// \brief This function calls Action when it determines that E >>>>> designates a >>>>> + /// misaligned member due to the packed attribute. This is used to >>>>> emit >>>>> + /// local diagnostics like in reference binding. >>>>> + void RefersToMemberWithReducedAlignment( >>>>> + Expr *E, >>>>> + std::function<void(Expr *, RecordDecl *, ValueDecl *, >>>>> CharUnits)> Action); >>>>> }; >>>>> >>>>> /// \brief RAII object that enters a new expression evaluation >>>>> context. >>>>> >>>>> Modified: cfe/trunk/lib/Sema/SemaCast.cpp >>>>> URL: >>>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCast.cpp?rev=275417&r1=275416&r2=275417&view=diff >>>>> >>>>> ============================================================================== >>>>> --- cfe/trunk/lib/Sema/SemaCast.cpp (original) >>>>> +++ cfe/trunk/lib/Sema/SemaCast.cpp Thu Jul 14 09:10:43 2016 >>>>> @@ -256,6 +256,7 @@ Sema::BuildCXXNamedCast(SourceLocation O >>>>> Op.CheckConstCast(); >>>>> if (Op.SrcExpr.isInvalid()) >>>>> return ExprError(); >>>>> + DiscardMisalignedMemberAddress(DestType.getTypePtr(), E); >>>>> } >>>>> return Op.complete(CXXConstCastExpr::Create(Context, >>>>> Op.ResultType, >>>>> Op.ValueKind, Op.SrcExpr.get(), >>>>> DestTInfo, >>>>> @@ -279,6 +280,7 @@ Sema::BuildCXXNamedCast(SourceLocation O >>>>> Op.CheckReinterpretCast(); >>>>> if (Op.SrcExpr.isInvalid()) >>>>> return ExprError(); >>>>> + DiscardMisalignedMemberAddress(DestType.getTypePtr(), E); >>>>> } >>>>> return Op.complete(CXXReinterpretCastExpr::Create(Context, >>>>> Op.ResultType, >>>>> Op.ValueKind, Op.Kind, >>>>> Op.SrcExpr.get(), >>>>> @@ -291,6 +293,7 @@ Sema::BuildCXXNamedCast(SourceLocation O >>>>> Op.CheckStaticCast(); >>>>> if (Op.SrcExpr.isInvalid()) >>>>> return ExprError(); >>>>> + DiscardMisalignedMemberAddress(DestType.getTypePtr(), E); >>>>> } >>>>> >>>>> return Op.complete(CXXStaticCastExpr::Create(Context, >>>>> Op.ResultType, >>>>> >>>>> Modified: cfe/trunk/lib/Sema/SemaChecking.cpp >>>>> URL: >>>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=275417&r1=275416&r2=275417&view=diff >>>>> >>>>> ============================================================================== >>>>> --- cfe/trunk/lib/Sema/SemaChecking.cpp (original) >>>>> +++ cfe/trunk/lib/Sema/SemaChecking.cpp Thu Jul 14 09:10:43 2016 >>>>> @@ -8302,6 +8302,8 @@ void CheckImplicitConversion(Sema &S, Ex >>>>> >>>>> DiagnoseNullConversion(S, E, T, CC); >>>>> >>>>> + S.DiscardMisalignedMemberAddress(Target, E); >>>>> + >>>>> if (!Source->isIntegerType() || !Target->isIntegerType()) >>>>> return; >>>>> >>>>> @@ -9371,6 +9373,7 @@ void Sema::CheckCompletedExpr(Expr *E, S >>>>> CheckUnsequencedOperations(E); >>>>> if (!IsConstexpr && !E->isValueDependent()) >>>>> CheckForIntOverflow(E); >>>>> + DiagnoseMisalignedMembers(); >>>>> } >>>>> >>>>> void Sema::CheckBitFieldInitialization(SourceLocation InitLoc, >>>>> @@ -10916,3 +10919,67 @@ void Sema::CheckArgumentWithTypeTag(cons >>>>> << ArgumentExpr->getSourceRange() >>>>> << TypeTagExpr->getSourceRange(); >>>>> } >>>>> + >>>>> +void Sema::AddPotentialMisalignedMembers(Expr *E, RecordDecl *RD, >>>>> ValueDecl *MD, >>>>> + CharUnits Alignment) { >>>>> + MisalignedMembers.emplace_back(E, RD, MD, Alignment); >>>>> +} >>>>> + >>>>> +void Sema::DiagnoseMisalignedMembers() { >>>>> + for (MisalignedMember &m : MisalignedMembers) { >>>>> + Diag(m.E->getLocStart(), >>>>> diag::warn_taking_address_of_packed_member) >>>>> + << m.MD << m.RD << m.E->getSourceRange(); >>>>> + } >>>>> + MisalignedMembers.clear(); >>>>> +} >>>>> + >>>>> +void Sema::DiscardMisalignedMemberAddress(const Type *T, Expr *E) { >>>>> + if (!T->isPointerType()) >>>>> + return; >>>>> + if (isa<UnaryOperator>(E) && >>>>> + cast<UnaryOperator>(E)->getOpcode() == UO_AddrOf) { >>>>> + auto *Op = cast<UnaryOperator>(E)->getSubExpr()->IgnoreParens(); >>>>> + if (isa<MemberExpr>(Op)) { >>>>> + auto MA = std::find(MisalignedMembers.begin(), >>>>> MisalignedMembers.end(), >>>>> + MisalignedMember(Op)); >>>>> + if (MA != MisalignedMembers.end() && >>>>> + Context.getTypeAlignInChars(T->getPointeeType()) <= >>>>> MA->Alignment) >>>>> + MisalignedMembers.erase(MA); >>>>> + } >>>>> + } >>>>> +} >>>>> + >>>>> +void Sema::RefersToMemberWithReducedAlignment( >>>>> + Expr *E, >>>>> + std::function<void(Expr *, RecordDecl *, ValueDecl *, CharUnits)> >>>>> Action) { >>>>> + const auto *ME = dyn_cast<MemberExpr>(E); >>>>> + while (ME && isa<FieldDecl>(ME->getMemberDecl())) { >>>>> + QualType BaseType = ME->getBase()->getType(); >>>>> + if (ME->isArrow()) >>>>> + BaseType = BaseType->getPointeeType(); >>>>> + RecordDecl *RD = BaseType->getAs<RecordType>()->getDecl(); >>>>> + >>>>> + ValueDecl *MD = ME->getMemberDecl(); >>>>> + bool ByteAligned = >>>>> Context.getTypeAlignInChars(MD->getType()).isOne(); >>>>> + if (ByteAligned) // Attribute packed does not have any effect. >>>>> + break; >>>>> + >>>>> + if (!ByteAligned && >>>>> + (RD->hasAttr<PackedAttr>() || (MD->hasAttr<PackedAttr>()))) { >>>>> + 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; >>>>> + } >>>>> + ME = dyn_cast<MemberExpr>(ME->getBase()); >>>>> + } >>>>> +} >>>>> + >>>>> +void Sema::CheckAddressOfPackedMember(Expr *rhs) { >>>>> + using namespace std::placeholders; >>>>> + RefersToMemberWithReducedAlignment( >>>>> + rhs, std::bind(&Sema::AddPotentialMisalignedMembers, >>>>> std::ref(*this), _1, >>>>> + _2, _3, _4)); >>>>> +} >>>>> + >>>>> >>>>> Modified: cfe/trunk/lib/Sema/SemaExpr.cpp >>>>> URL: >>>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=275417&r1=275416&r2=275417&view=diff >>>>> >>>>> ============================================================================== >>>>> --- cfe/trunk/lib/Sema/SemaExpr.cpp (original) >>>>> +++ cfe/trunk/lib/Sema/SemaExpr.cpp Thu Jul 14 09:10:43 2016 >>>>> @@ -6001,7 +6001,9 @@ Sema::ActOnCastExpr(Scope *S, SourceLoca >>>>> CheckTollFreeBridgeCast(castType, CastExpr); >>>>> >>>>> CheckObjCBridgeRelatedCast(castType, CastExpr); >>>>> - >>>>> + >>>>> + DiscardMisalignedMemberAddress(castType.getTypePtr(), CastExpr); >>>>> + >>>>> return BuildCStyleCastExpr(LParenLoc, castTInfo, RParenLoc, >>>>> CastExpr); >>>>> } >>>>> >>>>> @@ -10534,6 +10536,8 @@ QualType Sema::CheckAddressOfOperand(Exp >>>>> if (op->getType()->isObjCObjectType()) >>>>> return Context.getObjCObjectPointerType(op->getType()); >>>>> >>>>> + CheckAddressOfPackedMember(op); >>>>> + >>>>> return Context.getPointerType(op->getType()); >>>>> } >>>>> >>>>> >>>>> Modified: cfe/trunk/lib/Sema/SemaInit.cpp >>>>> URL: >>>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=275417&r1=275416&r2=275417&view=diff >>>>> >>>>> ============================================================================== >>>>> --- cfe/trunk/lib/Sema/SemaInit.cpp (original) >>>>> +++ cfe/trunk/lib/Sema/SemaInit.cpp Thu Jul 14 09:10:43 2016 >>>>> @@ -6457,6 +6457,15 @@ InitializationSequence::Perform(Sema &S, >>>>> ExtendingEntity->getDecl()); >>>>> >>>>> CheckForNullPointerDereference(S, CurInit.get()); >>>>> + >>>>> + S.RefersToMemberWithReducedAlignment(CurInit.get(), [&](Expr *E, >>>>> + >>>>> RecordDecl *RD, >>>>> + >>>>> ValueDecl *MD, >>>>> + >>>>> CharUnits) { >>>>> + S.Diag(Kind.getLocation(), >>>>> diag::err_binding_reference_to_packed_member) >>>>> + << MD << RD << E->getSourceRange(); >>>>> + }); >>>>> + >>>>> break; >>>>> >>>>> case SK_BindReferenceToTemporary: { >>>>> @@ -6645,12 +6654,16 @@ InitializationSequence::Perform(Sema &S, >>>>> getAssignmentAction(Entity), CCK); >>>>> if (CurInitExprRes.isInvalid()) >>>>> return ExprError(); >>>>> + >>>>> + S.DiscardMisalignedMemberAddress(Step->Type.getTypePtr(), >>>>> CurInit.get()); >>>>> + >>>>> CurInit = CurInitExprRes; >>>>> >>>>> if (Step->Kind == SK_ConversionSequenceNoNarrowing && >>>>> S.getLangOpts().CPlusPlus && >>>>> !CurInit.get()->isValueDependent()) >>>>> DiagnoseNarrowingInInitList(S, *Step->ICS, SourceType, >>>>> Entity.getType(), >>>>> CurInit.get()); >>>>> + >>>>> break; >>>>> } >>>>> >>>>> >>>>> Added: cfe/trunk/test/Sema/address-packed-member-memops.c >>>>> URL: >>>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/address-packed-member-memops.c?rev=275417&view=auto >>>>> >>>>> ============================================================================== >>>>> --- cfe/trunk/test/Sema/address-packed-member-memops.c (added) >>>>> +++ cfe/trunk/test/Sema/address-packed-member-memops.c Thu Jul 14 >>>>> 09:10:43 2016 >>>>> @@ -0,0 +1,26 @@ >>>>> +// RUN: %clang_cc1 -fsyntax-only -verify %s >>>>> +// expected-no-diagnostics >>>>> + >>>>> +struct B { >>>>> + int x, y, z, w; >>>>> +} b; >>>>> + >>>>> +struct __attribute__((packed)) A { >>>>> + struct B b; >>>>> +} a; >>>>> + >>>>> +typedef __typeof__(sizeof(int)) size_t; >>>>> + >>>>> +void *memcpy(void *dest, const void *src, size_t n); >>>>> +int memcmp(const void *s1, const void *s2, size_t n); >>>>> +void *memmove(void *dest, const void *src, size_t n); >>>>> +void *memset(void *s, int c, size_t n); >>>>> + >>>>> +int x; >>>>> + >>>>> +void foo(void) { >>>>> + memcpy(&a.b, &b, sizeof(b)); >>>>> + memmove(&a.b, &b, sizeof(b)); >>>>> + memset(&a.b, 0, sizeof(b)); >>>>> + x = memcmp(&a.b, &b, sizeof(b)); >>>>> +} >>>>> >>>>> Added: cfe/trunk/test/Sema/address-packed.c >>>>> URL: >>>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/address-packed.c?rev=275417&view=auto >>>>> >>>>> ============================================================================== >>>>> --- cfe/trunk/test/Sema/address-packed.c (added) >>>>> +++ cfe/trunk/test/Sema/address-packed.c Thu Jul 14 09:10:43 2016 >>>>> @@ -0,0 +1,160 @@ >>>>> +// RUN: %clang_cc1 -fsyntax-only -verify %s >>>>> +extern void f1(int *); >>>>> +extern void f2(char *); >>>>> + >>>>> +struct Ok { >>>>> + char c; >>>>> + int x; >>>>> +}; >>>>> + >>>>> +struct __attribute__((packed)) Arguable { >>>>> + char c0; >>>>> + int x; >>>>> + char c1; >>>>> +}; >>>>> + >>>>> +union __attribute__((packed)) UnionArguable { >>>>> + char c; >>>>> + int x; >>>>> +}; >>>>> + >>>>> +typedef struct Arguable ArguableT; >>>>> + >>>>> +struct Arguable *get_arguable(); >>>>> + >>>>> +void to_void(void *); >>>>> + >>>>> +void g0(void) { >>>>> + { >>>>> + struct Ok ok; >>>>> + f1(&ok.x); // no-warning >>>>> + f2(&ok.c); // no-warning >>>>> + } >>>>> + { >>>>> + struct Arguable arguable; >>>>> + f2(&arguable.c0); // no-warning >>>>> + 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 >>>>> + void *p = &arguable.x; // no-warning; >>>>> + to_void(p); >>>>> + } >>>>> + { >>>>> + 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 >>>>> + } >>>>> + { >>>>> + ArguableT arguable; >>>>> + f2(&arguable.c0); // no-warning >>>>> + 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 >>>>> + } >>>>> + { >>>>> + struct Arguable *arguable = get_arguable(); >>>>> + f2(&arguable->c0); // no-warning >>>>> + 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 >>>>> + } >>>>> + { >>>>> + ArguableT *arguable = get_arguable(); >>>>> + f2(&(arguable->c0)); // no-warning >>>>> + 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 >>>>> + } >>>>> +} >>>>> + >>>>> +struct S1 { >>>>> + char c; >>>>> + int i __attribute__((packed)); >>>>> +}; >>>>> + >>>>> +int *g1(struct S1 *s1) { >>>>> + return &s1->i; // expected-warning {{packed member 'i' of class or >>>>> structure 'S1'}} >>>>> +} >>>>> + >>>>> +struct S2_i { >>>>> + int i; >>>>> +}; >>>>> +struct __attribute__((packed)) S2 { >>>>> + char c; >>>>> + struct S2_i inner; >>>>> +}; >>>>> + >>>>> +int *g2(struct S2 *s2) { >>>>> + return &s2->inner.i; // expected-warning {{packed member 'inner' of >>>>> class or structure 'S2'}} >>>>> +} >>>>> + >>>>> +struct S2_a { >>>>> + char c; >>>>> + struct S2_i inner __attribute__((packed)); >>>>> +}; >>>>> + >>>>> +int *g2_a(struct S2_a *s2_a) { >>>>> + return &s2_a->inner.i; // expected-warning {{packed member 'inner' >>>>> of class or structure 'S2_a'}} >>>>> +} >>>>> + >>>>> +struct __attribute__((packed)) S3 { >>>>> + char c; >>>>> + struct { >>>>> + int i; >>>>> + } inner; >>>>> +}; >>>>> + >>>>> +int *g3(struct S3 *s3) { >>>>> + return &s3->inner.i; // expected-warning {{packed member 'inner' of >>>>> class or structure 'S3'}} >>>>> +} >>>>> + >>>>> +struct S4 { >>>>> + char c; >>>>> + struct __attribute__((packed)) { >>>>> + int i; >>>>> + } inner; >>>>> +}; >>>>> + >>>>> +int *g4(struct S4 *s4) { >>>>> + return &s4->inner.i; // expected-warning {{packed member 'i' of >>>>> class or structure 'S4::(anonymous)'}} >>>>> +} >>>>> + >>>>> +struct S5 { >>>>> + char c; >>>>> + struct { >>>>> + char c1; >>>>> + int i __attribute__((packed)); >>>>> + } inner; >>>>> +}; >>>>> + >>>>> +int *g5(struct S5 *s5) { >>>>> + return &s5->inner.i; // expected-warning {{packed member 'i' of >>>>> class or structure 'S5::(anonymous)'}} >>>>> +} >>>>> + >>>>> +struct __attribute__((packed, aligned(2))) AlignedTo2 { >>>>> + int x; >>>>> +}; >>>>> + >>>>> +char *g6(struct AlignedTo2 *s) { >>>>> + return (char *)&s->x; // no-warning >>>>> +} >>>>> + >>>>> +struct __attribute__((packed, aligned(2))) AlignedTo2Bis { >>>>> + int x; >>>>> +}; >>>>> + >>>>> +struct AlignedTo2Bis* g7(struct AlignedTo2 *s) >>>>> +{ >>>>> + return (struct AlignedTo2Bis*)&s->x; // no-warning >>>>> +} >>>>> >>>>> Added: cfe/trunk/test/SemaCXX/address-packed-member-memops.cpp >>>>> URL: >>>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/address-packed-member-memops.cpp?rev=275417&view=auto >>>>> >>>>> ============================================================================== >>>>> --- cfe/trunk/test/SemaCXX/address-packed-member-memops.cpp (added) >>>>> +++ cfe/trunk/test/SemaCXX/address-packed-member-memops.cpp Thu Jul 14 >>>>> 09:10:43 2016 >>>>> @@ -0,0 +1,28 @@ >>>>> +// RUN: %clang_cc1 -fsyntax-only -verify %s >>>>> +// expected-no-diagnostics >>>>> + >>>>> +struct B { >>>>> + int x, y, z, w; >>>>> +} b; >>>>> + >>>>> +struct __attribute__((packed)) A { >>>>> + struct B b; >>>>> +} a; >>>>> + >>>>> +typedef __typeof__(sizeof(int)) size_t; >>>>> + >>>>> +extern "C" { >>>>> +void *memcpy(void *dest, const void *src, size_t n); >>>>> +int memcmp(const void *s1, const void *s2, size_t n); >>>>> +void *memmove(void *dest, const void *src, size_t n); >>>>> +void *memset(void *s, int c, size_t n); >>>>> +} >>>>> + >>>>> +int x; >>>>> + >>>>> +void foo() { >>>>> + memcpy(&a.b, &b, sizeof(b)); >>>>> + memmove(&a.b, &b, sizeof(b)); >>>>> + memset(&a.b, 0, sizeof(b)); >>>>> + x = memcmp(&a.b, &b, sizeof(b)); >>>>> +} >>>>> >>>>> Added: cfe/trunk/test/SemaCXX/address-packed.cpp >>>>> URL: >>>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/address-packed.cpp?rev=275417&view=auto >>>>> >>>>> ============================================================================== >>>>> --- cfe/trunk/test/SemaCXX/address-packed.cpp (added) >>>>> +++ cfe/trunk/test/SemaCXX/address-packed.cpp Thu Jul 14 09:10:43 2016 >>>>> @@ -0,0 +1,118 @@ >>>>> +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s >>>>> +extern void f1(int *); >>>>> +extern void f2(char *); >>>>> + >>>>> +struct __attribute__((packed)) Arguable { >>>>> + int x; >>>>> + char c; >>>>> + static void foo(); >>>>> +}; >>>>> + >>>>> +extern void f3(void()); >>>>> + >>>>> +namespace Foo { >>>>> +struct __attribute__((packed)) Arguable { >>>>> + char c; >>>>> + int x; >>>>> + static void foo(); >>>>> +}; >>>>> +} >>>>> + >>>>> +struct Arguable *get_arguable(); >>>>> + >>>>> +void f4(int &); >>>>> + >>>>> +void to_void(void *); >>>>> + >>>>> +template <typename... T> >>>>> +void sink(T...); >>>>> + >>>>> +void g0() { >>>>> + { >>>>> + Foo::Arguable arguable; >>>>> + f1(&arguable.x); // expected-warning {{packed member 'x' of >>>>> class or structure 'Foo::Arguable'}} >>>>> + f2(&arguable.c); // no-warning >>>>> + f3(&arguable.foo); // no-warning >>>>> + >>>>> + int &w = arguable.x; // expected-error {{binding reference to >>>>> packed member 'x' of class or structure 'Foo::Arguable'}} >>>>> + sink(w); >>>>> + f4(arguable.x); // expected-error {{binding reference to packed >>>>> member 'x' of class or structure 'Foo::Arguable'}} >>>>> + >>>>> + to_void(&arguable.x); // no-warning >>>>> + void *p1 = &arguable.x; // no-warning >>>>> + void *p2 = static_cast<void *>(&arguable.x); // no-warning >>>>> + void *p3 = reinterpret_cast<void *>(&arguable.x); // no-warning >>>>> + void *p4 = (void *)&arguable.x; // no-warning >>>>> + sink(p1, p2, p3, p4); >>>>> + } >>>>> + { >>>>> + Arguable arguable1; >>>>> + Arguable &arguable(arguable1); >>>>> + f1(&arguable.x); // expected-warning {{packed member 'x' of >>>>> class or structure 'Arguable'}} >>>>> + f2(&arguable.c); // no-warning >>>>> + f3(&arguable.foo); // no-warning >>>>> + } >>>>> + { >>>>> + Arguable *arguable1; >>>>> + Arguable *&arguable(arguable1); >>>>> + f1(&arguable->x); // expected-warning {{packed member 'x' of >>>>> class or structure 'Arguable'}} >>>>> + f2(&arguable->c); // no-warning >>>>> + f3(&arguable->foo); // no-warning >>>>> + } >>>>> +} >>>>> + >>>>> +struct __attribute__((packed)) A { >>>>> + int x; >>>>> + char c; >>>>> + >>>>> + int *f0() { >>>>> + return &this->x; // expected-warning {{packed member 'x' of class >>>>> or structure 'A'}} >>>>> + } >>>>> + >>>>> + int *g0() { >>>>> + return &x; // expected-warning {{packed member 'x' of class or >>>>> structure 'A'}} >>>>> + } >>>>> + >>>>> + char *h0() { >>>>> + return &c; // no-warning >>>>> + } >>>>> +}; >>>>> + >>>>> +struct B : A { >>>>> + int *f1() { >>>>> + return &this->x; // expected-warning {{packed member 'x' of class >>>>> or structure 'A'}} >>>>> + } >>>>> + >>>>> + int *g1() { >>>>> + return &x; // expected-warning {{packed member 'x' of class or >>>>> structure 'A'}} >>>>> + } >>>>> + >>>>> + char *h1() { >>>>> + return &c; // no-warning >>>>> + } >>>>> +}; >>>>> + >>>>> +template <typename Ty> >>>>> +class __attribute__((packed)) S { >>>>> + Ty X; >>>>> + >>>>> +public: >>>>> + const Ty *get() const { >>>>> + return &X; // expected-warning {{packed member 'X' of class or >>>>> structure 'S<int>'}} >>>>> + // expected-warning@-1 {{packed member 'X' of class >>>>> or structure 'S<float>'}} >>>>> + } >>>>> +}; >>>>> + >>>>> +template <typename Ty> >>>>> +void h(Ty *); >>>>> + >>>>> +void g1() { >>>>> + S<int> s1; >>>>> + s1.get(); // expected-note {{in instantiation of member function >>>>> 'S<int>::get'}} >>>>> + >>>>> + S<char> s2; >>>>> + s2.get(); >>>>> + >>>>> + S<float> s3; >>>>> + s3.get(); // expected-note {{in instantiation of member function >>>>> 'S<float>::get'}} >>>>> +} >>>>> >>>>> >>>>> _______________________________________________ >>>>> cfe-commits mailing list >>>>> cfe-commits@lists.llvm.org >>>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits >>>>> >>>> >>>> >>>> _______________________________________________ >>>> cfe-commits mailing list >>>> cfe-commits@lists.llvm.org >>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits >>>> >>>> >>> >> >
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits