Introduce a single AST node SizeOfAlignOfExpr for all sizeof and alignof expressions, both of values and types.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59057 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 86a2f29..fbb2256 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -92,8 +92,6 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
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 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