Fix alignof computation of large arrays on x86_64.

We were exposing the extra alignment given to large arrays. The new behavior
matches gcc, which is a good thing since this is a gcc extension.

Thanks to Joerg Sonnenberger for noticing it.

While at it, centralize the method description in the .h file.

llvm-svn: 187999
This commit is contained in:
Rafael Espindola 2013-08-08 19:53:46 +00:00
parent 6beca0e1cf
commit 71eccb39b8
5 changed files with 24 additions and 22 deletions

View File

@ -1622,9 +1622,11 @@ public:
/// \pre \p D must not be a bitfield type, as bitfields do not have a valid
/// alignment.
///
/// If \p RefAsPointee, references are treated like their underlying type
/// (for alignof), else they're treated like pointers (for CodeGen).
CharUnits getDeclAlign(const Decl *D, bool RefAsPointee = false) const;
/// If \p ForAlignof, references are treated like their underlying type
/// and large arrays don't get any special treatment. If not \p ForAlignof
/// it computes the value expected by CodeGen: references are treated like
/// pointers and large arrays get extra alignment.
CharUnits getDeclAlign(const Decl *D, bool ForAlignof = false) const;
/// \brief Get or compute information about the layout of the specified
/// record (struct/union/class) \p D, which indicates its size and field

View File

@ -1239,12 +1239,7 @@ const llvm::fltSemantics &ASTContext::getFloatTypeSemantics(QualType T) const {
}
}
/// getDeclAlign - Return a conservative estimate of the alignment of the
/// specified decl. Note that bitfields do not have a valid alignment, so
/// this method will assert on them.
/// If @p RefAsPointee, references are treated like their underlying type
/// (for alignof), else they're treated like pointers (for CodeGen).
CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) const {
CharUnits ASTContext::getDeclAlign(const Decl *D, bool ForAlignof) const {
unsigned Align = Target->getCharWidth();
bool UseAlignAttrOnly = false;
@ -1277,7 +1272,7 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) const {
} else if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
QualType T = VD->getType();
if (const ReferenceType* RT = T->getAs<ReferenceType>()) {
if (RefAsPointee)
if (ForAlignof)
T = RT->getPointeeType();
else
T = getPointerType(RT->getPointeeType());
@ -1285,9 +1280,9 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) const {
if (!T->isIncompleteType() && !T->isFunctionType()) {
// Adjust alignments of declarations with array type by the
// large-array alignment on the target.
unsigned MinWidth = Target->getLargeArrayMinWidth();
if (const ArrayType *arrayType = getAsArrayType(T)) {
if (MinWidth) {
unsigned MinWidth = Target->getLargeArrayMinWidth();
if (!ForAlignof && MinWidth) {
if (isa<VariableArrayType>(arrayType))
Align = std::max(Align, Target->getLargeArrayAlign());
else if (isa<ConstantArrayType>(arrayType) &&

View File

@ -0,0 +1,11 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck %s
// PR5599
void test1_f(void *);
void test1_g(void) {
float x[4];
test1_f(x);
}
// CHECK: @test1_g
// CHECK: alloca [4 x float], align 16

View File

@ -1,16 +1,6 @@
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -verify %s
// expected-no-diagnostics
// PR5599
void frob(void *);
void foo(void) {
float x[4];
char y[__alignof__(x) == 16 ? 1 : -1];
frob(y);
}
// PR5637
typedef __attribute__((aligned(16))) struct {

View File

@ -58,3 +58,7 @@ struct S5 {
int x;
};
const int test8 = __alignof__(S5::x);
long long int test14[2];
static_assert(alignof(test14) == 8, "foo"); // expected-warning {{'alignof' applied to an expression is a GNU extension}}