AST: Don't ignore alignas on EnumDecls when calculating alignment
authorDavid Majnemer <david.majnemer@gmail.com>
Wed, 21 Jan 2015 10:54:38 +0000 (10:54 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Wed, 21 Jan 2015 10:54:38 +0000 (10:54 +0000)
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

clang/lib/AST/ASTContext.cpp
clang/lib/Sema/SemaDeclAttr.cpp
clang/test/CXX/dcl.dcl/dcl.attr/dcl.align/p5.cpp
clang/test/Sema/align-x86.c

index c1bbc5f085f10718abdcc13be1019991c958aa8f..c72c239320dcf50cb76930c835e38e41f22064c4 100644 (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))
index c17451eaaaf191ca9734ae5dd7a432a1cc20d542..c083e9ed6cef5561117c6ff502fdbb9e56e3596f 100644 (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();
   }
 }
 
index 3c250f9d25dd282d329b4adbc4ac2c441c37a4ca..e713d72dc58fa9bbcef6bac53d81cde7a3ebcc37 100644 (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;
index f112c6398c607498c04380c428e8b6d457a19553..e3b8c704b8584bf185524d7473db34c6ed8c092f 100644 (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