forked from OSchip/llvm-project
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:
parent
f45e07d766
commit
ef462e6bb0
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 };
|
||||
|
|
Loading…
Reference in New Issue