r275417 - Diagnose taking address and reference binding of packed members
Reid Kleckner via cfe-commits
cfe-commits at lists.llvm.org
Thu Jul 14 15:52:17 PDT 2016
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.
On Thu, Jul 14, 2016 at 7:10 AM, Roger Ferrer Ibanez via cfe-commits <
cfe-commits at 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 at -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 at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20160714/478e5674/attachment-0001.html>
More information about the cfe-commits
mailing list