]> granicus.if.org Git - clang/commitdiff
Make sizeof and __alignof work correctly with packed structs.
authorAnders Carlsson <andersca@mac.com>
Sat, 16 Feb 2008 01:20:23 +0000 (01:20 +0000)
committerAnders Carlsson <andersca@mac.com>
Sat, 16 Feb 2008 01:20:23 +0000 (01:20 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@47202 91177308-0d34-0410-b5e6-96231b3b80d8

AST/ASTContext.cpp
AST/Expr.cpp
include/clang/AST/Decl.h
test/Sema/struct-packed-align.c [new file with mode: 0644]

index 608858b55fd16dbcbd0975572e937dd5e335c222..7d7decb6ff0989111513ed7ee1f25fc48a35f4c3 100644 (file)
@@ -319,10 +319,13 @@ const ASTRecordLayout &ASTContext::getASTRecordLayout(const RecordDecl *D,
   unsigned RecordAlign = 8;  // Default alignment = 1 byte = 8 bits.
 
   if (D->getKind() != Decl::Union) {
+    bool StructIsPacked = D->getAttr<PackedAttr>();
+    
     // Layout each field, for now, just sequentially, respecting alignment.  In
     // the future, this will need to be tweakable by targets.
     for (unsigned i = 0, e = D->getNumMembers(); i != e; ++i) {
       const FieldDecl *FD = D->getMember(i);
+      bool FieldIsPacked = StructIsPacked || FD->getAttr<PackedAttr>();
       uint64_t FieldSize;
       unsigned FieldAlign;
       if (FD->getType()->isIncompleteType()) {
@@ -331,12 +334,12 @@ const ASTRecordLayout &ASTContext::getASTRecordLayout(const RecordDecl *D,
         // Flexible array members don't have any size, but they
         // have to be aligned appropriately for their element type.
         const ArrayType* ATy = FD->getType()->getAsArrayType();
-        FieldAlign = getTypeAlign(ATy->getElementType(), L);
+        FieldAlign = FieldIsPacked ? 8 : getTypeAlign(ATy->getElementType(), L);
         FieldSize = 0;
       } else {
         std::pair<uint64_t, unsigned> FieldInfo = getTypeInfo(FD->getType(), L);
         FieldSize = FieldInfo.first;
-        FieldAlign = FieldInfo.second;
+        FieldAlign = FieldIsPacked ? 8 : FieldInfo.second;
       }
 
       // Round up the current record size to the field's alignment boundary.
index b8c564e94e1b901658d3fd8d155c2e729e655fa6..0410e284a72cd431c632450d744419b2d5339dd6 100644 (file)
@@ -784,16 +784,18 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx,
     if (Exp->getArgumentType()->isFunctionType()) {
       // GCC extension: sizeof(function) = 1.
       Result = Exp->isSizeOf() ? 1 : 4;
-    } else if (Exp->isSizeOf()) {
+    } else 
       unsigned CharSize =
         Ctx.Target.getCharWidth(Ctx.getFullLoc(Exp->getOperatorLoc()));
       
-      Result = Ctx.getTypeSize(Exp->getArgumentType(),
-                               Exp->getOperatorLoc()) / CharSize;
+      if (Exp->isSizeOf())
+        Result = Ctx.getTypeSize(Exp->getArgumentType(),
+                                 Exp->getOperatorLoc()) / CharSize;
+      else
+        Result = Ctx.getTypeAlign(Exp->getArgumentType(), 
+                                  Exp->getOperatorLoc()) / CharSize;
     }
-    else
-      Result = Ctx.getTypeAlign(Exp->getArgumentType(), Exp->getOperatorLoc());
-    
+
     break;
   }
   case BinaryOperatorClass: {
index bf8a214eb14d880cb2fd3485a17638483ce1315f..0bf737c1ea4ef7c46aa52c13d896b8d9273c89ce 100644 (file)
@@ -138,9 +138,9 @@ public:
   void addAttr(Attr *attr);
   const Attr *getAttrs() const;
 
-  template<typename T> T *getAttr() {
-    for (Attr *attr = getAttrs(); attr; attr = attr->getNext())
-      if (T *V = dyn_cast<T>(attr))
+  template<typename T> const T *getAttr() const {
+    for (const Attr *attr = getAttrs(); attr; attr = attr->getNext())
+      if (const T *V = dyn_cast<T>(attr))
         return V;
 
     return 0;
diff --git a/test/Sema/struct-packed-align.c b/test/Sema/struct-packed-align.c
new file mode 100644 (file)
index 0000000..23885a5
--- /dev/null
@@ -0,0 +1,37 @@
+// RUN: clang %s -fsyntax-only -verify
+
+struct s {
+    char a;
+    int b  __attribute__((packed));
+    char c;
+    int d;
+};
+
+struct __attribute__((packed)) packed_s {
+    char a;
+    int b  __attribute__((packed));
+    char c;
+    int d;
+};
+
+struct fas {
+    char a;
+    int b[];
+};
+
+struct __attribute__((packed)) packed_fas {
+    char a;
+    int b[];
+};
+
+extern int a1[sizeof(struct s) == 12 ? 1 : -1];
+extern int a2[__alignof(struct s) == 4 ? 1 : -1];
+
+extern int b1[sizeof(struct packed_s) == 10 ? 1 : -1];
+extern int b2[__alignof(struct packed_s) == 1 ? 1 : -1];
+
+extern int c1[sizeof(struct fas) == 4 ? 1 : -1];
+extern int c2[__alignof(struct fas) == 4 ? 1 : -1];
+
+extern int d1[sizeof(struct packed_fas) == 1 ? 1 : -1];
+extern int d2[__alignof(struct packed_fas) == 1 ? 1 : -1];