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:
parent
5499e89d06
commit
6f28289aca
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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).
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -171,9 +171,6 @@ bool TransferFuncs::VisitUnaryOperator(UnaryOperator* U) {
|
|||
break;
|
||||
}
|
||||
|
||||
case UnaryOperator::SizeOf:
|
||||
return Initialized;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue