Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -5382,6 +5382,9 @@ "dereference of type %1 that was reinterpret_cast from type %0 has undefined " "behavior">, InGroup, 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>; def err_objc_object_assignment : Error< "cannot assign to class object (%0 invalid)">; Index: lib/Sema/SemaExpr.cpp =================================================================== --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -10514,6 +10514,23 @@ return QualType(); } + // Taking the address of a data member/field of a packed + // struct may be a problem if the pointer value is dereferenced + MemberExpr *ME = dyn_cast(op); + while (ME && isa(ME->getMemberDecl())) { + QualType BaseType = ME->getBase()->getType(); + if (ME->isArrow()) + BaseType = BaseType->getPointeeType(); + RecordDecl *RD = BaseType->getAs()->getDecl(); + if (RD->hasAttr() || + ME->getMemberDecl()->hasAttr()) { + Diag(OpLoc, diag::warn_taking_address_of_packed_member) + << ME->getMemberDecl() << RD; + break; + } + ME = dyn_cast(ME->getBase()); + } + return Context.getPointerType(op->getType()); } Index: test/Sema/address-packed.c =================================================================== --- /dev/null +++ test/Sema/address-packed.c @@ -0,0 +1,201 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -xc++ -fsyntax-only -verify %s +extern void f1(int *); +extern void f2(char *); + +struct Ok { + char c; + int x; +}; + +struct __attribute__((packed)) Arguable { + char c; + int x; +#ifdef __cplusplus + static void foo(); +#endif +}; + +union __attribute__((packed)) UnionArguable { + char c; + int x; +#ifdef __cplusplus + static void foo(); +#endif +}; + +extern void f3(void()); + +typedef struct Arguable ArguableT; + +#ifdef __cplusplus +namespace Foo { +struct __attribute__((packed)) Arguable { + char c; + int x; + static void foo(); +}; +} +#endif + +void g0() { + { + struct Ok ok; + f1(&ok.x); // no-warning + f2(&ok.c); // no-warning + } + { + struct Arguable arguable; + f1(&arguable.x); // expected-warning {{packed member 'x' of class or structure 'Arguable'}} + f2(&arguable.c); // expected-warning {{packed member 'c' of class or structure 'Arguable'}} + } + { + union UnionArguable arguable; + f1(&arguable.x); // expected-warning {{packed member 'x' of class or structure 'UnionArguable'}} + f2(&arguable.c); // expected-warning {{packed member 'c' of class or structure 'UnionArguable'}} + } + { + ArguableT arguable; + f1(&arguable.x); // expected-warning {{packed member 'x' of class or structure }} + f2(&arguable.c); // expected-warning {{packed member 'c' of class or structure }} + } + { + struct Arguable *arguable; + f1(&(arguable->x)); // expected-warning {{packed member 'x' of class or structure 'Arguable'}} + f2(&(arguable->c)); // expected-warning {{packed member 'c' of class or structure 'Arguable'}} + } + { + ArguableT *arguable; + f1(&(arguable->x)); // expected-warning {{packed member 'x' of class or structure 'Arguable'}} + f2(&(arguable->c)); // expected-warning {{packed member 'c' of class or structure 'Arguable'}} + } + +#ifdef __cplusplus + { + Ok ok; + f1(&ok.x); // no-warning + f2(&ok.c); // no-warning + } + { + Arguable arguable; + f1(&arguable.x); // expected-warning {{packed member 'x' of class or structure 'Arguable'}} + f2(&arguable.c); // expected-warning {{packed member 'c' of class or structure 'Arguable'}} + f3(&arguable.foo); // no-warning + } + { + Foo::Arguable arguable; + f1(&arguable.x); // expected-warning {{packed member 'x' of class or structure 'Foo::Arguable'}} + f2(&arguable.c); // expected-warning {{packed member 'c' of class or structure 'Foo::Arguable'}} + 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); // expected-warning {{packed member 'c' of class or structure 'Arguable'}} + 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); // expected-warning {{packed member 'c' of class or structure 'Arguable'}} + f3(&arguable->foo); // no-warning + } +#endif +} + +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)'}} +} + +#ifdef __cplusplus +struct __attribute__((packed)) A +{ + char c; + int x; + + 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'}} + } +}; + +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'}} + } +}; +#endif