AST: Don't ignore alignas on EnumDecls when calculating alignment

We didn't consider any alignment attributes on an EnumDecl when
calculating alignment.

While we are here, ignore alignment specifications on typedef types if
one is used as the underlying type.  Otherwise, weird things happen:

enum Y : int;
Y y;

typedef int __attribute__((aligned(64))) u;
enum Y : u {};

What is the alignment of 'Y'?  It would be more consistent with the
overall design of enums with fixed underlying types to consider the
underlying type's UnqualifiedDesugaredType.

This fixes PR22279.

llvm-svn: 226653
This commit is contained in:
David Majnemer 2015-01-21 10:54:38 +00:00
parent 435cf8a415
commit 475b25eefa
4 changed files with 31 additions and 10 deletions

View File

@ -1670,8 +1670,16 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
break;
}
if (const EnumType *ET = dyn_cast<EnumType>(TT))
return getTypeInfo(ET->getDecl()->getIntegerType());
if (const EnumType *ET = dyn_cast<EnumType>(TT)) {
const EnumDecl *ED = ET->getDecl();
TypeInfo Info =
getTypeInfo(ED->getIntegerType()->getUnqualifiedDesugaredType());
if (unsigned AttrAlign = ED->getMaxAlignment()) {
Info.Align = AttrAlign;
Info.AlignIsRequired = true;
}
return Info;
}
const RecordType *RT = cast<RecordType>(TT);
const ASTRecordLayout &Layout = getASTRecordLayout(RT->getDecl());
@ -1786,6 +1794,8 @@ unsigned ASTContext::getPreferredTypeAlign(const Type *T) const {
T = T->getBaseElementTypeUnsafe();
if (const ComplexType *CT = T->getAs<ComplexType>())
T = CT->getElementType().getTypePtr();
if (const EnumType *ET = T->getAs<EnumType>())
T = ET->getDecl()->getIntegerType().getTypePtr();
if (T->isSpecificBuiltinType(BuiltinType::Double) ||
T->isSpecificBuiltinType(BuiltinType::LongLong) ||
T->isSpecificBuiltinType(BuiltinType::ULongLong))

View File

@ -2953,12 +2953,15 @@ void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, TypeSourceInfo *TS,
void Sema::CheckAlignasUnderalignment(Decl *D) {
assert(D->hasAttrs() && "no attributes on decl");
QualType Ty;
if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
Ty = VD->getType();
else
Ty = Context.getTagDeclType(cast<TagDecl>(D));
if (Ty->isDependentType() || Ty->isIncompleteType())
QualType UnderlyingTy, DiagTy;
if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
UnderlyingTy = DiagTy = VD->getType();
} else {
UnderlyingTy = DiagTy = Context.getTagDeclType(cast<TagDecl>(D));
if (EnumDecl *ED = dyn_cast<EnumDecl>(D))
UnderlyingTy = ED->getIntegerType();
}
if (DiagTy->isDependentType() || DiagTy->isIncompleteType())
return;
// C++11 [dcl.align]p5, C11 6.7.5/4:
@ -2977,10 +2980,10 @@ void Sema::CheckAlignasUnderalignment(Decl *D) {
if (AlignasAttr && Align) {
CharUnits RequestedAlign = Context.toCharUnitsFromBits(Align);
CharUnits NaturalAlign = Context.getTypeAlignInChars(Ty);
CharUnits NaturalAlign = Context.getTypeAlignInChars(UnderlyingTy);
if (NaturalAlign > RequestedAlign)
Diag(AlignasAttr->getLocation(), diag::err_alignas_underaligned)
<< Ty << (unsigned)NaturalAlign.getQuantity();
<< DiagTy << (unsigned)NaturalAlign.getQuantity();
}
}

View File

@ -15,6 +15,12 @@ enum alignas(1) E1 {}; // expected-error {{requested alignment is less than mini
enum alignas(1) E2 : char {}; // ok
enum alignas(4) E3 { e3 = 0 }; // ok
enum alignas(4) E4 { e4 = 1ull << 33 }; // expected-error {{requested alignment is less than minimum alignment of 8 for type 'E4'}}
enum alignas(8) E5 {};
static_assert(alignof(E5) == 8, "");
typedef __attribute__((aligned(16))) int IntAlign16;
enum E6 : IntAlign16 {};
static_assert(alignof(E6) == 4, "");
struct S1 {
alignas(8) int n;

View File

@ -27,6 +27,8 @@ double g6[3];
short chk1[__alignof__(g6) == 8 ? 1 : -1];
short chk2[__alignof__(double[3]) == 8 ? 1 : -1];
enum { x = 18446744073709551615ULL } g7;
short chk1[__alignof__(g7) == 8 ? 1 : -1];
// PR5637