Introduce a single AST node SizeOfAlignOfExpr for all sizeof and alignof expressions, both of values and types.

llvm-svn: 59057
This commit is contained in:
Sebastian Redl 2008-11-11 17:56:53 +00:00
parent 5499e89d06
commit 6f28289aca
23 changed files with 212 additions and 267 deletions

View File

@ -473,9 +473,8 @@ namespace {
return 0;
}
virtual ExprResult
ActOnSizeOfAlignOfTypeExpr(SourceLocation OpLoc, bool isSizeof,
SourceLocation LParenLoc, TypeTy *Ty,
SourceLocation RParenLoc) {
ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType,
void *TyOrEx, const SourceRange &ArgRange) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}

View File

@ -2254,9 +2254,10 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {
FT->getResultType(), SourceLocation());
// Build sizeof(returnType)
SizeOfAlignOfTypeExpr *sizeofExpr = new SizeOfAlignOfTypeExpr(true,
returnType, Context->getSizeType(),
SourceLocation(), SourceLocation());
SizeOfAlignOfExpr *sizeofExpr = new SizeOfAlignOfExpr(true, true,
returnType.getAsOpaquePtr(),
Context->getSizeType(),
SourceLocation(), SourceLocation());
// (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))
// FIXME: Value of 8 is base on ppc32/x86 ABI for the most common cases.
// For X86 it is more complicated and some kind of target specific routine

View File

@ -431,8 +431,8 @@ public:
};
/// UnaryOperator - This represents the unary-expression's (except sizeof of
/// types), the postinc/postdec operators from postfix-expression, and various
/// UnaryOperator - This represents the unary-expression's (except sizeof and
/// alignof), the postinc/postdec operators from postfix-expression, and various
/// extensions.
///
/// Notes on various nodes:
@ -454,7 +454,6 @@ public:
AddrOf, Deref, // [C99 6.5.3.2] Address and indirection operators.
Plus, Minus, // [C99 6.5.3.3] Unary arithmetic operators.
Not, LNot, // [C99 6.5.3.3] Unary arithmetic operators.
SizeOf, AlignOf, // [C99 6.5.3.4] Sizeof (expr, not type) operator.
Real, Imag, // "__real expr"/"__imag expr" Extension.
Extension, // __extension__ marker.
OffsetOf // __builtin_offsetof
@ -484,7 +483,6 @@ public:
bool isPostfix() const { return isPostfix(Opc); }
bool isIncrementOp() const {return Opc==PreInc || Opc==PostInc; }
bool isIncrementDecrementOp() const { return Opc>=PostInc && Opc<=PreDec; }
bool isSizeOfAlignOfOp() const { return Opc == SizeOf || Opc == AlignOf; }
bool isOffsetOfOp() const { return Opc == OffsetOf; }
static bool isArithmeticOp(Opcode Op) { return Op >= Plus && Op <= LNot; }
@ -515,23 +513,39 @@ public:
static UnaryOperator* CreateImpl(llvm::Deserializer& D, ASTContext& C);
};
/// SizeOfAlignOfTypeExpr - [C99 6.5.3.4] - This is only for sizeof/alignof of
/// *types*. sizeof(expr) is handled by UnaryOperator.
class SizeOfAlignOfTypeExpr : public Expr {
bool isSizeof; // true if sizeof, false if alignof.
QualType Ty;
/// SizeOfAlignOfExpr - [C99 6.5.3.4] - This is for sizeof/alignof, both of
/// types and expressions.
class SizeOfAlignOfExpr : public Expr {
bool isSizeof : 1; // true if sizeof, false if alignof.
bool isType : 1; // true if operand is a type, false if an expression
void *Argument;
SourceLocation OpLoc, RParenLoc;
public:
SizeOfAlignOfTypeExpr(bool issizeof, QualType argType, QualType resultType,
SourceLocation op, SourceLocation rp) :
Expr(SizeOfAlignOfTypeExprClass, resultType),
isSizeof(issizeof), Ty(argType), OpLoc(op), RParenLoc(rp) {}
SizeOfAlignOfExpr(bool issizeof, bool istype, void *argument,
QualType resultType, SourceLocation op,
SourceLocation rp) :
Expr(SizeOfAlignOfExprClass, resultType),
isSizeof(issizeof), isType(istype), Argument(argument),
OpLoc(op), RParenLoc(rp) {}
virtual void Destroy(ASTContext& C);
bool isSizeOf() const { return isSizeof; }
QualType getArgumentType() const { return Ty; }
bool isArgumentType() const { return isType; }
QualType getArgumentType() const {
assert(isArgumentType() && "calling getArgumentType() when arg is expr");
return QualType::getFromOpaquePtr(Argument);
}
Expr* getArgumentExpr() const {
assert(!isArgumentType() && "calling getArgumentExpr() when arg is type");
return (Expr *)Argument;
}
/// Gets the argument type, or the type of the argument expression, whichever
/// is appropriate.
QualType getTypeOfArgument() const {
return isArgumentType() ? getArgumentType() : getArgumentExpr()->getType();
}
SourceLocation getOperatorLoc() const { return OpLoc; }
virtual SourceRange getSourceRange() const {
@ -539,16 +553,16 @@ public:
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == SizeOfAlignOfTypeExprClass;
return T->getStmtClass() == SizeOfAlignOfExprClass;
}
static bool classof(const SizeOfAlignOfTypeExpr *) { return true; }
static bool classof(const SizeOfAlignOfExpr *) { return true; }
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
virtual void EmitImpl(llvm::Serializer& S) const;
static SizeOfAlignOfTypeExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C);
static SizeOfAlignOfExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C);
};
//===----------------------------------------------------------------------===//

View File

@ -67,7 +67,7 @@ STMT(37, StringLiteral , Expr)
STMT(38, CharacterLiteral , Expr)
STMT(39, ParenExpr , Expr)
STMT(40, UnaryOperator , Expr)
STMT(41, SizeOfAlignOfTypeExpr , Expr)
STMT(41, SizeOfAlignOfExpr , Expr)
STMT(42, ArraySubscriptExpr , Expr)
STMT(43, CallExpr , Expr)
STMT(44, MemberExpr , Expr)

View File

@ -91,8 +91,6 @@ public:
case UnaryOperator::Minus: DISPATCH(UnaryMinus, UnaryOperator);
case UnaryOperator::Not: DISPATCH(UnaryNot, UnaryOperator);
case UnaryOperator::LNot: DISPATCH(UnaryLNot, UnaryOperator);
case UnaryOperator::SizeOf: DISPATCH(UnarySizeOf, UnaryOperator);
case UnaryOperator::AlignOf: DISPATCH(UnaryAlignOf, UnaryOperator);
case UnaryOperator::Real: DISPATCH(UnaryReal, UnaryOperator);
case UnaryOperator::Imag: DISPATCH(UnaryImag, UnaryOperator);
case UnaryOperator::Extension: DISPATCH(UnaryExtension, UnaryOperator);
@ -158,7 +156,6 @@ public:
UNARYOP_FALLBACK(Plus) UNARYOP_FALLBACK(Minus)
UNARYOP_FALLBACK(Not) UNARYOP_FALLBACK(LNot)
UNARYOP_FALLBACK(SizeOf) UNARYOP_FALLBACK(AlignOf)
UNARYOP_FALLBACK(Real) UNARYOP_FALLBACK(Imag)
UNARYOP_FALLBACK(Extension) UNARYOP_FALLBACK(OffsetOf)
#undef UNARYOP_FALLBACK

View File

@ -552,9 +552,9 @@ protected:
/// VisitReturnStmt - Transfer function logic for return statements.
void VisitReturnStmt(ReturnStmt* R, NodeTy* Pred, NodeSet& Dst);
/// VisitSizeOfAlignOfTypeExpr - Transfer function for sizeof(type).
void VisitSizeOfAlignOfTypeExpr(SizeOfAlignOfTypeExpr* Ex, NodeTy* Pred,
NodeSet& Dst);
/// VisitSizeOfAlignOfExpr - Transfer function for sizeof.
void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr* Ex, NodeTy* Pred,
NodeSet& Dst);
/// VisitUnaryOperator - Transfer function logic for unary operators.
void VisitUnaryOperator(UnaryOperator* B, NodeTy* Pred, NodeSet& Dst,

View File

@ -520,9 +520,8 @@ public:
return 0;
}
virtual ExprResult
ActOnSizeOfAlignOfTypeExpr(SourceLocation OpLoc, bool isSizeof,
SourceLocation LParenLoc, TypeTy *Ty,
SourceLocation RParenLoc) {
ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType,
void *TyOrEx, const SourceRange &ArgRange) {
return 0;
}

View File

@ -404,31 +404,23 @@ CFGBlock* CFGBuilder::WalkAST(Stmt* Terminator, bool AlwaysAddStmt = false) {
case Stmt::StmtExprClass:
return WalkAST_VisitStmtExpr(cast<StmtExpr>(Terminator));
case Stmt::SizeOfAlignOfTypeExprClass: {
SizeOfAlignOfTypeExpr* E = cast<SizeOfAlignOfTypeExpr>(Terminator);
case Stmt::SizeOfAlignOfExprClass: {
SizeOfAlignOfExpr* E = cast<SizeOfAlignOfExpr>(Terminator);
// VLA types have expressions that must be evaluated.
for (VariableArrayType* VA = FindVA(E->getArgumentType().getTypePtr());
VA != 0; VA = FindVA(VA->getElementType().getTypePtr()))
addStmt(VA->getSizeExpr());
if (E->isArgumentType()) {
for (VariableArrayType* VA = FindVA(E->getArgumentType().getTypePtr());
VA != 0; VA = FindVA(VA->getElementType().getTypePtr()))
addStmt(VA->getSizeExpr());
}
// Expressions in sizeof/alignof are not evaluated and thus have no
// control flow.
else
Block->appendStmt(Terminator);
return Block;
}
case Stmt::UnaryOperatorClass: {
UnaryOperator* U = cast<UnaryOperator>(Terminator);
// sizeof(expressions). For such expressions,
// the subexpression is not really evaluated, so
// we don't care about control-flow within the sizeof.
if (U->getOpcode() == UnaryOperator::SizeOf) {
Block->appendStmt(Terminator);
return Block;
}
break;
}
case Stmt::BinaryOperatorClass: {
BinaryOperator* B = cast<BinaryOperator>(Terminator);

View File

@ -92,8 +92,6 @@ const char *UnaryOperator::getOpcodeStr(Opcode Op) {
case LNot: return "!";
case Real: return "__real";
case Imag: return "__imag";
case SizeOf: return "sizeof";
case AlignOf: return "alignof";
case Extension: return "__extension__";
case OffsetOf: return "__builtin_offsetof";
}
@ -608,8 +606,7 @@ bool Expr::isConstantExpr(ASTContext &Ctx, SourceLocation *Loc) const {
// Get the operand value. If this is sizeof/alignof, do not evalute the
// operand. This affects C99 6.6p3.
if (!Exp->isSizeOfAlignOfOp() &&
Exp->getOpcode() != UnaryOperator::OffsetOf &&
if (Exp->getOpcode() != UnaryOperator::OffsetOf &&
!Exp->getSubExpr()->isConstantExpr(Ctx, Loc))
return false;
@ -621,10 +618,7 @@ bool Expr::isConstantExpr(ASTContext &Ctx, SourceLocation *Loc) const {
return false;
case UnaryOperator::Extension:
return true; // FIXME: this is wrong.
case UnaryOperator::SizeOf:
case UnaryOperator::AlignOf:
case UnaryOperator::OffsetOf:
// sizeof(vla) is not a constantexpr: C99 6.5.3.4p2.
if (!Exp->getSubExpr()->getType()->isConstantSizeType()) {
if (Loc) *Loc = Exp->getOperatorLoc();
return false;
@ -637,13 +631,15 @@ bool Expr::isConstantExpr(ASTContext &Ctx, SourceLocation *Loc) const {
return true;
}
}
case SizeOfAlignOfTypeExprClass: {
const SizeOfAlignOfTypeExpr *Exp = cast<SizeOfAlignOfTypeExpr>(this);
case SizeOfAlignOfExprClass: {
const SizeOfAlignOfExpr *Exp = cast<SizeOfAlignOfExpr>(this);
// alignof always evaluates to a constant.
if (Exp->isSizeOf() && !Exp->getArgumentType()->isVoidType() &&
!Exp->getArgumentType()->isConstantSizeType()) {
if (Loc) *Loc = Exp->getOperatorLoc();
return false;
if (Exp->isSizeOf()) {
QualType ArgTy = Exp->getTypeOfArgument();
if (!ArgTy->isVoidType() && !ArgTy->isConstantSizeType()) {
if (Loc) *Loc = Exp->getOperatorLoc();
return false;
}
}
return true;
}
@ -784,10 +780,10 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx,
case UnaryOperatorClass: {
const UnaryOperator *Exp = cast<UnaryOperator>(this);
// Get the operand value. If this is sizeof/alignof, do not evalute the
// Get the operand value. If this is offsetof, do not evalute the
// operand. This affects C99 6.6p3.
if (!Exp->isSizeOfAlignOfOp() && !Exp->isOffsetOfOp() &&
!Exp->getSubExpr()->isIntegerConstantExpr(Result, Ctx, Loc,isEvaluated))
if (!Exp->isOffsetOfOp() && !Exp->getSubExpr()->
isIntegerConstantExpr(Result, Ctx, Loc, isEvaluated))
return false;
switch (Exp->getOpcode()) {
@ -798,35 +794,6 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx,
return false;
case UnaryOperator::Extension:
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())));
// 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;
}
// Get information about the size or align.
if (Exp->getSubExpr()->getType()->isFunctionType()) {
// GCC extension: sizeof(function) = 1.
Result = Exp->getOpcode() == UnaryOperator::AlignOf ? 4 : 1;
} else {
unsigned CharSize = Ctx.Target.getCharWidth();
if (Exp->getOpcode() == UnaryOperator::AlignOf)
Result = Ctx.getTypeAlign(Exp->getSubExpr()->getType()) / CharSize;
else
Result = Ctx.getTypeSize(Exp->getSubExpr()->getType()) / CharSize;
}
break;
case UnaryOperator::LNot: {
bool Val = Result == 0;
Result.zextOrTrunc(static_cast<uint32_t>(Ctx.getTypeSize(getType())));
@ -847,34 +814,35 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx,
}
break;
}
case SizeOfAlignOfTypeExprClass: {
const SizeOfAlignOfTypeExpr *Exp = cast<SizeOfAlignOfTypeExpr>(this);
case SizeOfAlignOfExprClass: {
const SizeOfAlignOfExpr *Exp = cast<SizeOfAlignOfExpr>(this);
// Return the result in the right width.
Result.zextOrTrunc(static_cast<uint32_t>(Ctx.getTypeSize(getType())));
QualType ArgTy = Exp->getTypeOfArgument();
// sizeof(void) and __alignof__(void) = 1 as a gcc extension.
if (Exp->getArgumentType()->isVoidType()) {
if (ArgTy->isVoidType()) {
Result = 1;
break;
}
// alignof always evaluates to a constant, sizeof does if arg is not VLA.
if (Exp->isSizeOf() && !Exp->getArgumentType()->isConstantSizeType()) {
if (Exp->isSizeOf() && !ArgTy->isConstantSizeType()) {
if (Loc) *Loc = Exp->getOperatorLoc();
return false;
}
// Get information about the size or align.
if (Exp->getArgumentType()->isFunctionType()) {
if (ArgTy->isFunctionType()) {
// GCC extension: sizeof(function) = 1.
Result = Exp->isSizeOf() ? 1 : 4;
} else {
unsigned CharSize = Ctx.Target.getCharWidth();
if (Exp->isSizeOf())
Result = Ctx.getTypeSize(Exp->getArgumentType()) / CharSize;
Result = Ctx.getTypeSize(ArgTy) / CharSize;
else
Result = Ctx.getTypeAlign(Exp->getArgumentType()) / CharSize;
Result = Ctx.getTypeAlign(ArgTy) / CharSize;
}
break;
}
@ -1280,9 +1248,18 @@ int64_t UnaryOperator::evaluateOffsetOf(ASTContext& C) const
return ::evaluateOffsetOf(C, cast<Expr>(Val)) / CharSize;
}
void SizeOfAlignOfTypeExpr::Destroy(ASTContext& C) {
// Override default behavior of traversing children. We do not want
// to delete the type.
void SizeOfAlignOfExpr::Destroy(ASTContext& C) {
// Override default behavior of traversing children. If this has a type
// operand and the type is a variable-length array, the child iteration
// will iterate over the size expression. However, this expression belongs
// to the type, not to this, so we don't want to delete it.
// We still want to delete this expression.
// FIXME: Same as in Stmt::Destroy - will be eventually in ASTContext's
// pool allocator.
if (isArgumentType())
delete this;
else
Expr::Destroy(C);
}
//===----------------------------------------------------------------------===//
@ -1350,17 +1327,23 @@ Stmt::child_iterator ParenExpr::child_end() { return &Val+1; }
Stmt::child_iterator UnaryOperator::child_begin() { return &Val; }
Stmt::child_iterator UnaryOperator::child_end() { return &Val+1; }
// SizeOfAlignOfTypeExpr
Stmt::child_iterator SizeOfAlignOfTypeExpr::child_begin() {
// If the type is a VLA type (and not a typedef), the size expression of the
// VLA needs to be treated as an executable expression.
if (VariableArrayType* T = dyn_cast<VariableArrayType>(Ty.getTypePtr()))
return child_iterator(T);
else
return child_iterator();
// SizeOfAlignOfExpr
Stmt::child_iterator SizeOfAlignOfExpr::child_begin() {
// If this is of a type and the type is a VLA type (and not a typedef), the
// size expression of the VLA needs to be treated as an executable expression.
// Why isn't this weirdness documented better in StmtIterator?
if (isArgumentType()) {
if (VariableArrayType* T = dyn_cast<VariableArrayType>(
getArgumentType().getTypePtr()))
return child_iterator(T);
return child_iterator();
}
return child_iterator((Stmt**)&Argument);
}
Stmt::child_iterator SizeOfAlignOfTypeExpr::child_end() {
return child_iterator();
Stmt::child_iterator SizeOfAlignOfExpr::child_end() {
if (isArgumentType())
return child_iterator();
return child_iterator((Stmt**)&Argument + 1);
}
// ArraySubscriptExpr

View File

@ -222,14 +222,10 @@ public:
bool VisitCastExpr(CastExpr* E) {
return HandleCast(E->getLocStart(), E->getSubExpr(), E->getType());
}
bool VisitSizeOfAlignOfTypeExpr(const SizeOfAlignOfTypeExpr *E) {
return EvaluateSizeAlignOf(E->isSizeOf(), E->getArgumentType(),
E->getType());
}
bool VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E);
private:
bool HandleCast(SourceLocation CastLoc, Expr *SubExpr, QualType DestType);
bool EvaluateSizeAlignOf(bool isSizeOf, QualType SrcTy, QualType DstTy);
};
} // end anonymous namespace
@ -426,14 +422,16 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
return true;
}
/// EvaluateSizeAlignOf - Evaluate sizeof(SrcTy) or alignof(SrcTy) with a result
/// as a DstTy type.
bool IntExprEvaluator::EvaluateSizeAlignOf(bool isSizeOf, QualType SrcTy,
QualType DstTy) {
/// VisitSizeAlignOfExpr - Evaluate a sizeof or alignof with a result as the
/// expression's type.
bool IntExprEvaluator::VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E) {
QualType DstTy = E->getType();
// Return the result in the right width.
Result.zextOrTrunc(getIntTypeSizeInBits(DstTy));
Result.setIsUnsigned(DstTy->isUnsignedIntegerType());
QualType SrcTy = E->getTypeOfArgument();
// sizeof(void) and __alignof__(void) = 1 as a gcc extension.
if (SrcTy->isVoidType())
Result = 1;
@ -443,6 +441,8 @@ bool IntExprEvaluator::EvaluateSizeAlignOf(bool isSizeOf, QualType SrcTy,
// FIXME: Should we attempt to evaluate this?
return false;
}
bool isSizeOf = E->isSizeOf();
// GCC extension: sizeof(function) = 1.
if (SrcTy->isFunctionType()) {
@ -470,10 +470,6 @@ bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
return true;
}
if (E->isSizeOfAlignOfOp())
return EvaluateSizeAlignOf(E->getOpcode() == UnaryOperator::SizeOf,
E->getSubExpr()->getType(), E->getType());
// Get the operand value into 'Result'.
if (!Visit(E->getSubExpr()))
return false;

View File

@ -119,7 +119,7 @@ namespace {
void VisitFloatingLiteral(FloatingLiteral *Node);
void VisitStringLiteral(StringLiteral *Str);
void VisitUnaryOperator(UnaryOperator *Node);
void VisitSizeOfAlignOfTypeExpr(SizeOfAlignOfTypeExpr *Node);
void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node);
void VisitMemberExpr(MemberExpr *Node);
void VisitExtVectorElementExpr(ExtVectorElementExpr *Node);
void VisitBinaryOperator(BinaryOperator *Node);
@ -363,10 +363,11 @@ void StmtDumper::VisitUnaryOperator(UnaryOperator *Node) {
fprintf(F, " %s '%s'", Node->isPostfix() ? "postfix" : "prefix",
UnaryOperator::getOpcodeStr(Node->getOpcode()));
}
void StmtDumper::VisitSizeOfAlignOfTypeExpr(SizeOfAlignOfTypeExpr *Node) {
void StmtDumper::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node) {
DumpExpr(Node);
fprintf(F, " %s ", Node->isSizeOf() ? "sizeof" : "alignof");
DumpType(Node->getArgumentType());
if (Node->isArgumentType())
DumpType(Node->getArgumentType());
}
void StmtDumper::VisitMemberExpr(MemberExpr *Node) {

View File

@ -620,11 +620,9 @@ void StmtPrinter::VisitUnaryOperator(UnaryOperator *Node) {
if (!Node->isPostfix()) {
OS << UnaryOperator::getOpcodeStr(Node->getOpcode());
// Print a space if this is an "identifier operator" like sizeof or __real.
// Print a space if this is an "identifier operator" like __real.
switch (Node->getOpcode()) {
default: break;
case UnaryOperator::SizeOf:
case UnaryOperator::AlignOf:
case UnaryOperator::Real:
case UnaryOperator::Imag:
case UnaryOperator::Extension:
@ -663,9 +661,14 @@ void StmtPrinter::VisitUnaryOffsetOf(UnaryOperator *Node) {
OS << ")";
}
void StmtPrinter::VisitSizeOfAlignOfTypeExpr(SizeOfAlignOfTypeExpr *Node) {
OS << (Node->isSizeOf() ? "sizeof(" : "__alignof(");
OS << Node->getArgumentType().getAsString() << ")";
void StmtPrinter::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node) {
OS << (Node->isSizeOf() ? "sizeof" : "__alignof");
if (Node->isArgumentType())
OS << "(" << Node->getArgumentType().getAsString() << ")";
else {
OS << " ";
PrintExpr(Node->getArgumentExpr());
}
}
void StmtPrinter::VisitArraySubscriptExpr(ArraySubscriptExpr *Node) {
PrintExpr(Node->getLHS());

View File

@ -136,8 +136,8 @@ Stmt* Stmt::Create(Deserializer& D, ASTContext& C) {
case ReturnStmtClass:
return ReturnStmt::CreateImpl(D, C);
case SizeOfAlignOfTypeExprClass:
return SizeOfAlignOfTypeExpr::CreateImpl(D, C);
case SizeOfAlignOfExprClass:
return SizeOfAlignOfExpr::CreateImpl(D, C);
case StmtExprClass:
return StmtExpr::CreateImpl(D, C);
@ -795,22 +795,33 @@ ReturnStmt* ReturnStmt::CreateImpl(Deserializer& D, ASTContext& C) {
return new ReturnStmt(RetLoc,RetExpr);
}
void SizeOfAlignOfTypeExpr::EmitImpl(Serializer& S) const {
void SizeOfAlignOfExpr::EmitImpl(Serializer& S) const {
S.EmitBool(isSizeof);
S.Emit(Ty);
S.EmitBool(isType);
if (isType)
S.Emit(getArgumentType());
else
S.EmitOwnedPtr(getArgumentExpr());
S.Emit(getType());
S.Emit(OpLoc);
S.Emit(RParenLoc);
}
SizeOfAlignOfTypeExpr* SizeOfAlignOfTypeExpr::CreateImpl(Deserializer& D, ASTContext& C) {
SizeOfAlignOfExpr*
SizeOfAlignOfExpr::CreateImpl(Deserializer& D, ASTContext& C) {
bool isSizeof = D.ReadBool();
QualType Ty = QualType::ReadVal(D);
bool isType = D.ReadBool();
void *Argument;
if (isType)
Argument = QualType::ReadVal(D).getAsOpaquePtr();
else
Argument = D.ReadOwnedPtr<Expr>(C);
QualType Res = QualType::ReadVal(D);
SourceLocation OpLoc = SourceLocation::ReadVal(D);
SourceLocation RParenLoc = SourceLocation::ReadVal(D);
return new SizeOfAlignOfTypeExpr(isSizeof,Ty,Res,OpLoc,RParenLoc);
return new SizeOfAlignOfExpr(isSizeof, isType, Argument, Res,
OpLoc, RParenLoc);
}
void StmtExpr::EmitImpl(Serializer& S) const {

View File

@ -380,8 +380,8 @@ void GRExprEngine::Visit(Stmt* S, NodeTy* Pred, NodeSet& Dst) {
VisitReturnStmt(cast<ReturnStmt>(S), Pred, Dst);
break;
case Stmt::SizeOfAlignOfTypeExprClass:
VisitSizeOfAlignOfTypeExpr(cast<SizeOfAlignOfTypeExpr>(S), Pred, Dst);
case Stmt::SizeOfAlignOfExprClass:
VisitSizeOfAlignOfExpr(cast<SizeOfAlignOfExpr>(S), Pred, Dst);
break;
case Stmt::StmtExprClass: {
@ -1749,11 +1749,11 @@ void GRExprEngine::VisitInitListExpr(InitListExpr* E, NodeTy* Pred,
assert(0 && "unprocessed InitListExpr type");
}
/// VisitSizeOfAlignOfTypeExpr - Transfer function for sizeof(type).
void GRExprEngine::VisitSizeOfAlignOfTypeExpr(SizeOfAlignOfTypeExpr* Ex,
NodeTy* Pred,
NodeSet& Dst) {
QualType T = Ex->getArgumentType();
/// VisitSizeOfAlignOfExpr - Transfer function for sizeof(type).
void GRExprEngine::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr* Ex,
NodeTy* Pred,
NodeSet& Dst) {
QualType T = Ex->getTypeOfArgument();
uint64_t amt;
if (Ex->isSizeOf()) {
@ -1972,40 +1972,6 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred,
return;
}
case UnaryOperator::AlignOf: {
QualType T = U->getSubExpr()->getType();
// FIXME: Add support for VLAs.
if (!T.getTypePtr()->isConstantSizeType())
return;
uint64_t size = getContext().getTypeAlign(T) / 8;
const GRState* St = GetState(Pred);
St = BindExpr(St, U, NonLoc::MakeVal(getBasicVals(), size, U->getType()));
MakeNode(Dst, U, Pred, St);
return;
}
case UnaryOperator::SizeOf: {
QualType T = U->getSubExpr()->getType();
// FIXME: Add support for VLAs.
if (!T.getTypePtr()->isConstantSizeType())
return;
uint64_t size = getContext().getTypeSize(T) / 8;
const GRState* St = GetState(Pred);
St = BindExpr(St, U, NonLoc::MakeVal(getBasicVals(), size, U->getType()));
MakeNode(Dst, U, Pred, St);
return;
}
}
// Handle ++ and -- (both pre- and post-increment).

View File

@ -195,7 +195,6 @@ void TransferFuncs::VisitUnaryOperator(UnaryOperator* U) {
Expr *E = U->getSubExpr();
switch (U->getOpcode()) {
case UnaryOperator::SizeOf: return;
case UnaryOperator::PostInc:
case UnaryOperator::PostDec:
case UnaryOperator::PreInc:

View File

@ -171,9 +171,6 @@ bool TransferFuncs::VisitUnaryOperator(UnaryOperator* U) {
break;
}
case UnaryOperator::SizeOf:
return Initialized;
default:
break;
}

View File

@ -117,7 +117,7 @@ public:
}
ComplexPairTy VisitUnaryMinus (const UnaryOperator *E);
ComplexPairTy VisitUnaryNot (const UnaryOperator *E);
// LNot,SizeOf,AlignOf,Real,Imag never return complex.
// LNot,Real,Imag never return complex.
ComplexPairTy VisitUnaryExtension(const UnaryOperator *E) {
return Visit(E->getSubExpr());
}

View File

@ -384,8 +384,8 @@ public:
return 0;
}
llvm::Constant *VisitSizeOfAlignOfTypeExpr(const SizeOfAlignOfTypeExpr *E) {
return EmitSizeAlignOf(E->getArgumentType(), E->getType(), E->isSizeOf());
llvm::Constant *VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E) {
return EmitSizeAlignOf(E->getTypeOfArgument(), E->getType(), E->isSizeOf());
}
llvm::Constant *VisitAddrLabelExpr(const AddrLabelExpr *E) {
@ -426,12 +426,6 @@ public:
return llvm::ConstantExpr::getZExt(SubExpr, ConvertType(E->getType()));
}
llvm::Constant *VisitUnarySizeOf(const UnaryOperator *E) {
return EmitSizeAlignOf(E->getSubExpr()->getType(), E->getType(), true);
}
llvm::Constant *VisitUnaryAlignOf(const UnaryOperator *E) {
return EmitSizeAlignOf(E->getSubExpr()->getType(), E->getType(), false);
}
llvm::Constant *VisitUnaryAddrOf(const UnaryOperator *E) {
return EmitLValue(E->getSubExpr());
}

View File

@ -117,9 +117,7 @@ public:
CGF.getContext().typesAreCompatible(
E->getArgType1(), E->getArgType2()));
}
Value *VisitSizeOfAlignOfTypeExpr(const SizeOfAlignOfTypeExpr *E) {
return EmitSizeAlignOf(E->getArgumentType(), E->getType(), E->isSizeOf());
}
Value *VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E);
Value *VisitAddrLabelExpr(const AddrLabelExpr *E) {
llvm::Value *V =
llvm::ConstantInt::get(llvm::Type::Int32Ty,
@ -235,14 +233,6 @@ public:
Value *VisitUnaryMinus (const UnaryOperator *E);
Value *VisitUnaryNot (const UnaryOperator *E);
Value *VisitUnaryLNot (const UnaryOperator *E);
Value *VisitUnarySizeOf (const UnaryOperator *E) {
return EmitSizeAlignOf(E->getSubExpr()->getType(), E->getType(), true);
}
Value *VisitUnaryAlignOf (const UnaryOperator *E) {
return EmitSizeAlignOf(E->getSubExpr()->getType(), E->getType(), false);
}
Value *EmitSizeAlignOf(QualType TypeToSize, QualType RetType,
bool isSizeOf);
Value *VisitUnaryReal (const UnaryOperator *E);
Value *VisitUnaryImag (const UnaryOperator *E);
Value *VisitUnaryExtension(const UnaryOperator *E) {
@ -653,14 +643,16 @@ Value *ScalarExprEmitter::VisitUnaryLNot(const UnaryOperator *E) {
return Builder.CreateZExt(BoolVal, CGF.LLVMIntTy, "lnot.ext");
}
/// EmitSizeAlignOf - Return the size or alignment of the 'TypeToSize' type as
/// an integer (RetType).
Value *ScalarExprEmitter::EmitSizeAlignOf(QualType TypeToSize,
QualType RetType,bool isSizeOf){
/// VisitSizeOfAlignOfExpr - Return the size or alignment of the type of
/// argument of the sizeof expression as an integer.
Value *
ScalarExprEmitter::VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E) {
QualType RetType = E->getType();
assert(RetType->isIntegerType() && "Result type must be an integer!");
uint32_t ResultWidth =
static_cast<uint32_t>(CGF.getContext().getTypeSize(RetType));
QualType TypeToSize = E->getTypeOfArgument();
// sizeof(void) and __alignof__(void) = 1 as a gcc extension. Also
// for function types.
// FIXME: what is alignof a function type in gcc?
@ -670,7 +662,7 @@ Value *ScalarExprEmitter::EmitSizeAlignOf(QualType TypeToSize,
/// FIXME: This doesn't handle VLAs yet!
std::pair<uint64_t, unsigned> Info = CGF.getContext().getTypeInfo(TypeToSize);
uint64_t Val = isSizeOf ? Info.first : Info.second;
uint64_t Val = E->isSizeOf() ? Info.first : Info.second;
Val /= 8; // Return size in bytes, not bits.
return llvm::ConstantInt::get(llvm::APInt(ResultWidth, Val));

View File

@ -764,9 +764,10 @@ Parser::ExprResult Parser::ParseSizeofAlignofExpression() {
// If ParseParenExpression parsed a '(typename)' sequence only, the this is
// sizeof/alignof a type. Otherwise, it is sizeof/alignof an expression.
if (ExprType == CastExpr)
return Actions.ActOnSizeOfAlignOfTypeExpr(OpTok.getLocation(),
OpTok.is(tok::kw_sizeof),
LParenLoc, CastTy, RParenLoc);
return Actions.ActOnSizeOfAlignOfExpr(OpTok.getLocation(),
OpTok.is(tok::kw_sizeof),
/*isType=*/true, CastTy,
SourceRange(LParenLoc, RParenLoc));
// If this is a parenthesized expression, it is the start of a
// unary-expression, but doesn't include any postfix pieces. Parse these
@ -776,8 +777,10 @@ Parser::ExprResult Parser::ParseSizeofAlignofExpression() {
// If we get here, the operand to the sizeof/alignof was an expresion.
if (!Operand.isInvalid)
Operand = Actions.ActOnUnaryOp(OpTok.getLocation(), OpTok.getKind(),
Operand.Val);
Operand = Actions.ActOnSizeOfAlignOfExpr(OpTok.getLocation(),
OpTok.is(tok::kw_sizeof),
/*isType=*/false, Operand.Val,
SourceRange());
return Operand;
}

View File

@ -624,9 +624,11 @@ public:
virtual ExprResult ActOnUnaryOp(SourceLocation OpLoc, tok::TokenKind Op,
ExprTy *Input);
virtual ExprResult
ActOnSizeOfAlignOfTypeExpr(SourceLocation OpLoc, bool isSizeof,
SourceLocation LParenLoc, TypeTy *Ty,
SourceLocation RParenLoc);
ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType,
void *TyOrEx, const SourceRange &ArgRange);
bool CheckSizeOfAlignOfOperand(QualType type, SourceLocation OpLoc,
const SourceRange &R, bool isSizeof);
virtual ExprResult ActOnPostfixUnaryOp(SourceLocation OpLoc,
tok::TokenKind Kind, ExprTy *Input);
@ -1208,8 +1210,6 @@ public:
QualType CheckIncrementDecrementOperand(Expr *op, SourceLocation OpLoc);
QualType CheckAddressOfOperand(Expr *op, SourceLocation OpLoc);
QualType CheckIndirectionOperand(Expr *op, SourceLocation OpLoc);
QualType CheckSizeOfAlignOfOperand(QualType type, SourceLocation OpLoc,
const SourceRange &R, bool isSizeof);
QualType CheckRealImagOperand(Expr *&Op, SourceLocation OpLoc);
/// type checking primary expressions.

View File

@ -1470,11 +1470,7 @@ bool Sema::CheckArithmeticConstantExpression(const Expr* Init) {
default:
InitializerElementNotConstant(Init);
return true;
case UnaryOperator::SizeOf:
case UnaryOperator::AlignOf:
case UnaryOperator::OffsetOf:
// sizeof(E) is a constantexpr if and only if E is not evaluted.
// See C99 6.5.3.4p2 and 6.6p3.
if (Exp->getSubExpr()->getType()->isConstantSizeType())
return false;
InitializerElementNotConstant(Init);
@ -1487,14 +1483,14 @@ bool Sema::CheckArithmeticConstantExpression(const Expr* Init) {
return CheckArithmeticConstantExpression(Exp->getSubExpr());
}
}
case Expr::SizeOfAlignOfTypeExprClass: {
const SizeOfAlignOfTypeExpr *Exp = cast<SizeOfAlignOfTypeExpr>(Init);
case Expr::SizeOfAlignOfExprClass: {
const SizeOfAlignOfExpr *Exp = cast<SizeOfAlignOfExpr>(Init);
// Special check for void types, which are allowed as an extension
if (Exp->getArgumentType()->isVoidType())
if (Exp->getTypeOfArgument()->isVoidType())
return false;
// alignof always evaluates to a constant.
// FIXME: is sizeof(int[3.0]) a constant expression?
if (Exp->isSizeOf() && !Exp->getArgumentType()->isConstantSizeType()) {
if (Exp->isSizeOf() && !Exp->getTypeOfArgument()->isConstantSizeType()) {
InitializerElementNotConstant(Init);
return true;
}

View File

@ -654,10 +654,10 @@ Action::ExprResult Sema::ActOnParenExpr(SourceLocation L, SourceLocation R,
/// The UsualUnaryConversions() function is *not* called by this routine.
/// See C99 6.3.2.1p[2-4] for more details.
QualType Sema::CheckSizeOfAlignOfOperand(QualType exprType,
SourceLocation OpLoc,
const SourceRange &ExprRange,
bool isSizeof) {
bool Sema::CheckSizeOfAlignOfOperand(QualType exprType,
SourceLocation OpLoc,
const SourceRange &ExprRange,
bool isSizeof) {
// C99 6.5.3.4p1:
if (isa<FunctionType>(exprType) && isSizeof)
// alignof(function) is allowed.
@ -669,28 +669,40 @@ QualType Sema::CheckSizeOfAlignOfOperand(QualType exprType,
Diag(OpLoc, isSizeof ? diag::err_sizeof_incomplete_type :
diag::err_alignof_incomplete_type,
exprType.getAsString(), ExprRange);
return QualType(); // error
return true; // error
}
// C99 6.5.3.4p4: the type (an unsigned integer type) is size_t.
return Context.getSizeType();
return false;
}
Action::ExprResult Sema::
ActOnSizeOfAlignOfTypeExpr(SourceLocation OpLoc, bool isSizeof,
SourceLocation LPLoc, TypeTy *Ty,
SourceLocation RPLoc) {
/// ActOnSizeOfAlignOfExpr - Handle @c sizeof(type) and @c sizeof @c expr and
/// the same for @c alignof and @c __alignof
/// Note that the ArgRange is invalid if isType is false.
Action::ExprResult
Sema::ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType,
void *TyOrEx, const SourceRange &ArgRange) {
// If error parsing type, ignore.
if (Ty == 0) return true;
// Verify that this is a valid expression.
QualType ArgTy = QualType::getFromOpaquePtr(Ty);
QualType resultType =
CheckSizeOfAlignOfOperand(ArgTy, OpLoc, SourceRange(LPLoc, RPLoc),isSizeof);
if (TyOrEx == 0) return true;
if (resultType.isNull())
QualType ArgTy;
SourceRange Range;
if (isType) {
ArgTy = QualType::getFromOpaquePtr(TyOrEx);
Range = ArgRange;
} else {
// Get the end location.
Expr *ArgEx = (Expr *)TyOrEx;
Range = ArgEx->getSourceRange();
ArgTy = ArgEx->getType();
}
// Verify that the operand is valid.
if (CheckSizeOfAlignOfOperand(ArgTy, OpLoc, Range, isSizeof))
return true;
return new SizeOfAlignOfTypeExpr(isSizeof, ArgTy, resultType, OpLoc, RPLoc);
// C99 6.5.3.4p4: the type (an unsigned integer type) is size_t.
return new SizeOfAlignOfExpr(isSizeof, isType, TyOrEx, Context.getSizeType(),
OpLoc, Range.getEnd());
}
QualType Sema::CheckRealImagOperand(Expr *&V, SourceLocation Loc) {
@ -2635,8 +2647,6 @@ static inline UnaryOperator::Opcode ConvertTokenKindToUnaryOpcode(
case tok::minus: Opc = UnaryOperator::Minus; break;
case tok::tilde: Opc = UnaryOperator::Not; break;
case tok::exclaim: Opc = UnaryOperator::LNot; break;
case tok::kw_sizeof: Opc = UnaryOperator::SizeOf; break;
case tok::kw___alignof: Opc = UnaryOperator::AlignOf; break;
case tok::kw___real: Opc = UnaryOperator::Real; break;
case tok::kw___imag: Opc = UnaryOperator::Imag; break;
case tok::kw___extension__: Opc = UnaryOperator::Extension; break;
@ -2902,14 +2912,6 @@ Action::ExprResult Sema::ActOnUnaryOp(SourceLocation OpLoc, tok::TokenKind Op,
// LNot always has type int. C99 6.5.3.3p5.
resultType = Context.IntTy;
break;
case UnaryOperator::SizeOf:
resultType = CheckSizeOfAlignOfOperand(Input->getType(), OpLoc,
Input->getSourceRange(), true);
break;
case UnaryOperator::AlignOf:
resultType = CheckSizeOfAlignOfOperand(Input->getType(), OpLoc,
Input->getSourceRange(), false);
break;
case UnaryOperator::Real:
case UnaryOperator::Imag:
resultType = CheckRealImagOperand(Input, OpLoc);