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