diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 5f97df904cc3..b88149ad41e9 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -334,24 +334,30 @@ unsigned ASTContext::getDeclAlignInBytes(const Decl *D) { /// does not work on incomplete types. std::pair 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(T)->getElementType()); + break; + case Type::ConstantArray: { const ConstantArrayType *CAT = cast(T); @@ -377,7 +383,11 @@ ASTContext::getTypeInfo(const Type *T) { switch (cast(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(T)->getDecl(); + if (const AlignedAttr *Aligned = Typedef->getAttr()) { + Align = Aligned->getAlignment(); + Width = getTypeSize(Typedef->getUnderlyingType().getTypePtr()); + } else + return getTypeInfo(Typedef->getUnderlyingType().getTypePtr()); break; } + + case Type::TypeOfExpr: + return getTypeInfo(cast(T)->getUnderlyingExpr()->getType() + .getTypePtr()); + + case Type::TypeOf: + return getTypeInfo(cast(T)->getUnderlyingType().getTypePtr()); + + case Type::QualifiedName: + return getTypeInfo(cast(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); diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index fce59133c105..5d92e99a06dd 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -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(Ty)) - return GetAlignOfType(QualType(EXTQT->getBaseType(), 0)); - - // alignof VLA/incomplete array. - if (const ArrayType *VAT = dyn_cast(Ty)) - return GetAlignOfType(VAT->getElementType()); - - // sizeof (objc class)? - if (isa(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) { diff --git a/clang/test/Sema/attr-aligned.c b/clang/test/Sema/attr-aligned.c index c7d65ee9ae8a..6e641cb371f9 100644 --- a/clang/test/Sema/attr-aligned.c +++ b/clang/test/Sema/attr-aligned.c @@ -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]; + +// +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 };