implement codegen support for sizeof(void), fixing PR2080.

llvm-svn: 47429
This commit is contained in:
Chris Lattner 2008-02-21 05:45:29 +00:00
parent 4da4f85090
commit 3b418d8446
3 changed files with 45 additions and 15 deletions

View File

@ -580,7 +580,8 @@ bool Expr::isConstantExpr(ASTContext &Ctx, SourceLocation *Loc) const {
case SizeOfAlignOfTypeExprClass: {
const SizeOfAlignOfTypeExpr *Exp = cast<SizeOfAlignOfTypeExpr>(this);
// alignof always evaluates to a constant.
if (Exp->isSizeOf() && !Exp->getArgumentType()->isConstantSizeType()) {
if (Exp->isSizeOf() && !Exp->getArgumentType()->isVoidType() &&
!Exp->getArgumentType()->isConstantSizeType()) {
if (Loc) *Loc = Exp->getOperatorLoc();
return false;
}
@ -721,17 +722,23 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx,
return true; // FIXME: this is wrong.
case UnaryOperator::SizeOf:
case UnaryOperator::AlignOf:
// Return the result in the right width.
Result.zextOrTrunc(
static_cast<uint32_t>(Ctx.getTypeSize(getType(),
Exp->getOperatorLoc())));
// sizeof(void) and __alignof__(void) = 1 as a gcc extension.
if (Exp->getSubExpr()->getType()->isVoidType()) {
Result = 1;
break;
}
// sizeof(vla) is not a constantexpr: C99 6.5.3.4p2.
if (!Exp->getSubExpr()->getType()->isConstantSizeType()) {
if (Loc) *Loc = Exp->getOperatorLoc();
return false;
}
// Return the result in the right width.
Result.zextOrTrunc(
static_cast<uint32_t>(Ctx.getTypeSize(getType(),
Exp->getOperatorLoc())));
// Get information about the size or align.
if (Exp->getSubExpr()->getType()->isFunctionType()) {
// GCC extension: sizeof(function) = 1.
@ -771,16 +778,23 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx,
}
case SizeOfAlignOfTypeExprClass: {
const SizeOfAlignOfTypeExpr *Exp = cast<SizeOfAlignOfTypeExpr>(this);
// alignof always evaluates to a constant.
// Return the result in the right width.
Result.zextOrTrunc(
static_cast<uint32_t>(Ctx.getTypeSize(getType(), Exp->getOperatorLoc())));
// sizeof(void) and __alignof__(void) = 1 as a gcc extension.
if (Exp->getArgumentType()->isVoidType()) {
Result = 1;
break;
}
// alignof always evaluates to a constant, sizeof does if arg is not VLA.
if (Exp->isSizeOf() && !Exp->getArgumentType()->isConstantSizeType()) {
if (Loc) *Loc = Exp->getOperatorLoc();
return false;
}
// Return the result in the right width.
Result.zextOrTrunc(
static_cast<uint32_t>(Ctx.getTypeSize(getType(), Exp->getOperatorLoc())));
// Get information about the size or align.
if (Exp->getArgumentType()->isFunctionType()) {
// GCC extension: sizeof(function) = 1.

View File

@ -607,6 +607,15 @@ Value *ScalarExprEmitter::VisitUnaryLNot(const UnaryOperator *E) {
/// an integer (RetType).
Value *ScalarExprEmitter::EmitSizeAlignOf(QualType TypeToSize,
QualType RetType,bool isSizeOf){
assert(RetType->isIntegerType() && "Result type must be an integer!");
uint32_t ResultWidth =
static_cast<uint32_t>(CGF.getContext().getTypeSize(RetType,
SourceLocation()));
// sizeof(void) and __alignof__(void) = 1 as a gcc extension.
if (TypeToSize->isVoidType())
return llvm::ConstantInt::get(llvm::APInt(ResultWidth, 1));
/// FIXME: This doesn't handle VLAs yet!
std::pair<uint64_t, unsigned> Info =
CGF.getContext().getTypeInfo(TypeToSize, SourceLocation());
@ -614,10 +623,6 @@ Value *ScalarExprEmitter::EmitSizeAlignOf(QualType TypeToSize,
uint64_t Val = isSizeOf ? Info.first : Info.second;
Val /= 8; // Return size in bytes, not bits.
assert(RetType->isIntegerType() && "Result type must be an integer!");
uint32_t ResultWidth = static_cast<uint32_t>(
CGF.getContext().getTypeSize(RetType, SourceLocation()));
return llvm::ConstantInt::get(llvm::APInt(ResultWidth, Val));
}

View File

@ -23,3 +23,14 @@ int test3() {
bp -= (short)1;
}
// PR2080 - sizeof void
int t1 = sizeof(void);
int t2 = __alignof__(void);
void test4() {
t1 = sizeof(void);
t2 = __alignof__(void);
t1 = sizeof(test4());
t2 = __alignof__(test4());
}