зеркало из https://github.com/microsoft/clang-1.git
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
This commit is contained in:
Родитель
d70d0b05e5
Коммит
6a24acbb3d
|
@ -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.
|
||||
|
|
14
AST/Expr.cpp
14
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: {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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];
|
Загрузка…
Ссылка в новой задаче