diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 181ea9069117..fce228957479 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -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()) + Align = std::max(Align, AA->getAlignment()); + if (const ValueDecl *VD = dyn_cast(D)) { QualType T = VD->getType(); // Incomplete or function types default to 1. - if (T->isIncompleteType() || T->isFunctionType()) - return 1; - - while (isa(T) || isa(T)) - T = cast(T)->getElementType(); - - return getTypeAlign(T) / Target.getCharWidth(); + if (!T->isIncompleteType() && !T->isFunctionType()) { + while (isa(T) || isa(T)) + T = cast(T)->getElementType(); + + 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 diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index b613492f1453..f27419c0a240 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -994,31 +994,18 @@ bool Expr::isIntegerConstantExprInternal(llvm::APSInt &Result, ASTContext &Ctx, } case SizeOfAlignOfExprClass: { const SizeOfAlignOfExpr *Exp = cast(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: { diff --git a/clang/test/Sema/attr-aligned.c b/clang/test/Sema/attr-aligned.c index 390e6d9df45c..aa72566c89fa 100644 --- a/clang/test/Sema/attr-aligned.c +++ b/clang/test/Sema/attr-aligned.c @@ -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]; +