Skip to content

Commit 9426870

Browse files
committed
__attribute__((aligned(n))) directly specifies the alignment of a declaration
unless it's a non-packed field, in which case it can only increase the alignment. [[align]] effectively works the same way for well-formed code (because it's ill-formed for [[align]] to decrease alignment ever). Fixes rdar://problem/8335865 llvm-svn: 116070
1 parent b75d0ca commit 9426870

File tree

3 files changed

+42
-7
lines changed

3 files changed

+42
-7
lines changed

clang/lib/AST/ASTContext.cpp

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -532,9 +532,27 @@ const llvm::fltSemantics &ASTContext::getFloatTypeSemantics(QualType T) const {
532532
CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) {
533533
unsigned Align = Target.getCharWidth();
534534

535-
Align = std::max(Align, D->getMaxAlignment());
535+
bool UseAlignAttrOnly = false;
536+
if (unsigned AlignFromAttr = D->getMaxAlignment()) {
537+
Align = AlignFromAttr;
538+
539+
// __attribute__((aligned)) can increase or decrease alignment
540+
// *except* on a struct or struct member, where it only increases
541+
// alignment unless 'packed' is also specified.
542+
//
543+
// It is an error for [[align]] to decrease alignment, so we can
544+
// ignore that possibility; Sema should diagnose it.
545+
if (isa<FieldDecl>(D)) {
546+
UseAlignAttrOnly = D->hasAttr<PackedAttr>() ||
547+
cast<FieldDecl>(D)->getParent()->hasAttr<PackedAttr>();
548+
} else {
549+
UseAlignAttrOnly = true;
550+
}
551+
}
536552

537-
if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
553+
if (UseAlignAttrOnly) {
554+
// ignore type of value
555+
} else if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
538556
QualType T = VD->getType();
539557
if (const ReferenceType* RT = T->getAs<ReferenceType>()) {
540558
if (RefAsPointee)

clang/test/Sema/attr-aligned.c

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,26 @@ struct struct_with_ueber_char {
1313
ueber_aligned_char c;
1414
};
1515

16-
char c = 0;
16+
char a = 0;
1717

1818
char a0[__alignof__(ueber_aligned_char) == 8? 1 : -1] = { 0 };
1919
char a1[__alignof__(struct struct_with_ueber_char) == 8? 1 : -1] = { 0 };
20-
char a2[__alignof__(c) == 1? : -1] = { 0 };
21-
char a3[sizeof(c) == 1? : -1] = { 0 };
20+
char a2[__alignof__(a) == 1? : -1] = { 0 };
21+
char a3[sizeof(a) == 1? : -1] = { 0 };
22+
23+
// rdar://problem/8335865
24+
int b __attribute__((aligned(2)));
25+
char b1[__alignof__(b) == 2 ?: -1] = {0};
26+
27+
struct C { int member __attribute__((aligned(2))); } c;
28+
char c1[__alignof__(c) == 4 ?: -1] = {0};
29+
char c2[__alignof__(c.member) == 4 ?: -1] = {0};
30+
31+
struct D { int member __attribute__((aligned(2))) __attribute__((packed)); } d;
32+
char d1[__alignof__(d) == 2 ?: -1] = {0};
33+
char d2[__alignof__(d.member) == 2 ?: -1] = {0};
34+
35+
struct E { int member __attribute__((aligned(2))); } __attribute__((packed));
36+
struct E e;
37+
char e1[__alignof__(e) == 2 ?: -1] = {0};
38+
char e2[__alignof__(e.member) == 2 ?: -1] = {0};

clang/test/SemaCXX/attr-cxx0x.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@ struct final_override : final_member { virtual void quux (); }; // expected-erro
1010

1111
int align_illegal [[align(3)]]; //expected-error {{requested alignment is not a power of 2}}
1212
char align_big [[align(int)]];
13-
int align_small [[align(1)]];
13+
int align_small [[align(1)]]; // FIXME: this should be rejected
1414
int align_multiple [[align(1), align(8), align(1)]];
1515

1616
struct align_member {
1717
int member [[align(8)]];
1818
};
1919

2020
static_assert(alignof(align_big) == alignof(int), "k's alignment is wrong");
21-
static_assert(alignof(align_small) == alignof(int), "j's alignment is wrong");
21+
static_assert(alignof(align_small) == 1, "j's alignment is wrong");
2222
static_assert(alignof(align_multiple) == 8, "l's alignment is wrong");
2323
static_assert(alignof(align_member) == 8, "quuux's alignment is wrong");
2424
static_assert(sizeof(align_member) == 8, "quuux's size is wrong");

0 commit comments

Comments
 (0)