[PATCH] Make getPreferredTypeAlign respect alignments specified with an aligned attribute on a typedef

Stephan Tolksdorf st at quanttec.com
Tue Feb 11 08:29:02 PST 2014


On 14-02-11 00:32, Stephan Tolksdorf wrote:
> The result of alignof(T) is computed using ASTContext::getPreferredTypeAlign, which for certain types may return an alignment that is greater than the one computed by getTypeAlign. This patch teaches getPreferredTypeAlign not to change alignments specified with an aligned attribute on a typedef and thus allows the following test to compile:
>
> typedef long long T __attribute__((aligned(1));
> static_assert(alignof(T) == 1, "");
>
> This patch does not affect the new test in CodeGen/alignment.c, but given the special handling of long long in getPreferredTypeAlign I thought it might be prudent to add a check for long long typedefs with an aligned attribute to the existing test for int typedefs.

I've updated the patch to use getAs<> for the cast, as discussed on IRC.

- Stephan

-------------- next part --------------
---
 lib/AST/ASTContext.cpp   |  5 +++++
 test/CodeGen/alignment.c | 17 +++++++++++++++++
 test/Sema/attr-aligned.c |  3 +++
 3 files changed, 25 insertions(+)

diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 6af79cd..888b76d 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -1762,12 +1762,17 @@ CharUnits ASTContext::getTypeAlignInChars(const Type *T) const {
 unsigned ASTContext::getPreferredTypeAlign(const Type *T) const {
   unsigned ABIAlign = getTypeAlign(T);
 
   if (Target->getTriple().getArch() == llvm::Triple::xcore)
     return ABIAlign;  // Never overalign on XCore.
 
+  // Don't change alignments specified with an aligned attribute on a typedef.
+  if (const TypedefType* TT = T->getAs<TypedefType>())
+    if (TT->getDecl()->getMaxAlignment())
+      return ABIAlign;
+
   // Double and long long should be naturally aligned if possible.
   if (const ComplexType* CT = T->getAs<ComplexType>())
     T = CT->getElementType().getTypePtr();
   if (T->isSpecificBuiltinType(BuiltinType::Double) ||
       T->isSpecificBuiltinType(BuiltinType::LongLong) ||
       T->isSpecificBuiltinType(BuiltinType::ULongLong))
diff --git a/test/CodeGen/alignment.c b/test/CodeGen/alignment.c
index 04d6aac..091bc45 100644
--- a/test/CodeGen/alignment.c
+++ b/test/CodeGen/alignment.c
@@ -24,12 +24,29 @@ int test1a(myint *p) {
 }
 // CHECK: @test1a(
 // CHECK: load i32* {{.*}}, align 1
 // CHECK: ret i32
 
 
+typedef long long int myllint __attribute__((aligned(1)));
+
+void test1b(myllint *p) {
+  *p = 0;
+}
+// CHECK: @test1b(
+// CHECK: store i64 0, i64* {{.*}}, align 1
+// CHECK: ret void
+
+long long int test1c(myllint *p) {
+  return *p;
+}
+// CHECK: @test1c(
+// CHECK: load i64* {{.*}}, align 1
+// CHECK: ret i64
+
+
 // PR5279 - Reduced alignment on typedef.
 typedef float __attribute__((vector_size(16), aligned(4))) packedfloat4;
 
 void test2(packedfloat4 *p) {
   *p = (packedfloat4) { 3.2f, 2.3f, 0.1f, 0.0f };
 }
diff --git a/test/Sema/attr-aligned.c b/test/Sema/attr-aligned.c
index c094ff1..22158e9 100644
--- a/test/Sema/attr-aligned.c
+++ b/test/Sema/attr-aligned.c
@@ -17,12 +17,15 @@ 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__(a) == 1? : -1] = { 0 };
 char a3[sizeof(a) == 1? : -1] = { 0 };
 
+typedef long long __attribute__((aligned(1))) underaligned_longlong;
+char a4[__alignof__(underaligned_longlong) == 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};
-- 
1.7.11.msysgit.1



More information about the cfe-commits mailing list