From: Anders Carlsson Date: Sat, 16 Feb 2008 01:20:23 +0000 (+0000) Subject: Make sizeof and __alignof work correctly with packed structs. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6a24acbb3dbb3bea9426716bee6ad6023ad15f3f;p=clang Make sizeof and __alignof work correctly with packed structs. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@47202 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/AST/ASTContext.cpp b/AST/ASTContext.cpp index 608858b55f..7d7decb6ff 100644 --- a/AST/ASTContext.cpp +++ b/AST/ASTContext.cpp @@ -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(); + // 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(); 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 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. diff --git a/AST/Expr.cpp b/AST/Expr.cpp index b8c564e94e..0410e284a7 100644 --- a/AST/Expr.cpp +++ b/AST/Expr.cpp @@ -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: { diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index bf8a214eb1..0bf737c1ea 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -138,9 +138,9 @@ public: void addAttr(Attr *attr); const Attr *getAttrs() const; - template T *getAttr() { - for (Attr *attr = getAttrs(); attr; attr = attr->getNext()) - if (T *V = dyn_cast(attr)) + template const T *getAttr() const { + for (const Attr *attr = getAttrs(); attr; attr = attr->getNext()) + if (const T *V = dyn_cast(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 index 0000000000..23885a5461 --- /dev/null +++ b/test/Sema/struct-packed-align.c @@ -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];