Improvements to ASTContext::getDeclAlignInBytes; fixes the testcase in

PR3254 and part of PR3433.

The isICE changes are necessary to keep the computed results 
consistent with Evaluate.

llvm-svn: 65258
This commit is contained in:
Eli Friedman 2009-02-22 02:56:25 +00:00
parent 10cbe66f17
commit 19a546c15b
3 changed files with 30 additions and 32 deletions

View File

@ -264,21 +264,23 @@ const llvm::fltSemantics &ASTContext::getFloatTypeSemantics(QualType T) const {
/// specified decl. Note that bitfields do not have a valid alignment, so
/// this method will assert on them.
unsigned ASTContext::getDeclAlignInBytes(const Decl *D) {
// FIXME: If attribute(align) is specified on the decl, round up to it.
unsigned Align = Target.getCharWidth();
if (const AlignedAttr* AA = D->getAttr<AlignedAttr>())
Align = std::max(Align, AA->getAlignment());
if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
QualType T = VD->getType();
// Incomplete or function types default to 1.
if (T->isIncompleteType() || T->isFunctionType())
return 1;
if (!T->isIncompleteType() && !T->isFunctionType()) {
while (isa<VariableArrayType>(T) || isa<IncompleteArrayType>(T))
T = cast<ArrayType>(T)->getElementType();
while (isa<VariableArrayType>(T) || isa<IncompleteArrayType>(T))
T = cast<ArrayType>(T)->getElementType();
return getTypeAlign(T) / Target.getCharWidth();
Align = std::max(Align, getPreferredTypeAlign(T.getTypePtr()));
}
}
return 1;
return Align / Target.getCharWidth();
}
/// getTypeSize - Return the size of the specified type, in bits. This method

View File

@ -994,31 +994,18 @@ bool Expr::isIntegerConstantExprInternal(llvm::APSInt &Result, ASTContext &Ctx,
}
case SizeOfAlignOfExprClass: {
const SizeOfAlignOfExpr *Exp = cast<SizeOfAlignOfExpr>(this);
QualType ArgTy = Exp->getTypeOfArgument();
// sizeof(void) and __alignof__(void) = 1 as a gcc extension.
if (ArgTy->isVoidType()) {
Result = Ctx.MakeIntValue(1, getType());
break;
}
// alignof always evaluates to a constant, sizeof does if arg is not VLA.
if (Exp->isSizeOf() && !ArgTy->isConstantSizeType()) {
// alignof is always an ICE; sizeof is an ICE if and only if
// the operand isn't a VLA
if (Exp->isSizeOf() && ArgTy->isVariableArrayType()) {
if (Loc) *Loc = Exp->getOperatorLoc();
return false;
}
// Get information about the size or align.
if (ArgTy->isFunctionType()) {
// GCC extension: sizeof(function) = 1.
Result = Ctx.MakeIntValue(Exp->isSizeOf() ? 1 : 4, getType());
} else {
unsigned CharSize = Ctx.Target.getCharWidth();
if (Exp->isSizeOf())
Result = Ctx.MakeIntValue(Ctx.getTypeSize(ArgTy)/CharSize, getType());
else
Result = Ctx.MakeIntValue(Ctx.getTypeAlign(ArgTy)/CharSize, getType());
}
// Use the Evaluate logic to calculate the value, since the
// calculation is non-trivial.
Result = EvaluateAsInt(Ctx);
break;
}
case BinaryOperatorClass: {

View File

@ -1,3 +1,12 @@
// RUN: clang -fsyntax-only -verify %s
// RUN: clang -triple i386-apple-darwin9 -fsyntax-only -verify %s
int x __attribute__((aligned(3))); // expected-error {{requested alignment is not a power of 2}}
// PR3254
short g0[3] __attribute__((aligned));
short g0_chk[__alignof__(g0) == 16 ? 1 : -1];
// PR3433
double g1;
short chk1[__alignof__(g1) == 8 ? 1 : -1];