]> granicus.if.org Git - clang/commitdiff
Introduce a single AST node SizeOfAlignOfExpr for all sizeof and alignof expressions...
authorSebastian Redl <sebastian.redl@getdesigned.at>
Tue, 11 Nov 2008 17:56:53 +0000 (17:56 +0000)
committerSebastian Redl <sebastian.redl@getdesigned.at>
Tue, 11 Nov 2008 17:56:53 +0000 (17:56 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59057 91177308-0d34-0410-b5e6-96231b3b80d8

23 files changed:
Driver/PrintParserCallbacks.cpp
Driver/RewriteObjC.cpp
include/clang/AST/Expr.h
include/clang/AST/StmtNodes.def
include/clang/AST/StmtVisitor.h
include/clang/Analysis/PathSensitive/GRExprEngine.h
include/clang/Parse/Action.h
lib/AST/CFG.cpp
lib/AST/Expr.cpp
lib/AST/ExprConstant.cpp
lib/AST/StmtDumper.cpp
lib/AST/StmtPrinter.cpp
lib/AST/StmtSerialization.cpp
lib/Analysis/GRExprEngine.cpp
lib/Analysis/LiveVariables.cpp
lib/Analysis/UninitializedValues.cpp
lib/CodeGen/CGExprComplex.cpp
lib/CodeGen/CGExprConstant.cpp
lib/CodeGen/CGExprScalar.cpp
lib/Parse/ParseExpr.cpp
lib/Sema/Sema.h
lib/Sema/SemaDecl.cpp
lib/Sema/SemaExpr.cpp

index adf3bed0d02aa30fa29d2fa386af78bbc1cca629..0048a6d459b1281211c569cbd6630a29fdcd8a2c 100644 (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;
     }
index 35d7cc8e1fa7c60ed753323c093b415946ce4434..9d78c42d0253bc569162c573c9761e40c15d3795 100644 (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
index 6023c6803d01237713a34a139d90aacae5d98200..efab1a14e140ebfe3556ead4c0808550b7dd7525 100644 (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);
 };
 
 //===----------------------------------------------------------------------===//
index 2b814a0e4b0f84a1a81158f4c8fccf9cd2242045..6a1c4248e4e48a2041b705dd927a388924591f77 100644 (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)
index fb1e4d120272fb4f562b7fe930978043e40a3287..22b467ea73ce2a8ba9c8e92f97e1b2da3ec01eb9 100644 (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
index 5339f6f3a26f7af989a79a0ed254383af0d697c9..45874bb6819e95e7088f7c6d2a240d5500506302 100644 (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,
index d1ab26f6937448e3f62c1141a005acbd27199f7e..1e036e755984238b7c14fa318e7055b08ef92068 100644 (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;
   }
   
index b75ec68e1584174c81f268cbe9950dc0cf85e101..95e188269e1496ef257e1d22c7ab9ffc368caa20 100644 (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);
 
index 86a2f2902e95668bbe462d44d38038f3f165cc01..fbb225613fd2c729b0a14c55f31da24ab757d149 100644 (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
index 12010646bced3fb5109b9b9fb6ebcc3c2de77cff..99fa8d5813dd54d96df4fb6b3447e22e99d86081 100644 (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;
index ecfdbf78d27f0242e20b4f1a4d294ff262c54e33..0b9e62d2c5681a1bc3b840bd4e8f4a53c29cfddb 100644 (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) {
index cc861cc6b4e484f08a49a077bd0f6fb01307c4fe..7529eec9847886f478225f98d80af52b22f08a26 100644 (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());
index 398288157691fb79f1c5374724a1868a919e8b01..f71b88b46f1d3279a920fd9a0bd9bcc7efd9e183 100644 (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 {
index 11ce8ea7ff98459fc398e828633777e555a66b1f..8e6d5ab5cc35057202b38b3308d1e766830444b8 100644 (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).
index 9b0f09e54e36c095b5a8476ad02a44f10ea7278c..07fda99166c4f43d4e82e743ade017778de650b8 100644 (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:
index a02e544506e1191eeeb155234ef1bca77c81e4b3..60489023b26e068ad718f9370cc0ba7e464edbd6 100644 (file)
@@ -171,9 +171,6 @@ bool TransferFuncs::VisitUnaryOperator(UnaryOperator* U) {
       break;
     }
     
-    case UnaryOperator::SizeOf:
-      return Initialized;
-      
     default:
       break;
   }
index 92226620269acb4615ddaae3aab221d09cf48f83..b4ca6c0f57fc2b5c788a332464033d38404ae1d1 100644 (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());
   }
index 89b34e611ba88a70c1a6e330e91886a485ae227c..1e224571f95258ca07072a0a815f030c39c9881c 100644 (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());
   }
index 465574187aa9d2479e170ac26ed3e3efa9385f56..82f0cc7e77732cdc52221eeec633526646a87d18 100644 (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));
index df55bf79fcaec5ca5f2e2254fc4d148c1a947727..467eef03b6f394589ea2c546c09d8c98bb8bafd9 100644 (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;
 }
 
index 7f72928064a1b73e61fa177052bc9188cb374457..7cd507a0aa30919d62fc2be837d9c25c288967bf 100644 (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.
index b595ad7f317ae70e1bddf3cca13a2d14feccb360..fc412a605edfe7df38880035ad0861740e8e7498 100644 (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;
     }
index a45d6717b797a0525ddcbef0eddfa2f156731739..92efa68cc434ad74da2a35153a05b764a13b833c 100644 (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);