aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Basic/TargetInfo.h6
-rw-r--r--lib/AST/ASTContext.cpp9
-rw-r--r--lib/Basic/TargetInfo.cpp2
-rw-r--r--lib/Basic/Targets.cpp2
-rw-r--r--test/CodeGen/const-arithmetic.c4
-rw-r--r--test/CodeGenCXX/static-init.cpp2
-rw-r--r--test/Sema/align-x86-64.c11
7 files changed, 33 insertions, 3 deletions
diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h
index 00fd9b92e1..0cef286afe 100644
--- a/include/clang/Basic/TargetInfo.h
+++ b/include/clang/Basic/TargetInfo.h
@@ -51,6 +51,7 @@ protected:
unsigned char FloatWidth, FloatAlign;
unsigned char DoubleWidth, DoubleAlign;
unsigned char LongDoubleWidth, LongDoubleAlign;
+ unsigned char LargeArrayMinWidth, LargeArrayAlign;
unsigned char LongWidth, LongAlign;
unsigned char LongLongWidth, LongLongAlign;
const char *DescriptionString;
@@ -194,6 +195,11 @@ public:
return *LongDoubleFormat;
}
+ // getLargeArrayMinWidth/Align - Return the minimum array size that is
+ // 'large' and its alignment.
+ unsigned getLargeArrayMinWidth() const { return LargeArrayMinWidth; }
+ unsigned getLargeArrayAlign() const { return LargeArrayAlign; }
+
/// getIntMaxTWidth - Return the size of intmax_t and uintmax_t for this
/// target, in bits.
unsigned getIntMaxTWidth() const {
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 43bf21313f..6e7bb0773c 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -414,6 +414,15 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) {
T = getPointerType(RT->getPointeeType());
}
if (!T->isIncompleteType() && !T->isFunctionType()) {
+ unsigned MinWidth = Target.getLargeArrayMinWidth();
+ unsigned ArrayAlign = Target.getLargeArrayAlign();
+ if (isa<VariableArrayType>(T) && MinWidth != 0)
+ Align = std::max(Align, ArrayAlign);
+ if (ConstantArrayType *CT = dyn_cast<ConstantArrayType>(T)) {
+ unsigned Size = getTypeSize(CT);
+ if (MinWidth != 0 && MinWidth <= Size)
+ Align = std::max(Align, ArrayAlign);
+ }
// Incomplete or function types default to 1.
while (isa<VariableArrayType>(T) || isa<IncompleteArrayType>(T))
T = cast<ArrayType>(T)->getElementType();
diff --git a/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp
index 6692e641f2..98249c029b 100644
--- a/lib/Basic/TargetInfo.cpp
+++ b/lib/Basic/TargetInfo.cpp
@@ -34,6 +34,8 @@ TargetInfo::TargetInfo(const std::string &T) : Triple(T) {
DoubleAlign = 64;
LongDoubleWidth = 64;
LongDoubleAlign = 64;
+ LargeArrayMinWidth = 0;
+ LargeArrayAlign = 0;
SizeType = UnsignedLong;
PtrDiffType = SignedLong;
IntMaxType = SignedLongLong;
diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp
index 255c71d9b7..82c6507190 100644
--- a/lib/Basic/Targets.cpp
+++ b/lib/Basic/Targets.cpp
@@ -1278,6 +1278,8 @@ public:
LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
LongDoubleWidth = 128;
LongDoubleAlign = 128;
+ LargeArrayMinWidth = 128;
+ LargeArrayAlign = 128;
IntMaxType = SignedLong;
UIntMaxType = UnsignedLong;
Int64Type = SignedLong;
diff --git a/test/CodeGen/const-arithmetic.c b/test/CodeGen/const-arithmetic.c
index e12b4f6d92..92c02f0b3d 100644
--- a/test/CodeGen/const-arithmetic.c
+++ b/test/CodeGen/const-arithmetic.c
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s
-// CHECK: @g1 = global [2 x i8*] [i8* getelementptr (i8* getelementptr inbounds ([0 x %struct.anon]* @g0, i32 0, i32 0, i32 0), i64 -2), i8* getelementptr (i8* getelementptr inbounds ([0 x %struct.anon]* @g0, i32 0, i32 0, i32 0), i64 -46)], align 8 ; <[2 x i8*]*> [#uses=0]
-// CHECK: @g2 = global [2 x i8*] [i8* getelementptr (i8* getelementptr inbounds ([0 x %struct.anon]* @g0, i32 0, i32 0, i32 0), i64 -2), i8* getelementptr (i8* getelementptr inbounds ([0 x %struct.anon]* @g0, i32 0, i32 0, i32 0), i64 -46)], align 8 ; <[2 x i8*]*> [#uses=0]
+// CHECK: @g1 = global [2 x i8*] [i8* getelementptr (i8* getelementptr inbounds ([0 x %struct.anon]* @g0, i32 0, i32 0, i32 0), i64 -2), i8* getelementptr (i8* getelementptr inbounds ([0 x %struct.anon]* @g0, i32 0, i32 0, i32 0), i64 -46)], align 16 ; <[2 x i8*]*> [#uses=0]
+// CHECK: @g2 = global [2 x i8*] [i8* getelementptr (i8* getelementptr inbounds ([0 x %struct.anon]* @g0, i32 0, i32 0, i32 0), i64 -2), i8* getelementptr (i8* getelementptr inbounds ([0 x %struct.anon]* @g0, i32 0, i32 0, i32 0), i64 -46)], align 16 ; <[2 x i8*]*> [#uses=0]
extern struct { unsigned char a, b; } g0[];
void *g1[] = {g0 + -1, g0 + -23 };
diff --git a/test/CodeGenCXX/static-init.cpp b/test/CodeGenCXX/static-init.cpp
index 9ad87df8f0..09b398a530 100644
--- a/test/CodeGenCXX/static-init.cpp
+++ b/test/CodeGenCXX/static-init.cpp
@@ -2,7 +2,7 @@
// CHECK: @_ZZ1hvE1i = internal global i32 0, align 4
-// CHECK: @_ZZN5test16getvarEiE3var = internal constant [4 x i32] [i32 1, i32 0, i32 2, i32 4], align 4
+// CHECK: @_ZZN5test16getvarEiE3var = internal constant [4 x i32] [i32 1, i32 0, i32 2, i32 4], align 16
// CHECK: @_ZZ2h2vE1i = linkonce_odr global i32 0
// CHECK: @_ZGVZ2h2vE1i = linkonce_odr global i64 0
diff --git a/test/Sema/align-x86-64.c b/test/Sema/align-x86-64.c
new file mode 100644
index 0000000000..6dcf5714b0
--- /dev/null
+++ b/test/Sema/align-x86-64.c
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -verify %s
+
+// PR5599
+
+void frob(void *);
+
+void foo(void) {
+ float x[4];
+ char y[__alignof__(x) == 16 ? 1 : -1];
+ frob(y);
+}