From c9301cf73af73b45ae89b5f8e63c97462dec082f Mon Sep 17 00:00:00 2001 From: David Majnemer <david.majnemer@gmail.com> Date: Wed, 21 Jan 2015 10:54:38 +0000 Subject: [PATCH] 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@226653 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/ASTContext.cpp | 14 ++++++++++++-- lib/Sema/SemaDeclAttr.cpp | 19 +++++++++++-------- test/CXX/dcl.dcl/dcl.attr/dcl.align/p5.cpp | 6 ++++++ test/Sema/align-x86.c | 2 ++ 4 files changed, 31 insertions(+), 10 deletions(-) diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index c1bbc5f085f..c72c239320d 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -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)) diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index c17451eaaaf..c083e9ed6ce 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -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(); } } diff --git a/test/CXX/dcl.dcl/dcl.attr/dcl.align/p5.cpp b/test/CXX/dcl.dcl/dcl.attr/dcl.align/p5.cpp index 3c250f9d25d..e713d72dc58 100644 --- a/test/CXX/dcl.dcl/dcl.attr/dcl.align/p5.cpp +++ b/test/CXX/dcl.dcl/dcl.attr/dcl.align/p5.cpp @@ -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; diff --git a/test/Sema/align-x86.c b/test/Sema/align-x86.c index f112c6398c6..e3b8c704b85 100644 --- a/test/Sema/align-x86.c +++ b/test/Sema/align-x86.c @@ -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 -- GitLab