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);