Properly compute the alignment of typedefs that make use of the

"aligned" attribute. Previously, we were skipping over these
attributes when we jumped directly to the canonical type. Now,
ASTContext::getTypeInfo walks through typedefs and other
"non-canonical" types manually, looking for "aligned" attributes on
typedefs.

As part of this change, I moved the GNU-specific logic (such as
determining the alignment of void or of a function pointer) out of the
expression evaluator and into ASTContext::getTypeInfo.

llvm-svn: 70497
This commit is contained in:
Douglas Gregor 2009-04-30 17:32:17 +00:00
parent f45e07d766
commit ef462e6bb0
3 changed files with 59 additions and 32 deletions

View File

@ -334,24 +334,30 @@ unsigned ASTContext::getDeclAlignInBytes(const Decl *D) {
/// does not work on incomplete types.
std::pair<uint64_t, unsigned>
ASTContext::getTypeInfo(const Type *T) {
T = getCanonicalType(T);
uint64_t Width=0;
unsigned Align=8;
switch (T->getTypeClass()) {
#define TYPE(Class, Base)
#define ABSTRACT_TYPE(Class, Base)
#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
#define NON_CANONICAL_TYPE(Class, Base)
#define DEPENDENT_TYPE(Class, Base) case Type::Class:
#include "clang/AST/TypeNodes.def"
assert(false && "Should not see non-canonical or dependent types");
assert(false && "Should not see dependent types");
break;
case Type::FunctionNoProto:
case Type::FunctionProto:
// GCC extension: alignof(function) = 32 bits
Width = 0;
Align = 32;
break;
case Type::IncompleteArray:
assert(0 && "Incomplete types have no size!");
case Type::VariableArray:
assert(0 && "VLAs not implemented yet!");
Width = 0;
Align = getTypeAlign(cast<ArrayType>(T)->getElementType());
break;
case Type::ConstantArray: {
const ConstantArrayType *CAT = cast<ConstantArrayType>(T);
@ -377,7 +383,11 @@ ASTContext::getTypeInfo(const Type *T) {
switch (cast<BuiltinType>(T)->getKind()) {
default: assert(0 && "Unknown builtin type!");
case BuiltinType::Void:
assert(0 && "Incomplete types have no size!");
// GCC extension: alignof(void) = 8 bits.
Width = 0;
Align = 8;
break;
case BuiltinType::Bool:
Width = Target.getBoolWidth();
Align = Target.getBoolAlign();
@ -517,10 +527,34 @@ ASTContext::getTypeInfo(const Type *T) {
break;
}
case Type::TemplateSpecialization:
assert(false && "Dependent types have no size");
case Type::Typedef: {
const TypedefDecl *Typedef = cast<TypedefType>(T)->getDecl();
if (const AlignedAttr *Aligned = Typedef->getAttr<AlignedAttr>()) {
Align = Aligned->getAlignment();
Width = getTypeSize(Typedef->getUnderlyingType().getTypePtr());
} else
return getTypeInfo(Typedef->getUnderlyingType().getTypePtr());
break;
}
case Type::TypeOfExpr:
return getTypeInfo(cast<TypeOfExprType>(T)->getUnderlyingExpr()->getType()
.getTypePtr());
case Type::TypeOf:
return getTypeInfo(cast<TypeOfType>(T)->getUnderlyingType().getTypePtr());
case Type::QualifiedName:
return getTypeInfo(cast<QualifiedNameType>(T)->getNamedType().getTypePtr());
case Type::TemplateSpecialization:
assert(getCanonicalType(T) != T &&
"Cannot request the size of a dependent type");
// FIXME: this is likely to be wrong once we support template
// aliases, since a template alias could refer to a typedef that
// has an __aligned__ attribute on it.
return getTypeInfo(getCanonicalType(T));
}
assert(Align && (Align & (Align-1)) == 0 && "Alignment must be power of 2");
return std::make_pair(Width, Align);

View File

@ -1021,32 +1021,11 @@ bool IntExprEvaluator::VisitConditionalOperator(const ConditionalOperator *E) {
}
unsigned IntExprEvaluator::GetAlignOfType(QualType T) {
const Type *Ty = Info.Ctx.getCanonicalType(T).getTypePtr();
// __alignof__(void) = 1 as a gcc extension.
if (Ty->isVoidType())
return 1;
// GCC extension: alignof(function) = 4.
// FIXME: AlignOf shouldn't be unconditionally 4! It should listen to the
// attribute(align) directive.
if (Ty->isFunctionType())
return 4;
if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(Ty))
return GetAlignOfType(QualType(EXTQT->getBaseType(), 0));
// alignof VLA/incomplete array.
if (const ArrayType *VAT = dyn_cast<ArrayType>(Ty))
return GetAlignOfType(VAT->getElementType());
// sizeof (objc class)?
if (isa<ObjCInterfaceType>(Ty))
return 1; // FIXME: This probably isn't right.
// Get information about the alignment.
unsigned CharSize = Info.Ctx.Target.getCharWidth();
return Info.Ctx.getPreferredTypeAlign(Ty) / CharSize;
// FIXME: Why do we ask for the preferred alignment?
return Info.Ctx.getPreferredTypeAlign(T.getTypePtr()) / CharSize;
}
unsigned IntExprEvaluator::GetAlignOfExpr(const Expr *E) {

View File

@ -5,3 +5,17 @@ int x __attribute__((aligned(3))); // expected-error {{requested alignment is no
// PR3254
short g0[3] __attribute__((aligned));
short g0_chk[__alignof__(g0) == 16 ? 1 : -1];
// <rdar://problem/6840045>
typedef char ueber_aligned_char __attribute__((aligned(8)));
struct struct_with_ueber_char {
ueber_aligned_char c;
};
char c = 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__(c) == 1? : -1] = { 0 };
char a3[sizeof(c) == 1? : -1] = { 0 };