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/Sema/Sema.h b/lib/Sema/Sema.h
index 7f72928..7cd507a 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -624,9 +624,11 @@
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 @@
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.
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index b595ad7..fc412a6 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -1470,11 +1470,7 @@
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 @@
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;
}
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index a45d671..92efa68 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -654,10 +654,10 @@
/// 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 @@
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 @@
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 @@
// 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);