From: John McCall Date: Fri, 8 Oct 2010 18:24:19 +0000 (+0000) Subject: __attribute__((aligned(n))) directly specifies the alignment of a declaration X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4081a5c5f1381c4ec77f8ab3866693917e4329c4;p=clang __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 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@116070 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 0e549dddcd..1fddd3256f 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -532,9 +532,27 @@ const llvm::fltSemantics &ASTContext::getFloatTypeSemantics(QualType T) const { CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) { unsigned Align = Target.getCharWidth(); - Align = std::max(Align, D->getMaxAlignment()); + bool UseAlignAttrOnly = false; + if (unsigned AlignFromAttr = D->getMaxAlignment()) { + Align = AlignFromAttr; + + // __attribute__((aligned)) can increase or decrease alignment + // *except* on a struct or struct member, where it only increases + // alignment unless 'packed' is also specified. + // + // It is an error for [[align]] to decrease alignment, so we can + // ignore that possibility; Sema should diagnose it. + if (isa(D)) { + UseAlignAttrOnly = D->hasAttr() || + cast(D)->getParent()->hasAttr(); + } else { + UseAlignAttrOnly = true; + } + } - if (const ValueDecl *VD = dyn_cast(D)) { + if (UseAlignAttrOnly) { + // ignore type of value + } else if (const ValueDecl *VD = dyn_cast(D)) { QualType T = VD->getType(); if (const ReferenceType* RT = T->getAs()) { if (RefAsPointee) diff --git a/test/Sema/attr-aligned.c b/test/Sema/attr-aligned.c index bcb12ee40d..c094ff172d 100644 --- a/test/Sema/attr-aligned.c +++ b/test/Sema/attr-aligned.c @@ -13,9 +13,26 @@ struct struct_with_ueber_char { ueber_aligned_char c; }; -char c = 0; +char a = 0; char a0[__alignof__(ueber_aligned_char) == 8? 1 : -1] = { 0 }; char a1[__alignof__(struct struct_with_ueber_char) == 8? 1 : -1] = { 0 }; -char a2[__alignof__(c) == 1? : -1] = { 0 }; -char a3[sizeof(c) == 1? : -1] = { 0 }; +char a2[__alignof__(a) == 1? : -1] = { 0 }; +char a3[sizeof(a) == 1? : -1] = { 0 }; + +// rdar://problem/8335865 +int b __attribute__((aligned(2))); +char b1[__alignof__(b) == 2 ?: -1] = {0}; + +struct C { int member __attribute__((aligned(2))); } c; +char c1[__alignof__(c) == 4 ?: -1] = {0}; +char c2[__alignof__(c.member) == 4 ?: -1] = {0}; + +struct D { int member __attribute__((aligned(2))) __attribute__((packed)); } d; +char d1[__alignof__(d) == 2 ?: -1] = {0}; +char d2[__alignof__(d.member) == 2 ?: -1] = {0}; + +struct E { int member __attribute__((aligned(2))); } __attribute__((packed)); +struct E e; +char e1[__alignof__(e) == 2 ?: -1] = {0}; +char e2[__alignof__(e.member) == 2 ?: -1] = {0}; diff --git a/test/SemaCXX/attr-cxx0x.cpp b/test/SemaCXX/attr-cxx0x.cpp index 8fbf50c26e..4d1e47f7c3 100644 --- a/test/SemaCXX/attr-cxx0x.cpp +++ b/test/SemaCXX/attr-cxx0x.cpp @@ -10,7 +10,7 @@ struct final_override : final_member { virtual void quux (); }; // expected-erro int align_illegal [[align(3)]]; //expected-error {{requested alignment is not a power of 2}} char align_big [[align(int)]]; -int align_small [[align(1)]]; +int align_small [[align(1)]]; // FIXME: this should be rejected int align_multiple [[align(1), align(8), align(1)]]; struct align_member { @@ -18,7 +18,7 @@ struct align_member { }; static_assert(alignof(align_big) == alignof(int), "k's alignment is wrong"); -static_assert(alignof(align_small) == alignof(int), "j's alignment is wrong"); +static_assert(alignof(align_small) == 1, "j's alignment is wrong"); static_assert(alignof(align_multiple) == 8, "l's alignment is wrong"); static_assert(alignof(align_member) == 8, "quuux's alignment is wrong"); static_assert(sizeof(align_member) == 8, "quuux's size is wrong");