rogfer01 updated this revision to Diff 69968.
rogfer01 added a comment.

Skip the check if the field is already aligned to 1.


https://reviews.llvm.org/D23657

Files:
  lib/Sema/SemaChecking.cpp
  test/Sema/address-packed.c

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,43 +42,48 @@
 
     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;
     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
+    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();
     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
+    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();
     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
+    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'}}
+}
Index: lib/Sema/SemaChecking.cpp
===================================================================
--- lib/Sema/SemaChecking.cpp
+++ lib/Sema/SemaChecking.cpp
@@ -11016,16 +11016,18 @@
 }
 
 void Sema::DiscardMisalignedMemberAddress(const Type *T, Expr *E) {
-  if (!T->isPointerType())
+  if (!T->isPointerType() && !T->isIntegerType())
     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)
+          (T->isIntegerType() ||
+           (T->isPointerType() &&
+            Context.getTypeAlignInChars(T->getPointeeType()) <= MA->Alignment)))
         MisalignedMembers.erase(MA);
     }
   }
@@ -11035,25 +11037,38 @@
     Expr *E,
     std::function<void(Expr *, RecordDecl *, ValueDecl *, CharUnits)> Action) {
   const auto *ME = dyn_cast<MemberExpr>(E);
+  CharUnits RequiredAlignment;
   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;
+    CharUnits AlignField = Context.getTypeAlignInChars(MD->getType());
 
-    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;
+    RequiredAlignment = std::max(RequiredAlignment, AlignField);
+    if (RD->hasAttr<PackedAttr>() || MD->hasAttr<PackedAttr>()) {
+      CharUnits AlignRecord = Context.getTypeAlignInChars(BaseType);
+      if ((RequiredAlignment > AlignRecord) ||
+          ((Context.toCharUnitsFromBits(
+                Context.getFieldOffset(cast<FieldDecl>(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;
+      }
     }
+    else if (AlignField.isOne())
+        // If this field already has the least alignment possible it will never
+        // yield a misaligned pointer.
+        break;
     ME = dyn_cast<MemberExpr>(ME->getBase());
   }
 }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to