diff options
author | Chris Lattner <sabre@nondot.org> | 2009-01-24 21:09:06 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2009-01-24 21:09:06 +0000 |
commit | e9feb475d72ba50dc29cec62a8c47cae721065eb (patch) | |
tree | d9a6dfe4707151c4cbae019bec3971bcc9c1c187 /lib/AST/ExprConstant.cpp | |
parent | caae7b099a0324b7c15dc89a9b70969d5d7ce996 (diff) |
Improve handling of alignof. alignof(VLA) now works properly for example.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@62932 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/ExprConstant.cpp')
-rw-r--r-- | lib/AST/ExprConstant.cpp | 63 |
1 files changed, 50 insertions, 13 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 16c6e89c32..6d1d150c1c 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -508,6 +508,8 @@ public: private: bool HandleCast(CastExpr* E); + uint64_t GetAlignOfExpr(const Expr *E); + uint64_t GetAlignOfType(QualType T); }; } // end anonymous namespace @@ -842,6 +844,41 @@ bool IntExprEvaluator::VisitConditionalOperator(const ConditionalOperator *E) { return Visit(Cond ? E->getTrueExpr() : E->getFalseExpr()); } +uint64_t 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 ASQualType *ASQT = dyn_cast<ASQualType>(Ty)) + return GetAlignOfType(QualType(ASQT->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.getTypeAlign(Ty) / CharSize; +} + +uint64_t IntExprEvaluator::GetAlignOfExpr(const Expr *E) { + + return GetAlignOfType(E->getType()); +} + + /// VisitSizeAlignOfExpr - Evaluate a sizeof or alignof with a result as the /// expression's type. bool IntExprEvaluator::VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E) { @@ -850,6 +887,15 @@ bool IntExprEvaluator::VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E) { Result.zextOrTrunc(getIntTypeSizeInBits(DstTy)); Result.setIsUnsigned(DstTy->isUnsignedIntegerType()); + // Handle alignof separately. + if (!E->isSizeOf()) { + if (E->isArgumentType()) + Result = GetAlignOfType(E->getArgumentType()); + else + Result = GetAlignOfExpr(E->getArgumentExpr()); + return true; + } + QualType SrcTy = E->getTypeOfArgument(); // sizeof(void) and __alignof__(void) = 1 as a gcc extension. @@ -859,31 +905,22 @@ bool IntExprEvaluator::VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E) { } // sizeof(vla) is not a constantexpr: C99 6.5.3.4p2. - // FIXME: But alignof(vla) is! - if (!SrcTy->isConstantSizeType()) { - // FIXME: Should we attempt to evaluate this? + if (!SrcTy->isConstantSizeType()) return false; - } // sizeof (objc class) ? if (SrcTy->isObjCInterfaceType()) return false; - bool isSizeOf = E->isSizeOf(); - // GCC extension: sizeof(function) = 1. if (SrcTy->isFunctionType()) { - // FIXME: AlignOf shouldn't be unconditionally 4! - Result = isSizeOf ? 1 : 4; + Result = 1; return true; } - // Get information about the size or align. + // Get information about the size. unsigned CharSize = Info.Ctx.Target.getCharWidth(); - if (isSizeOf) - Result = Info.Ctx.getTypeSize(SrcTy) / CharSize; - else - Result = Info.Ctx.getTypeAlign(SrcTy) / CharSize; + Result = Info.Ctx.getTypeSize(SrcTy) / CharSize; return true; } |