forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			1689 lines
		
	
	
		
			56 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			1689 lines
		
	
	
		
			56 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===--- ExprConstant.cpp - Expression Constant Evaluator -----------------===//
 | |
| //
 | |
| //                     The LLVM Compiler Infrastructure
 | |
| //
 | |
| // This file is distributed under the University of Illinois Open Source
 | |
| // License. See LICENSE.TXT for details.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| //
 | |
| // This file implements the Expr constant evaluator.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #include "clang/AST/APValue.h"
 | |
| #include "clang/AST/ASTContext.h"
 | |
| #include "clang/AST/RecordLayout.h"
 | |
| #include "clang/AST/StmtVisitor.h"
 | |
| #include "clang/AST/ASTDiagnostic.h"
 | |
| #include "clang/Basic/TargetInfo.h"
 | |
| #include "llvm/Support/Compiler.h"
 | |
| using namespace clang;
 | |
| using llvm::APSInt;
 | |
| using llvm::APFloat;
 | |
| 
 | |
| /// EvalInfo - This is a private struct used by the evaluator to capture
 | |
| /// information about a subexpression as it is folded.  It retains information
 | |
| /// about the AST context, but also maintains information about the folded
 | |
| /// expression.
 | |
| ///
 | |
| /// If an expression could be evaluated, it is still possible it is not a C
 | |
| /// "integer constant expression" or constant expression.  If not, this struct
 | |
| /// captures information about how and why not.
 | |
| ///
 | |
| /// One bit of information passed *into* the request for constant folding
 | |
| /// indicates whether the subexpression is "evaluated" or not according to C
 | |
| /// rules.  For example, the RHS of (0 && foo()) is not evaluated.  We can
 | |
| /// evaluate the expression regardless of what the RHS is, but C only allows
 | |
| /// certain things in certain situations.
 | |
| struct EvalInfo {
 | |
|   ASTContext &Ctx;
 | |
|   
 | |
|   /// EvalResult - Contains information about the evaluation.
 | |
|   Expr::EvalResult &EvalResult;
 | |
| 
 | |
|   EvalInfo(ASTContext &ctx, Expr::EvalResult& evalresult) : Ctx(ctx), 
 | |
|            EvalResult(evalresult) {}
 | |
| };
 | |
| 
 | |
| 
 | |
| static bool EvaluateLValue(const Expr *E, APValue &Result, EvalInfo &Info);
 | |
| static bool EvaluatePointer(const Expr *E, APValue &Result, EvalInfo &Info);
 | |
| static bool EvaluateInteger(const Expr *E, APSInt  &Result, EvalInfo &Info);
 | |
| static bool EvaluateIntegerOrLValue(const Expr *E, APValue  &Result, EvalInfo &Info);
 | |
| static bool EvaluateFloat(const Expr *E, APFloat &Result, EvalInfo &Info);
 | |
| static bool EvaluateComplex(const Expr *E, APValue &Result, EvalInfo &Info);
 | |
| 
 | |
| //===----------------------------------------------------------------------===//
 | |
| // Misc utilities
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| static bool HandleConversionToBool(Expr* E, bool& Result, EvalInfo &Info) {
 | |
|   if (E->getType()->isIntegralType()) {
 | |
|     APSInt IntResult;
 | |
|     if (!EvaluateInteger(E, IntResult, Info))
 | |
|       return false;
 | |
|     Result = IntResult != 0;
 | |
|     return true;
 | |
|   } else if (E->getType()->isRealFloatingType()) {
 | |
|     APFloat FloatResult(0.0);
 | |
|     if (!EvaluateFloat(E, FloatResult, Info))
 | |
|       return false;
 | |
|     Result = !FloatResult.isZero();
 | |
|     return true;
 | |
|   } else if (E->getType()->hasPointerRepresentation()) {
 | |
|     APValue PointerResult;
 | |
|     if (!EvaluatePointer(E, PointerResult, Info))
 | |
|       return false;
 | |
|     // FIXME: Is this accurate for all kinds of bases?  If not, what would
 | |
|     // the check look like?
 | |
|     Result = PointerResult.getLValueBase() || PointerResult.getLValueOffset();
 | |
|     return true;
 | |
|   } else if (E->getType()->isAnyComplexType()) {
 | |
|     APValue ComplexResult;
 | |
|     if (!EvaluateComplex(E, ComplexResult, Info))
 | |
|       return false;
 | |
|     if (ComplexResult.isComplexFloat()) {
 | |
|       Result = !ComplexResult.getComplexFloatReal().isZero() ||
 | |
|                !ComplexResult.getComplexFloatImag().isZero();
 | |
|     } else {
 | |
|       Result = ComplexResult.getComplexIntReal().getBoolValue() ||
 | |
|                ComplexResult.getComplexIntImag().getBoolValue();
 | |
|     }
 | |
|     return true;
 | |
|   }
 | |
| 
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| static APSInt HandleFloatToIntCast(QualType DestType, QualType SrcType, 
 | |
|                                    APFloat &Value, ASTContext &Ctx) {
 | |
|   unsigned DestWidth = Ctx.getIntWidth(DestType);
 | |
|   // Determine whether we are converting to unsigned or signed.
 | |
|   bool DestSigned = DestType->isSignedIntegerType();
 | |
|   
 | |
|   // FIXME: Warning for overflow.
 | |
|   uint64_t Space[4];
 | |
|   bool ignored;
 | |
|   (void)Value.convertToInteger(Space, DestWidth, DestSigned,
 | |
|                                llvm::APFloat::rmTowardZero, &ignored);
 | |
|   return APSInt(llvm::APInt(DestWidth, 4, Space), !DestSigned);
 | |
| }
 | |
| 
 | |
| static APFloat HandleFloatToFloatCast(QualType DestType, QualType SrcType, 
 | |
|                                       APFloat &Value, ASTContext &Ctx) {
 | |
|   bool ignored;
 | |
|   APFloat Result = Value;
 | |
|   Result.convert(Ctx.getFloatTypeSemantics(DestType), 
 | |
|                  APFloat::rmNearestTiesToEven, &ignored);
 | |
|   return Result;
 | |
| }
 | |
| 
 | |
| static APSInt HandleIntToIntCast(QualType DestType, QualType SrcType, 
 | |
|                                  APSInt &Value, ASTContext &Ctx) {
 | |
|   unsigned DestWidth = Ctx.getIntWidth(DestType);
 | |
|   APSInt Result = Value;
 | |
|   // Figure out if this is a truncate, extend or noop cast.
 | |
|   // If the input is signed, do a sign extend, noop, or truncate.
 | |
|   Result.extOrTrunc(DestWidth);
 | |
|   Result.setIsUnsigned(DestType->isUnsignedIntegerType());
 | |
|   return Result;
 | |
| }
 | |
| 
 | |
| static APFloat HandleIntToFloatCast(QualType DestType, QualType SrcType, 
 | |
|                                     APSInt &Value, ASTContext &Ctx) {
 | |
| 
 | |
|   APFloat Result(Ctx.getFloatTypeSemantics(DestType), 1);
 | |
|   Result.convertFromAPInt(Value, Value.isSigned(),
 | |
|                           APFloat::rmNearestTiesToEven);
 | |
|   return Result;
 | |
| }
 | |
| 
 | |
| //===----------------------------------------------------------------------===//
 | |
| // LValue Evaluation
 | |
| //===----------------------------------------------------------------------===//
 | |
| namespace {
 | |
| class VISIBILITY_HIDDEN LValueExprEvaluator
 | |
|   : public StmtVisitor<LValueExprEvaluator, APValue> {
 | |
|   EvalInfo &Info;
 | |
| public:
 | |
|     
 | |
|   LValueExprEvaluator(EvalInfo &info) : Info(info) {}
 | |
| 
 | |
|   APValue VisitStmt(Stmt *S) {
 | |
|     return APValue();
 | |
|   }
 | |
| 
 | |
|   APValue VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
 | |
|   APValue VisitDeclRefExpr(DeclRefExpr *E);
 | |
|   APValue VisitBlockExpr(BlockExpr *E);
 | |
|   APValue VisitPredefinedExpr(PredefinedExpr *E) { return APValue(E, 0); }
 | |
|   APValue VisitCompoundLiteralExpr(CompoundLiteralExpr *E);
 | |
|   APValue VisitMemberExpr(MemberExpr *E);
 | |
|   APValue VisitStringLiteral(StringLiteral *E) { return APValue(E, 0); }
 | |
|   APValue VisitObjCEncodeExpr(ObjCEncodeExpr *E) { return APValue(E, 0); }
 | |
|   APValue VisitArraySubscriptExpr(ArraySubscriptExpr *E);
 | |
|   APValue VisitUnaryDeref(UnaryOperator *E);
 | |
|   APValue VisitUnaryExtension(const UnaryOperator *E)
 | |
|     { return Visit(E->getSubExpr()); }
 | |
|   APValue VisitChooseExpr(const ChooseExpr *E)
 | |
|     { return Visit(E->getChosenSubExpr(Info.Ctx)); }
 | |
|   // FIXME: Missing: __real__, __imag__
 | |
| };
 | |
| } // end anonymous namespace
 | |
| 
 | |
| static bool EvaluateLValue(const Expr* E, APValue& Result, EvalInfo &Info) {
 | |
|   Result = LValueExprEvaluator(Info).Visit(const_cast<Expr*>(E));
 | |
|   return Result.isLValue();
 | |
| }
 | |
| 
 | |
| APValue LValueExprEvaluator::VisitDeclRefExpr(DeclRefExpr *E)
 | |
| { 
 | |
|   if (!E->hasGlobalStorage())
 | |
|     return APValue();
 | |
|   
 | |
|   return APValue(E, 0); 
 | |
| }
 | |
| 
 | |
| APValue LValueExprEvaluator::VisitBlockExpr(BlockExpr *E)
 | |
| { 
 | |
|   if (E->hasBlockDeclRefExprs())
 | |
|     return APValue();
 | |
|     
 | |
|   return APValue(E, 0);
 | |
| }
 | |
| 
 | |
| APValue LValueExprEvaluator::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
 | |
|   if (E->isFileScope())
 | |
|     return APValue(E, 0);
 | |
|   return APValue();
 | |
| }
 | |
| 
 | |
| APValue LValueExprEvaluator::VisitMemberExpr(MemberExpr *E) {
 | |
|   APValue result;
 | |
|   QualType Ty;
 | |
|   if (E->isArrow()) {
 | |
|     if (!EvaluatePointer(E->getBase(), result, Info))
 | |
|       return APValue();
 | |
|     Ty = E->getBase()->getType()->getAsPointerType()->getPointeeType();
 | |
|   } else {
 | |
|     result = Visit(E->getBase());
 | |
|     if (result.isUninit())
 | |
|       return APValue();
 | |
|     Ty = E->getBase()->getType();
 | |
|   }
 | |
| 
 | |
|   RecordDecl *RD = Ty->getAsRecordType()->getDecl();
 | |
|   const ASTRecordLayout &RL = Info.Ctx.getASTRecordLayout(RD);
 | |
| 
 | |
|   FieldDecl *FD = dyn_cast<FieldDecl>(E->getMemberDecl());
 | |
|   if (!FD) // FIXME: deal with other kinds of member expressions
 | |
|     return APValue();
 | |
|     
 | |
|   // FIXME: This is linear time.
 | |
|   unsigned i = 0;
 | |
|   for (RecordDecl::field_iterator Field = RD->field_begin(Info.Ctx),
 | |
|                                FieldEnd = RD->field_end(Info.Ctx);
 | |
|        Field != FieldEnd; (void)++Field, ++i) {
 | |
|     if (*Field == FD)
 | |
|       break;
 | |
|   }
 | |
| 
 | |
|   result.setLValue(result.getLValueBase(),
 | |
|                    result.getLValueOffset() + RL.getFieldOffset(i) / 8);
 | |
| 
 | |
|   return result;
 | |
| }
 | |
| 
 | |
| APValue LValueExprEvaluator::VisitArraySubscriptExpr(ArraySubscriptExpr *E)
 | |
| {
 | |
|   APValue Result;
 | |
|   
 | |
|   if (!EvaluatePointer(E->getBase(), Result, Info))
 | |
|     return APValue();
 | |
|   
 | |
|   APSInt Index;
 | |
|   if (!EvaluateInteger(E->getIdx(), Index, Info))
 | |
|     return APValue();
 | |
| 
 | |
|   uint64_t ElementSize = Info.Ctx.getTypeSize(E->getType()) / 8;
 | |
| 
 | |
|   uint64_t Offset = Index.getSExtValue() * ElementSize;
 | |
|   Result.setLValue(Result.getLValueBase(), 
 | |
|                    Result.getLValueOffset() + Offset);
 | |
|   return Result;
 | |
| }
 | |
| 
 | |
| APValue LValueExprEvaluator::VisitUnaryDeref(UnaryOperator *E)
 | |
| {
 | |
|   APValue Result;
 | |
|   if (!EvaluatePointer(E->getSubExpr(), Result, Info))
 | |
|     return APValue();
 | |
|   return Result;
 | |
| }
 | |
| 
 | |
| //===----------------------------------------------------------------------===//
 | |
| // Pointer Evaluation
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| namespace {
 | |
| class VISIBILITY_HIDDEN PointerExprEvaluator
 | |
|   : public StmtVisitor<PointerExprEvaluator, APValue> {
 | |
|   EvalInfo &Info;
 | |
| public:
 | |
|     
 | |
|   PointerExprEvaluator(EvalInfo &info) : Info(info) {}
 | |
| 
 | |
|   APValue VisitStmt(Stmt *S) {
 | |
|     return APValue();
 | |
|   }
 | |
| 
 | |
|   APValue VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
 | |
| 
 | |
|   APValue VisitBinaryOperator(const BinaryOperator *E);
 | |
|   APValue VisitCastExpr(const CastExpr* E);
 | |
|   APValue VisitUnaryExtension(const UnaryOperator *E)
 | |
|       { return Visit(E->getSubExpr()); }
 | |
|   APValue VisitUnaryAddrOf(const UnaryOperator *E);
 | |
|   APValue VisitObjCStringLiteral(ObjCStringLiteral *E)
 | |
|       { return APValue(E, 0); }
 | |
|   APValue VisitAddrLabelExpr(AddrLabelExpr *E)
 | |
|       { return APValue(E, 0); }
 | |
|   APValue VisitCallExpr(CallExpr *E);
 | |
|   APValue VisitBlockExpr(BlockExpr *E) {
 | |
|     if (!E->hasBlockDeclRefExprs())
 | |
|       return APValue(E, 0);
 | |
|     return APValue();
 | |
|   }
 | |
|   APValue VisitImplicitValueInitExpr(ImplicitValueInitExpr *E)
 | |
|       { return APValue((Expr*)0, 0); }
 | |
|   APValue VisitConditionalOperator(ConditionalOperator *E);
 | |
|   APValue VisitChooseExpr(ChooseExpr *E)
 | |
|     { return Visit(E->getChosenSubExpr(Info.Ctx)); }
 | |
|   // FIXME: Missing: @protocol, @selector
 | |
| };
 | |
| } // end anonymous namespace
 | |
| 
 | |
| static bool EvaluatePointer(const Expr* E, APValue& Result, EvalInfo &Info) {
 | |
|   if (!E->getType()->hasPointerRepresentation())
 | |
|     return false;
 | |
|   Result = PointerExprEvaluator(Info).Visit(const_cast<Expr*>(E));
 | |
|   return Result.isLValue();
 | |
| }
 | |
| 
 | |
| APValue PointerExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
 | |
|   if (E->getOpcode() != BinaryOperator::Add &&
 | |
|       E->getOpcode() != BinaryOperator::Sub)
 | |
|     return APValue();
 | |
|   
 | |
|   const Expr *PExp = E->getLHS();
 | |
|   const Expr *IExp = E->getRHS();
 | |
|   if (IExp->getType()->isPointerType())
 | |
|     std::swap(PExp, IExp);
 | |
|   
 | |
|   APValue ResultLValue;
 | |
|   if (!EvaluatePointer(PExp, ResultLValue, Info))
 | |
|     return APValue();
 | |
|   
 | |
|   llvm::APSInt AdditionalOffset(32);
 | |
|   if (!EvaluateInteger(IExp, AdditionalOffset, Info))
 | |
|     return APValue();
 | |
| 
 | |
|   QualType PointeeType = PExp->getType()->getAsPointerType()->getPointeeType();
 | |
|   uint64_t SizeOfPointee;
 | |
|   
 | |
|   // Explicitly handle GNU void* and function pointer arithmetic extensions.
 | |
|   if (PointeeType->isVoidType() || PointeeType->isFunctionType())
 | |
|     SizeOfPointee = 1;
 | |
|   else
 | |
|     SizeOfPointee = Info.Ctx.getTypeSize(PointeeType) / 8;
 | |
| 
 | |
|   uint64_t Offset = ResultLValue.getLValueOffset();
 | |
| 
 | |
|   if (E->getOpcode() == BinaryOperator::Add)
 | |
|     Offset += AdditionalOffset.getLimitedValue() * SizeOfPointee;
 | |
|   else
 | |
|     Offset -= AdditionalOffset.getLimitedValue() * SizeOfPointee;
 | |
| 
 | |
|   return APValue(ResultLValue.getLValueBase(), Offset);
 | |
| }
 | |
| 
 | |
| APValue PointerExprEvaluator::VisitUnaryAddrOf(const UnaryOperator *E) {
 | |
|   APValue result;
 | |
|   if (EvaluateLValue(E->getSubExpr(), result, Info))
 | |
|     return result;
 | |
|   return APValue();
 | |
| }
 | |
|   
 | |
| 
 | |
| APValue PointerExprEvaluator::VisitCastExpr(const CastExpr* E) {
 | |
|   const Expr* SubExpr = E->getSubExpr();
 | |
| 
 | |
|    // Check for pointer->pointer cast
 | |
|   if (SubExpr->getType()->isPointerType()) {
 | |
|     APValue Result;
 | |
|     if (EvaluatePointer(SubExpr, Result, Info))
 | |
|       return Result;
 | |
|     return APValue();
 | |
|   }
 | |
|   
 | |
|   if (SubExpr->getType()->isIntegralType()) {
 | |
|     APValue Result;
 | |
|     if (!EvaluateIntegerOrLValue(SubExpr, Result, Info))
 | |
|       return APValue();
 | |
| 
 | |
|     if (Result.isInt()) {
 | |
|       Result.getInt().extOrTrunc((unsigned)Info.Ctx.getTypeSize(E->getType()));
 | |
|       return APValue(0, Result.getInt().getZExtValue());
 | |
|     }
 | |
|     
 | |
|     // Cast is of an lvalue, no need to change value.
 | |
|     return Result;
 | |
|   }
 | |
| 
 | |
|   if (SubExpr->getType()->isFunctionType() ||
 | |
|       SubExpr->getType()->isBlockPointerType() ||
 | |
|       SubExpr->getType()->isArrayType()) {
 | |
|     APValue Result;
 | |
|     if (EvaluateLValue(SubExpr, Result, Info))
 | |
|       return Result;
 | |
|     return APValue();
 | |
|   }
 | |
| 
 | |
|   return APValue();
 | |
| }  
 | |
| 
 | |
| APValue PointerExprEvaluator::VisitCallExpr(CallExpr *E) {
 | |
|   if (E->isBuiltinCall(Info.Ctx) == 
 | |
|         Builtin::BI__builtin___CFStringMakeConstantString)
 | |
|     return APValue(E, 0);
 | |
|   return APValue();
 | |
| }
 | |
| 
 | |
| APValue PointerExprEvaluator::VisitConditionalOperator(ConditionalOperator *E) {
 | |
|   bool BoolResult;
 | |
|   if (!HandleConversionToBool(E->getCond(), BoolResult, Info))
 | |
|     return APValue();
 | |
| 
 | |
|   Expr* EvalExpr = BoolResult ? E->getTrueExpr() : E->getFalseExpr();
 | |
| 
 | |
|   APValue Result;
 | |
|   if (EvaluatePointer(EvalExpr, Result, Info))
 | |
|     return Result;
 | |
|   return APValue();
 | |
| }
 | |
| 
 | |
| //===----------------------------------------------------------------------===//
 | |
| // Vector Evaluation
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| namespace {
 | |
|   class VISIBILITY_HIDDEN VectorExprEvaluator
 | |
|   : public StmtVisitor<VectorExprEvaluator, APValue> {
 | |
|     EvalInfo &Info;
 | |
|     APValue GetZeroVector(QualType VecType);
 | |
|   public:
 | |
|     
 | |
|     VectorExprEvaluator(EvalInfo &info) : Info(info) {}
 | |
|     
 | |
|     APValue VisitStmt(Stmt *S) {
 | |
|       return APValue();
 | |
|     }
 | |
|     
 | |
|     APValue VisitParenExpr(ParenExpr *E)
 | |
|         { return Visit(E->getSubExpr()); }
 | |
|     APValue VisitUnaryExtension(const UnaryOperator *E)
 | |
|       { return Visit(E->getSubExpr()); }
 | |
|     APValue VisitUnaryPlus(const UnaryOperator *E)
 | |
|       { return Visit(E->getSubExpr()); }
 | |
|     APValue VisitUnaryReal(const UnaryOperator *E)
 | |
|       { return Visit(E->getSubExpr()); }
 | |
|     APValue VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E)
 | |
|       { return GetZeroVector(E->getType()); }
 | |
|     APValue VisitCastExpr(const CastExpr* E);
 | |
|     APValue VisitCompoundLiteralExpr(const CompoundLiteralExpr *E);
 | |
|     APValue VisitInitListExpr(const InitListExpr *E);
 | |
|     APValue VisitConditionalOperator(const ConditionalOperator *E);
 | |
|     APValue VisitChooseExpr(const ChooseExpr *E)
 | |
|       { return Visit(E->getChosenSubExpr(Info.Ctx)); }
 | |
|     APValue VisitUnaryImag(const UnaryOperator *E);
 | |
|     // FIXME: Missing: unary -, unary ~, binary add/sub/mul/div,
 | |
|     //                 binary comparisons, binary and/or/xor,
 | |
|     //                 shufflevector, ExtVectorElementExpr
 | |
|     //        (Note that these require implementing conversions
 | |
|     //         between vector types.)
 | |
|   };
 | |
| } // end anonymous namespace
 | |
| 
 | |
| static bool EvaluateVector(const Expr* E, APValue& Result, EvalInfo &Info) {
 | |
|   if (!E->getType()->isVectorType())
 | |
|     return false;
 | |
|   Result = VectorExprEvaluator(Info).Visit(const_cast<Expr*>(E));
 | |
|   return !Result.isUninit();
 | |
| }
 | |
| 
 | |
| APValue VectorExprEvaluator::VisitCastExpr(const CastExpr* E) {
 | |
|   const Expr* SE = E->getSubExpr();
 | |
| 
 | |
|   // Check for vector->vector bitcast.
 | |
|   if (SE->getType()->isVectorType())
 | |
|     return this->Visit(const_cast<Expr*>(SE));
 | |
| 
 | |
|   return APValue();
 | |
| }
 | |
| 
 | |
| APValue 
 | |
| VectorExprEvaluator::VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) {
 | |
|   return this->Visit(const_cast<Expr*>(E->getInitializer()));
 | |
| }
 | |
| 
 | |
| APValue 
 | |
| VectorExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
 | |
|   const VectorType *VT = E->getType()->getAsVectorType();
 | |
|   unsigned NumInits = E->getNumInits();
 | |
|   unsigned NumElements = VT->getNumElements();
 | |
|   
 | |
|   QualType EltTy = VT->getElementType();
 | |
|   llvm::SmallVector<APValue, 4> Elements;
 | |
| 
 | |
|   for (unsigned i = 0; i < NumElements; i++) {
 | |
|     if (EltTy->isIntegerType()) {
 | |
|       llvm::APSInt sInt(32);
 | |
|       if (i < NumInits) {
 | |
|         if (!EvaluateInteger(E->getInit(i), sInt, Info))
 | |
|           return APValue();
 | |
|       } else {
 | |
|         sInt = Info.Ctx.MakeIntValue(0, EltTy);
 | |
|       }
 | |
|       Elements.push_back(APValue(sInt));
 | |
|     } else {
 | |
|       llvm::APFloat f(0.0);
 | |
|       if (i < NumInits) {
 | |
|         if (!EvaluateFloat(E->getInit(i), f, Info))
 | |
|           return APValue();
 | |
|       } else {
 | |
|         f = APFloat::getZero(Info.Ctx.getFloatTypeSemantics(EltTy));
 | |
|       }
 | |
|       Elements.push_back(APValue(f));
 | |
|     }
 | |
|   }
 | |
|   return APValue(&Elements[0], Elements.size());
 | |
| }
 | |
| 
 | |
| APValue 
 | |
| VectorExprEvaluator::GetZeroVector(QualType T) {
 | |
|   const VectorType *VT = T->getAsVectorType();
 | |
|   QualType EltTy = VT->getElementType();
 | |
|   APValue ZeroElement;
 | |
|   if (EltTy->isIntegerType())
 | |
|     ZeroElement = APValue(Info.Ctx.MakeIntValue(0, EltTy));
 | |
|   else
 | |
|     ZeroElement =
 | |
|         APValue(APFloat::getZero(Info.Ctx.getFloatTypeSemantics(EltTy)));
 | |
| 
 | |
|   llvm::SmallVector<APValue, 4> Elements(VT->getNumElements(), ZeroElement);
 | |
|   return APValue(&Elements[0], Elements.size());
 | |
| }
 | |
| 
 | |
| APValue VectorExprEvaluator::VisitConditionalOperator(const ConditionalOperator *E) {
 | |
|   bool BoolResult;
 | |
|   if (!HandleConversionToBool(E->getCond(), BoolResult, Info))
 | |
|     return APValue();
 | |
| 
 | |
|   Expr* EvalExpr = BoolResult ? E->getTrueExpr() : E->getFalseExpr();
 | |
| 
 | |
|   APValue Result;
 | |
|   if (EvaluateVector(EvalExpr, Result, Info))
 | |
|     return Result;
 | |
|   return APValue();
 | |
| }
 | |
| 
 | |
| APValue VectorExprEvaluator::VisitUnaryImag(const UnaryOperator *E) {
 | |
|   if (!E->getSubExpr()->isEvaluatable(Info.Ctx))
 | |
|     Info.EvalResult.HasSideEffects = true;
 | |
|   return GetZeroVector(E->getType());
 | |
| }
 | |
| 
 | |
| //===----------------------------------------------------------------------===//
 | |
| // Integer Evaluation
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| namespace {
 | |
| class VISIBILITY_HIDDEN IntExprEvaluator
 | |
|   : public StmtVisitor<IntExprEvaluator, bool> {
 | |
|   EvalInfo &Info;
 | |
|   APValue &Result;
 | |
| public:
 | |
|   IntExprEvaluator(EvalInfo &info, APValue &result)
 | |
|     : Info(info), Result(result) {}
 | |
| 
 | |
|   bool Success(const llvm::APSInt &SI, const Expr *E) {
 | |
|     assert(E->getType()->isIntegralType() && "Invalid evaluation result.");
 | |
|     assert(SI.isSigned() == E->getType()->isSignedIntegerType() &&
 | |
|            "Invalid evaluation result.");
 | |
|     assert(SI.getBitWidth() == Info.Ctx.getIntWidth(E->getType()) &&
 | |
|            "Invalid evaluation result.");
 | |
|     Result = APValue(SI);
 | |
|     return true;
 | |
|   }
 | |
| 
 | |
|   bool Success(const llvm::APInt &I, const Expr *E) {
 | |
|     assert(E->getType()->isIntegralType() && "Invalid evaluation result.");
 | |
|     assert(I.getBitWidth() == Info.Ctx.getIntWidth(E->getType()) &&
 | |
|            "Invalid evaluation result.");
 | |
|     Result = APValue(APSInt(I));
 | |
|     Result.getInt().setIsUnsigned(E->getType()->isUnsignedIntegerType());
 | |
|     return true;
 | |
|   }
 | |
| 
 | |
|   bool Success(uint64_t Value, const Expr *E) {
 | |
|     assert(E->getType()->isIntegralType() && "Invalid evaluation result.");
 | |
|     Result = APValue(Info.Ctx.MakeIntValue(Value, E->getType()));
 | |
|     return true;
 | |
|   }
 | |
| 
 | |
|   bool Error(SourceLocation L, diag::kind D, const Expr *E) {
 | |
|     // Take the first error.
 | |
|     if (Info.EvalResult.Diag == 0) {
 | |
|       Info.EvalResult.DiagLoc = L;
 | |
|       Info.EvalResult.Diag = D;
 | |
|       Info.EvalResult.DiagExpr = E;
 | |
|     }
 | |
|     return false;
 | |
|   }
 | |
|     
 | |
|   //===--------------------------------------------------------------------===//
 | |
|   //                            Visitor Methods
 | |
|   //===--------------------------------------------------------------------===//
 | |
|   
 | |
|   bool VisitStmt(Stmt *) {
 | |
|     assert(0 && "This should be called on integers, stmts are not integers");
 | |
|     return false;
 | |
|   }
 | |
|     
 | |
|   bool VisitExpr(Expr *E) {
 | |
|     return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E);
 | |
|   }
 | |
|   
 | |
|   bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
 | |
| 
 | |
|   bool VisitIntegerLiteral(const IntegerLiteral *E) {
 | |
|     return Success(E->getValue(), E);
 | |
|   }
 | |
|   bool VisitCharacterLiteral(const CharacterLiteral *E) {
 | |
|     return Success(E->getValue(), E);
 | |
|   }
 | |
|   bool VisitTypesCompatibleExpr(const TypesCompatibleExpr *E) {
 | |
|     // Per gcc docs "this built-in function ignores top level
 | |
|     // qualifiers".  We need to use the canonical version to properly
 | |
|     // be able to strip CRV qualifiers from the type.
 | |
|     QualType T0 = Info.Ctx.getCanonicalType(E->getArgType1());
 | |
|     QualType T1 = Info.Ctx.getCanonicalType(E->getArgType2());
 | |
|     return Success(Info.Ctx.typesAreCompatible(T0.getUnqualifiedType(), 
 | |
|                                                T1.getUnqualifiedType()),
 | |
|                    E);
 | |
|   }
 | |
|   bool VisitDeclRefExpr(const DeclRefExpr *E);
 | |
|   bool VisitCallExpr(const CallExpr *E);
 | |
|   bool VisitBinaryOperator(const BinaryOperator *E);
 | |
|   bool VisitUnaryOperator(const UnaryOperator *E);
 | |
|   bool VisitConditionalOperator(const ConditionalOperator *E);
 | |
| 
 | |
|   bool VisitCastExpr(CastExpr* E);
 | |
|   bool VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E);
 | |
| 
 | |
|   bool VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E) {
 | |
|     return Success(E->getValue(), E);
 | |
|   }
 | |
|   
 | |
|   bool VisitGNUNullExpr(const GNUNullExpr *E) {
 | |
|     return Success(0, E);
 | |
|   }
 | |
|     
 | |
|   bool VisitCXXZeroInitValueExpr(const CXXZeroInitValueExpr *E) {
 | |
|     return Success(0, E);
 | |
|   }
 | |
| 
 | |
|   bool VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) {
 | |
|     return Success(0, E);
 | |
|   }
 | |
| 
 | |
|   bool VisitUnaryTypeTraitExpr(const UnaryTypeTraitExpr *E) {
 | |
|     return Success(E->EvaluateTrait(), E);
 | |
|   }
 | |
| 
 | |
|   bool VisitChooseExpr(const ChooseExpr *E) {
 | |
|     return Visit(E->getChosenSubExpr(Info.Ctx));
 | |
|   }
 | |
| 
 | |
|   bool VisitUnaryReal(const UnaryOperator *E);
 | |
|   bool VisitUnaryImag(const UnaryOperator *E);
 | |
| 
 | |
| private:
 | |
|   unsigned GetAlignOfExpr(const Expr *E);
 | |
|   unsigned GetAlignOfType(QualType T);
 | |
|   // FIXME: Missing: array subscript of vector, member of vector
 | |
| };
 | |
| } // end anonymous namespace
 | |
| 
 | |
| static bool EvaluateIntegerOrLValue(const Expr* E, APValue &Result, EvalInfo &Info) {
 | |
|   if (!E->getType()->isIntegralType())
 | |
|     return false;
 | |
|   
 | |
|   return IntExprEvaluator(Info, Result).Visit(const_cast<Expr*>(E));
 | |
| }
 | |
| 
 | |
| static bool EvaluateInteger(const Expr* E, APSInt &Result, EvalInfo &Info) {
 | |
|   APValue Val;
 | |
|   if (!EvaluateIntegerOrLValue(E, Val, Info) || !Val.isInt())
 | |
|     return false;
 | |
|   Result = Val.getInt();
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| bool IntExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) {
 | |
|   // Enums are integer constant exprs.
 | |
|   if (const EnumConstantDecl *D = dyn_cast<EnumConstantDecl>(E->getDecl())) {
 | |
|     // FIXME: This is an ugly hack around the fact that enums don't set their
 | |
|     // signedness consistently; see PR3173.
 | |
|     APSInt SI = D->getInitVal();
 | |
|     SI.setIsUnsigned(!E->getType()->isSignedIntegerType());
 | |
|     // FIXME: This is an ugly hack around the fact that enums don't
 | |
|     // set their width (!?!) consistently; see PR3173.
 | |
|     SI.extOrTrunc(Info.Ctx.getIntWidth(E->getType()));
 | |
|     return Success(SI, E);
 | |
|   }
 | |
| 
 | |
|   // In C++, const, non-volatile integers initialized with ICEs are ICEs.
 | |
|   // In C, they can also be folded, although they are not ICEs.
 | |
|   if (E->getType().getCVRQualifiers() == QualType::Const) {
 | |
|     if (const VarDecl *D = dyn_cast<VarDecl>(E->getDecl())) {
 | |
|       if (const Expr *Init = D->getInit())
 | |
|         return Visit(const_cast<Expr*>(Init));
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   // Otherwise, random variable references are not constants.
 | |
|   return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E);
 | |
| }
 | |
| 
 | |
| /// EvaluateBuiltinClassifyType - Evaluate __builtin_classify_type the same way
 | |
| /// as GCC.
 | |
| static int EvaluateBuiltinClassifyType(const CallExpr *E) {
 | |
|   // The following enum mimics the values returned by GCC.
 | |
|   // FIXME: Does GCC differ between lvalue and rvalue references here?
 | |
|   enum gcc_type_class {
 | |
|     no_type_class = -1,
 | |
|     void_type_class, integer_type_class, char_type_class,
 | |
|     enumeral_type_class, boolean_type_class,
 | |
|     pointer_type_class, reference_type_class, offset_type_class,
 | |
|     real_type_class, complex_type_class,
 | |
|     function_type_class, method_type_class,
 | |
|     record_type_class, union_type_class,
 | |
|     array_type_class, string_type_class,
 | |
|     lang_type_class
 | |
|   };
 | |
|   
 | |
|   // If no argument was supplied, default to "no_type_class". This isn't 
 | |
|   // ideal, however it is what gcc does.
 | |
|   if (E->getNumArgs() == 0)
 | |
|     return no_type_class;
 | |
|   
 | |
|   QualType ArgTy = E->getArg(0)->getType();
 | |
|   if (ArgTy->isVoidType())
 | |
|     return void_type_class;
 | |
|   else if (ArgTy->isEnumeralType())
 | |
|     return enumeral_type_class;
 | |
|   else if (ArgTy->isBooleanType())
 | |
|     return boolean_type_class;
 | |
|   else if (ArgTy->isCharType())
 | |
|     return string_type_class; // gcc doesn't appear to use char_type_class
 | |
|   else if (ArgTy->isIntegerType())
 | |
|     return integer_type_class;
 | |
|   else if (ArgTy->isPointerType())
 | |
|     return pointer_type_class;
 | |
|   else if (ArgTy->isReferenceType())
 | |
|     return reference_type_class;
 | |
|   else if (ArgTy->isRealType())
 | |
|     return real_type_class;
 | |
|   else if (ArgTy->isComplexType())
 | |
|     return complex_type_class;
 | |
|   else if (ArgTy->isFunctionType())
 | |
|     return function_type_class;
 | |
|   else if (ArgTy->isStructureType())
 | |
|     return record_type_class;
 | |
|   else if (ArgTy->isUnionType())
 | |
|     return union_type_class;
 | |
|   else if (ArgTy->isArrayType())
 | |
|     return array_type_class;
 | |
|   else if (ArgTy->isUnionType())
 | |
|     return union_type_class;
 | |
|   else  // FIXME: offset_type_class, method_type_class, & lang_type_class?
 | |
|     assert(0 && "CallExpr::isBuiltinClassifyType(): unimplemented type");
 | |
|   return -1;
 | |
| }
 | |
| 
 | |
| bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
 | |
|   switch (E->isBuiltinCall(Info.Ctx)) {
 | |
|   default:
 | |
|     return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E);
 | |
|   case Builtin::BI__builtin_classify_type:
 | |
|     return Success(EvaluateBuiltinClassifyType(E), E);
 | |
|     
 | |
|   case Builtin::BI__builtin_constant_p:
 | |
|     // __builtin_constant_p always has one operand: it returns true if that
 | |
|     // operand can be folded, false otherwise.
 | |
|     return Success(E->getArg(0)->isEvaluatable(Info.Ctx), E);
 | |
|   }
 | |
| }
 | |
| 
 | |
| bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
 | |
|   if (E->getOpcode() == BinaryOperator::Comma) {
 | |
|     if (!Visit(E->getRHS()))
 | |
|       return false;
 | |
| 
 | |
|     // If we can't evaluate the LHS, it might have side effects;
 | |
|     // conservatively mark it.
 | |
|     if (!E->getLHS()->isEvaluatable(Info.Ctx))
 | |
|       Info.EvalResult.HasSideEffects = true;
 | |
| 
 | |
|     return true;
 | |
|   }
 | |
| 
 | |
|   if (E->isLogicalOp()) {
 | |
|     // These need to be handled specially because the operands aren't
 | |
|     // necessarily integral
 | |
|     bool lhsResult, rhsResult;
 | |
|     
 | |
|     if (HandleConversionToBool(E->getLHS(), lhsResult, Info)) {
 | |
|       // We were able to evaluate the LHS, see if we can get away with not
 | |
|       // evaluating the RHS: 0 && X -> 0, 1 || X -> 1
 | |
|       if (lhsResult == (E->getOpcode() == BinaryOperator::LOr))
 | |
|         return Success(lhsResult, E);
 | |
| 
 | |
|       if (HandleConversionToBool(E->getRHS(), rhsResult, Info)) {
 | |
|         if (E->getOpcode() == BinaryOperator::LOr)
 | |
|           return Success(lhsResult || rhsResult, E);
 | |
|         else
 | |
|           return Success(lhsResult && rhsResult, E);
 | |
|       }
 | |
|     } else {
 | |
|       if (HandleConversionToBool(E->getRHS(), rhsResult, Info)) {
 | |
|         // We can't evaluate the LHS; however, sometimes the result
 | |
|         // is determined by the RHS: X && 0 -> 0, X || 1 -> 1.
 | |
|         if (rhsResult == (E->getOpcode() == BinaryOperator::LOr) || 
 | |
|             !rhsResult == (E->getOpcode() == BinaryOperator::LAnd)) {
 | |
|           // Since we weren't able to evaluate the left hand side, it
 | |
|           // must have had side effects.
 | |
|           Info.EvalResult.HasSideEffects = true;
 | |
| 
 | |
|           return Success(rhsResult, E);
 | |
|         }
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   QualType LHSTy = E->getLHS()->getType();
 | |
|   QualType RHSTy = E->getRHS()->getType();
 | |
| 
 | |
|   if (LHSTy->isAnyComplexType()) {
 | |
|     assert(RHSTy->isAnyComplexType() && "Invalid comparison");
 | |
|     APValue LHS, RHS;
 | |
| 
 | |
|     if (!EvaluateComplex(E->getLHS(), LHS, Info))
 | |
|       return false;
 | |
| 
 | |
|     if (!EvaluateComplex(E->getRHS(), RHS, Info))
 | |
|       return false;
 | |
| 
 | |
|     if (LHS.isComplexFloat()) {
 | |
|       APFloat::cmpResult CR_r = 
 | |
|         LHS.getComplexFloatReal().compare(RHS.getComplexFloatReal());
 | |
|       APFloat::cmpResult CR_i = 
 | |
|         LHS.getComplexFloatImag().compare(RHS.getComplexFloatImag());
 | |
| 
 | |
|       if (E->getOpcode() == BinaryOperator::EQ)
 | |
|         return Success((CR_r == APFloat::cmpEqual &&
 | |
|                         CR_i == APFloat::cmpEqual), E);
 | |
|       else {
 | |
|         assert(E->getOpcode() == BinaryOperator::NE &&
 | |
|                "Invalid complex comparison.");
 | |
|         return Success(((CR_r == APFloat::cmpGreaterThan || 
 | |
|                          CR_r == APFloat::cmpLessThan) &&
 | |
|                         (CR_i == APFloat::cmpGreaterThan || 
 | |
|                          CR_i == APFloat::cmpLessThan)), E);
 | |
|       }
 | |
|     } else {
 | |
|       if (E->getOpcode() == BinaryOperator::EQ)
 | |
|         return Success((LHS.getComplexIntReal() == RHS.getComplexIntReal() &&
 | |
|                         LHS.getComplexIntImag() == RHS.getComplexIntImag()), E);
 | |
|       else {
 | |
|         assert(E->getOpcode() == BinaryOperator::NE &&
 | |
|                "Invalid compex comparison.");
 | |
|         return Success((LHS.getComplexIntReal() != RHS.getComplexIntReal() ||
 | |
|                         LHS.getComplexIntImag() != RHS.getComplexIntImag()), E);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   
 | |
|   if (LHSTy->isRealFloatingType() &&
 | |
|       RHSTy->isRealFloatingType()) {
 | |
|     APFloat RHS(0.0), LHS(0.0);
 | |
|     
 | |
|     if (!EvaluateFloat(E->getRHS(), RHS, Info))
 | |
|       return false;
 | |
|     
 | |
|     if (!EvaluateFloat(E->getLHS(), LHS, Info))
 | |
|       return false;
 | |
|     
 | |
|     APFloat::cmpResult CR = LHS.compare(RHS);
 | |
| 
 | |
|     switch (E->getOpcode()) {
 | |
|     default:
 | |
|       assert(0 && "Invalid binary operator!");
 | |
|     case BinaryOperator::LT:
 | |
|       return Success(CR == APFloat::cmpLessThan, E);
 | |
|     case BinaryOperator::GT:
 | |
|       return Success(CR == APFloat::cmpGreaterThan, E);
 | |
|     case BinaryOperator::LE:
 | |
|       return Success(CR == APFloat::cmpLessThan || CR == APFloat::cmpEqual, E);
 | |
|     case BinaryOperator::GE:
 | |
|       return Success(CR == APFloat::cmpGreaterThan || CR == APFloat::cmpEqual, 
 | |
|                      E);
 | |
|     case BinaryOperator::EQ:
 | |
|       return Success(CR == APFloat::cmpEqual, E);
 | |
|     case BinaryOperator::NE:
 | |
|       return Success(CR == APFloat::cmpGreaterThan 
 | |
|                      || CR == APFloat::cmpLessThan, E);
 | |
|     }
 | |
|   }
 | |
|   
 | |
|   if (LHSTy->isPointerType() && RHSTy->isPointerType()) {
 | |
|     if (E->getOpcode() == BinaryOperator::Sub || E->isEqualityOp()) {
 | |
|       APValue LHSValue;
 | |
|       if (!EvaluatePointer(E->getLHS(), LHSValue, Info))
 | |
|         return false;
 | |
| 
 | |
|       APValue RHSValue;
 | |
|       if (!EvaluatePointer(E->getRHS(), RHSValue, Info))
 | |
|         return false;
 | |
| 
 | |
|       // Reject any bases; this is conservative, but good enough for
 | |
|       // common uses
 | |
|       if (LHSValue.getLValueBase() || RHSValue.getLValueBase())
 | |
|         return false;
 | |
| 
 | |
|       if (E->getOpcode() == BinaryOperator::Sub) {
 | |
|         const QualType Type = E->getLHS()->getType();
 | |
|         const QualType ElementType = Type->getAsPointerType()->getPointeeType();
 | |
| 
 | |
|         uint64_t D = LHSValue.getLValueOffset() - RHSValue.getLValueOffset();
 | |
|         D /= Info.Ctx.getTypeSize(ElementType) / 8;
 | |
| 
 | |
|         return Success(D, E);
 | |
|       }
 | |
|       bool Result;
 | |
|       if (E->getOpcode() == BinaryOperator::EQ) {
 | |
|         Result = LHSValue.getLValueOffset() == RHSValue.getLValueOffset();
 | |
|       } else {
 | |
|         Result = LHSValue.getLValueOffset() != RHSValue.getLValueOffset();
 | |
|       }
 | |
|       return Success(Result, E);
 | |
|     }
 | |
|   }
 | |
|   if (!LHSTy->isIntegralType() ||
 | |
|       !RHSTy->isIntegralType()) {
 | |
|     // We can't continue from here for non-integral types, and they
 | |
|     // could potentially confuse the following operations.
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   // The LHS of a constant expr is always evaluated and needed.
 | |
|   if (!Visit(E->getLHS()))
 | |
|     return false; // error in subexpression.
 | |
| 
 | |
|   APValue RHSVal;
 | |
|   if (!EvaluateIntegerOrLValue(E->getRHS(), RHSVal, Info))
 | |
|     return false;
 | |
| 
 | |
|   // Handle cases like (unsigned long)&a + 4.
 | |
|   if (E->isAdditiveOp() && Result.isLValue() && RHSVal.isInt()) {
 | |
|     uint64_t offset = Result.getLValueOffset();
 | |
|     if (E->getOpcode() == BinaryOperator::Add)
 | |
|       offset += RHSVal.getInt().getZExtValue();
 | |
|     else
 | |
|       offset -= RHSVal.getInt().getZExtValue();
 | |
|     Result = APValue(Result.getLValueBase(), offset);
 | |
|     return true;
 | |
|   }
 | |
| 
 | |
|   // Handle cases like 4 + (unsigned long)&a
 | |
|   if (E->getOpcode() == BinaryOperator::Add &&
 | |
|         RHSVal.isLValue() && Result.isInt()) {
 | |
|     uint64_t offset = RHSVal.getLValueOffset();
 | |
|     offset += Result.getInt().getZExtValue();
 | |
|     Result = APValue(RHSVal.getLValueBase(), offset);
 | |
|     return true;
 | |
|   }
 | |
| 
 | |
|   // All the following cases expect both operands to be an integer
 | |
|   if (!Result.isInt() || !RHSVal.isInt())
 | |
|     return false;
 | |
| 
 | |
|   APSInt& RHS = RHSVal.getInt();
 | |
| 
 | |
|   switch (E->getOpcode()) {
 | |
|   default:
 | |
|     return Error(E->getOperatorLoc(), diag::note_invalid_subexpr_in_ice, E);
 | |
|   case BinaryOperator::Mul: return Success(Result.getInt() * RHS, E);
 | |
|   case BinaryOperator::Add: return Success(Result.getInt() + RHS, E);
 | |
|   case BinaryOperator::Sub: return Success(Result.getInt() - RHS, E);
 | |
|   case BinaryOperator::And: return Success(Result.getInt() & RHS, E);
 | |
|   case BinaryOperator::Xor: return Success(Result.getInt() ^ RHS, E);
 | |
|   case BinaryOperator::Or:  return Success(Result.getInt() | RHS, E);
 | |
|   case BinaryOperator::Div:
 | |
|     if (RHS == 0)
 | |
|       return Error(E->getOperatorLoc(), diag::note_expr_divide_by_zero, E);
 | |
|     return Success(Result.getInt() / RHS, E);
 | |
|   case BinaryOperator::Rem:
 | |
|     if (RHS == 0)
 | |
|       return Error(E->getOperatorLoc(), diag::note_expr_divide_by_zero, E);
 | |
|     return Success(Result.getInt() % RHS, E);
 | |
|   case BinaryOperator::Shl: {
 | |
|     // FIXME: Warn about out of range shift amounts!
 | |
|     unsigned SA = 
 | |
|       (unsigned) RHS.getLimitedValue(Result.getInt().getBitWidth()-1);
 | |
|     return Success(Result.getInt() << SA, E);
 | |
|   }
 | |
|   case BinaryOperator::Shr: {
 | |
|     unsigned SA = 
 | |
|       (unsigned) RHS.getLimitedValue(Result.getInt().getBitWidth()-1);
 | |
|     return Success(Result.getInt() >> SA, E);
 | |
|   }
 | |
|       
 | |
|   case BinaryOperator::LT: return Success(Result.getInt() < RHS, E);
 | |
|   case BinaryOperator::GT: return Success(Result.getInt() > RHS, E);
 | |
|   case BinaryOperator::LE: return Success(Result.getInt() <= RHS, E);
 | |
|   case BinaryOperator::GE: return Success(Result.getInt() >= RHS, E);
 | |
|   case BinaryOperator::EQ: return Success(Result.getInt() == RHS, E);
 | |
|   case BinaryOperator::NE: return Success(Result.getInt() != RHS, E);
 | |
|   }
 | |
| }
 | |
| 
 | |
| bool IntExprEvaluator::VisitConditionalOperator(const ConditionalOperator *E) {
 | |
|   bool Cond;
 | |
|   if (!HandleConversionToBool(E->getCond(), Cond, Info))
 | |
|     return false;
 | |
| 
 | |
|   return Visit(Cond ? E->getTrueExpr() : E->getFalseExpr());
 | |
| }
 | |
| 
 | |
| unsigned IntExprEvaluator::GetAlignOfType(QualType T) {
 | |
|   // Get information about the alignment.
 | |
|   unsigned CharSize = Info.Ctx.Target.getCharWidth();
 | |
| 
 | |
|   // FIXME: Why do we ask for the preferred alignment?
 | |
|   return Info.Ctx.getPreferredTypeAlign(T.getTypePtr()) / CharSize;
 | |
| }
 | |
| 
 | |
| unsigned IntExprEvaluator::GetAlignOfExpr(const Expr *E) {
 | |
|   E = E->IgnoreParens();
 | |
| 
 | |
|   // alignof decl is always accepted, even if it doesn't make sense: we default
 | |
|   // to 1 in those cases. 
 | |
|   if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
 | |
|     return Info.Ctx.getDeclAlignInBytes(DRE->getDecl());
 | |
| 
 | |
|   if (const MemberExpr *ME = dyn_cast<MemberExpr>(E))
 | |
|     return Info.Ctx.getDeclAlignInBytes(ME->getMemberDecl());
 | |
| 
 | |
|   return GetAlignOfType(E->getType());
 | |
| }
 | |
| 
 | |
| 
 | |
| /// VisitSizeAlignOfExpr - Evaluate a sizeof or alignof with a result as the
 | |
| /// expression's type.
 | |
| bool IntExprEvaluator::VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E) {
 | |
|   QualType DstTy = E->getType();
 | |
| 
 | |
|   // Handle alignof separately.
 | |
|   if (!E->isSizeOf()) {
 | |
|     if (E->isArgumentType())
 | |
|       return Success(GetAlignOfType(E->getArgumentType()), E);
 | |
|     else
 | |
|       return Success(GetAlignOfExpr(E->getArgumentExpr()), E);
 | |
|   }
 | |
| 
 | |
|   QualType SrcTy = E->getTypeOfArgument();
 | |
| 
 | |
|   // sizeof(void), __alignof__(void), sizeof(function) = 1 as a gcc
 | |
|   // extension.
 | |
|   if (SrcTy->isVoidType() || SrcTy->isFunctionType())
 | |
|     return Success(1, E);
 | |
| 
 | |
|   // sizeof(vla) is not a constantexpr: C99 6.5.3.4p2.
 | |
|   if (!SrcTy->isConstantSizeType())
 | |
|     return false;
 | |
| 
 | |
|   // Get information about the size.
 | |
|   unsigned BitWidth = Info.Ctx.getTypeSize(SrcTy);
 | |
|   return Success(BitWidth / Info.Ctx.Target.getCharWidth(), E);
 | |
| }
 | |
| 
 | |
| bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
 | |
|   // Special case unary operators that do not need their subexpression
 | |
|   // evaluated.  offsetof/sizeof/alignof are all special.
 | |
|   if (E->isOffsetOfOp()) {
 | |
|     // The AST for offsetof is defined in such a way that we can just
 | |
|     // directly Evaluate it as an l-value.
 | |
|     APValue LV;
 | |
|     if (!EvaluateLValue(E->getSubExpr(), LV, Info))
 | |
|       return false;
 | |
|     if (LV.getLValueBase())
 | |
|       return false;
 | |
|     return Success(LV.getLValueOffset(), E);
 | |
|   }
 | |
| 
 | |
|   if (E->getOpcode() == UnaryOperator::LNot) {
 | |
|     // LNot's operand isn't necessarily an integer, so we handle it specially.
 | |
|     bool bres;
 | |
|     if (!HandleConversionToBool(E->getSubExpr(), bres, Info))
 | |
|       return false;
 | |
|     return Success(!bres, E);
 | |
|   }
 | |
| 
 | |
|   // Only handle integral operations...
 | |
|   if (!E->getSubExpr()->getType()->isIntegralType())
 | |
|     return false;
 | |
| 
 | |
|   // Get the operand value into 'Result'.
 | |
|   if (!Visit(E->getSubExpr()))
 | |
|     return false;
 | |
| 
 | |
|   switch (E->getOpcode()) {
 | |
|   default:
 | |
|     // Address, indirect, pre/post inc/dec, etc are not valid constant exprs.
 | |
|     // See C99 6.6p3.
 | |
|     return Error(E->getOperatorLoc(), diag::note_invalid_subexpr_in_ice, E);
 | |
|   case UnaryOperator::Extension:
 | |
|     // FIXME: Should extension allow i-c-e extension expressions in its scope?
 | |
|     // If so, we could clear the diagnostic ID.
 | |
|     return true;
 | |
|   case UnaryOperator::Plus:
 | |
|     // The result is always just the subexpr. 
 | |
|     return true;
 | |
|   case UnaryOperator::Minus:
 | |
|     if (!Result.isInt()) return false;
 | |
|     return Success(-Result.getInt(), E);
 | |
|   case UnaryOperator::Not:
 | |
|     if (!Result.isInt()) return false;
 | |
|     return Success(~Result.getInt(), E);
 | |
|   }
 | |
| }
 | |
|   
 | |
| /// HandleCast - This is used to evaluate implicit or explicit casts where the
 | |
| /// result type is integer.
 | |
| bool IntExprEvaluator::VisitCastExpr(CastExpr *E) {
 | |
|   Expr *SubExpr = E->getSubExpr();
 | |
|   QualType DestType = E->getType();
 | |
|   QualType SrcType = SubExpr->getType();
 | |
| 
 | |
|   if (DestType->isBooleanType()) {
 | |
|     bool BoolResult;
 | |
|     if (!HandleConversionToBool(SubExpr, BoolResult, Info))
 | |
|       return false;
 | |
|     return Success(BoolResult, E);
 | |
|   }
 | |
| 
 | |
|   // Handle simple integer->integer casts.
 | |
|   if (SrcType->isIntegralType()) {
 | |
|     if (!Visit(SubExpr))
 | |
|       return false;
 | |
| 
 | |
|     if (!Result.isInt()) {
 | |
|       // Only allow casts of lvalues if they are lossless.
 | |
|       return Info.Ctx.getTypeSize(DestType) == Info.Ctx.getTypeSize(SrcType);
 | |
|     }
 | |
| 
 | |
|     return Success(HandleIntToIntCast(DestType, SrcType,
 | |
|                                       Result.getInt(), Info.Ctx), E);
 | |
|   }
 | |
|   
 | |
|   // FIXME: Clean this up!
 | |
|   if (SrcType->isPointerType()) {
 | |
|     APValue LV;
 | |
|     if (!EvaluatePointer(SubExpr, LV, Info))
 | |
|       return false;
 | |
| 
 | |
|     if (LV.getLValueBase()) {
 | |
|       // Only allow based lvalue casts if they are lossless.
 | |
|       if (Info.Ctx.getTypeSize(DestType) != Info.Ctx.getTypeSize(SrcType))
 | |
|         return false;
 | |
| 
 | |
|       Result = LV;
 | |
|       return true;
 | |
|     }
 | |
| 
 | |
|     APSInt AsInt = Info.Ctx.MakeIntValue(LV.getLValueOffset(), SrcType);
 | |
|     return Success(HandleIntToIntCast(DestType, SrcType, AsInt, Info.Ctx), E);
 | |
|   }
 | |
| 
 | |
|   if (SrcType->isArrayType() || SrcType->isFunctionType()) {
 | |
|     // This handles double-conversion cases, where there's both
 | |
|     // an l-value promotion and an implicit conversion to int.
 | |
|     APValue LV;
 | |
|     if (!EvaluateLValue(SubExpr, LV, Info))
 | |
|       return false;
 | |
| 
 | |
|     if (Info.Ctx.getTypeSize(DestType) != Info.Ctx.getTypeSize(Info.Ctx.VoidPtrTy))
 | |
|       return false;
 | |
| 
 | |
|     Result = LV;
 | |
|     return true;
 | |
|   }
 | |
| 
 | |
|   if (SrcType->isAnyComplexType()) {
 | |
|     APValue C;
 | |
|     if (!EvaluateComplex(SubExpr, C, Info))
 | |
|       return false;
 | |
|     if (C.isComplexFloat())
 | |
|       return Success(HandleFloatToIntCast(DestType, SrcType,
 | |
|                                           C.getComplexFloatReal(), Info.Ctx),
 | |
|                      E);
 | |
|     else
 | |
|       return Success(HandleIntToIntCast(DestType, SrcType,
 | |
|                                         C.getComplexIntReal(), Info.Ctx), E);
 | |
|   }
 | |
|   // FIXME: Handle vectors
 | |
| 
 | |
|   if (!SrcType->isRealFloatingType())
 | |
|     return Error(E->getExprLoc(), diag::note_invalid_subexpr_in_ice, E);
 | |
| 
 | |
|   APFloat F(0.0);
 | |
|   if (!EvaluateFloat(SubExpr, F, Info))
 | |
|     return Error(E->getExprLoc(), diag::note_invalid_subexpr_in_ice, E);
 | |
|   
 | |
|   return Success(HandleFloatToIntCast(DestType, SrcType, F, Info.Ctx), E);
 | |
| }
 | |
| 
 | |
| bool IntExprEvaluator::VisitUnaryReal(const UnaryOperator *E) {
 | |
|   if (E->getSubExpr()->getType()->isAnyComplexType()) {
 | |
|     APValue LV;
 | |
|     if (!EvaluateComplex(E->getSubExpr(), LV, Info) || !LV.isComplexInt())
 | |
|       return Error(E->getExprLoc(), diag::note_invalid_subexpr_in_ice, E);
 | |
|     return Success(LV.getComplexIntReal(), E);
 | |
|   }
 | |
| 
 | |
|   return Visit(E->getSubExpr());
 | |
| }
 | |
| 
 | |
| bool IntExprEvaluator::VisitUnaryImag(const UnaryOperator *E) {
 | |
|   if (E->getSubExpr()->getType()->isComplexIntegerType()) {
 | |
|     APValue LV;
 | |
|     if (!EvaluateComplex(E->getSubExpr(), LV, Info) || !LV.isComplexInt())
 | |
|       return Error(E->getExprLoc(), diag::note_invalid_subexpr_in_ice, E);
 | |
|     return Success(LV.getComplexIntImag(), E);
 | |
|   }
 | |
| 
 | |
|   if (!E->getSubExpr()->isEvaluatable(Info.Ctx))
 | |
|     Info.EvalResult.HasSideEffects = true;
 | |
|   return Success(0, E);
 | |
| }
 | |
| 
 | |
| //===----------------------------------------------------------------------===//
 | |
| // Float Evaluation
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| namespace {
 | |
| class VISIBILITY_HIDDEN FloatExprEvaluator
 | |
|   : public StmtVisitor<FloatExprEvaluator, bool> {
 | |
|   EvalInfo &Info;
 | |
|   APFloat &Result;
 | |
| public:
 | |
|   FloatExprEvaluator(EvalInfo &info, APFloat &result)
 | |
|     : Info(info), Result(result) {}
 | |
| 
 | |
|   bool VisitStmt(Stmt *S) {
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
 | |
|   bool VisitCallExpr(const CallExpr *E);
 | |
| 
 | |
|   bool VisitUnaryOperator(const UnaryOperator *E);
 | |
|   bool VisitBinaryOperator(const BinaryOperator *E);
 | |
|   bool VisitFloatingLiteral(const FloatingLiteral *E);
 | |
|   bool VisitCastExpr(CastExpr *E);
 | |
|   bool VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *E);
 | |
| 
 | |
|   bool VisitChooseExpr(const ChooseExpr *E)
 | |
|     { return Visit(E->getChosenSubExpr(Info.Ctx)); }
 | |
|   bool VisitUnaryExtension(const UnaryOperator *E)
 | |
|     { return Visit(E->getSubExpr()); }
 | |
| 
 | |
|   // FIXME: Missing: __real__/__imag__, array subscript of vector,
 | |
|   //                 member of vector, ImplicitValueInitExpr,
 | |
|   //                 conditional ?:, comma
 | |
| };
 | |
| } // end anonymous namespace
 | |
| 
 | |
| static bool EvaluateFloat(const Expr* E, APFloat& Result, EvalInfo &Info) {
 | |
|   return FloatExprEvaluator(Info, Result).Visit(const_cast<Expr*>(E));
 | |
| }
 | |
| 
 | |
| bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) {
 | |
|   switch (E->isBuiltinCall(Info.Ctx)) {
 | |
|   default: return false;
 | |
|   case Builtin::BI__builtin_huge_val:
 | |
|   case Builtin::BI__builtin_huge_valf:
 | |
|   case Builtin::BI__builtin_huge_vall:
 | |
|   case Builtin::BI__builtin_inf:
 | |
|   case Builtin::BI__builtin_inff:
 | |
|   case Builtin::BI__builtin_infl: {
 | |
|     const llvm::fltSemantics &Sem =
 | |
|       Info.Ctx.getFloatTypeSemantics(E->getType());
 | |
|     Result = llvm::APFloat::getInf(Sem);
 | |
|     return true;
 | |
|   }
 | |
|       
 | |
|   case Builtin::BI__builtin_nan:
 | |
|   case Builtin::BI__builtin_nanf:
 | |
|   case Builtin::BI__builtin_nanl:
 | |
|     // If this is __builtin_nan("") turn this into a simple nan, otherwise we
 | |
|     // can't constant fold it.
 | |
|     if (const StringLiteral *S = 
 | |
|         dyn_cast<StringLiteral>(E->getArg(0)->IgnoreParenCasts())) {
 | |
|       if (!S->isWide() && S->getByteLength() == 0) { // empty string.
 | |
|         const llvm::fltSemantics &Sem =
 | |
|           Info.Ctx.getFloatTypeSemantics(E->getType());
 | |
|         Result = llvm::APFloat::getNaN(Sem);
 | |
|         return true;
 | |
|       }
 | |
|     }
 | |
|     return false;
 | |
| 
 | |
|   case Builtin::BI__builtin_fabs:
 | |
|   case Builtin::BI__builtin_fabsf:
 | |
|   case Builtin::BI__builtin_fabsl:
 | |
|     if (!EvaluateFloat(E->getArg(0), Result, Info))
 | |
|       return false;
 | |
|     
 | |
|     if (Result.isNegative())
 | |
|       Result.changeSign();
 | |
|     return true;
 | |
| 
 | |
|   case Builtin::BI__builtin_copysign: 
 | |
|   case Builtin::BI__builtin_copysignf: 
 | |
|   case Builtin::BI__builtin_copysignl: {
 | |
|     APFloat RHS(0.);
 | |
|     if (!EvaluateFloat(E->getArg(0), Result, Info) ||
 | |
|         !EvaluateFloat(E->getArg(1), RHS, Info))
 | |
|       return false;
 | |
|     Result.copySign(RHS);
 | |
|     return true;
 | |
|   }
 | |
|   }
 | |
| }
 | |
| 
 | |
| bool FloatExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
 | |
|   if (E->getOpcode() == UnaryOperator::Deref)
 | |
|     return false;
 | |
| 
 | |
|   if (!EvaluateFloat(E->getSubExpr(), Result, Info))
 | |
|     return false;
 | |
| 
 | |
|   switch (E->getOpcode()) {
 | |
|   default: return false;
 | |
|   case UnaryOperator::Plus: 
 | |
|     return true;
 | |
|   case UnaryOperator::Minus:
 | |
|     Result.changeSign();
 | |
|     return true;
 | |
|   }
 | |
| }
 | |
| 
 | |
| bool FloatExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
 | |
|   // FIXME: Diagnostics?  I really don't understand how the warnings
 | |
|   // and errors are supposed to work.
 | |
|   APFloat RHS(0.0);
 | |
|   if (!EvaluateFloat(E->getLHS(), Result, Info))
 | |
|     return false;
 | |
|   if (!EvaluateFloat(E->getRHS(), RHS, Info))
 | |
|     return false;
 | |
| 
 | |
|   switch (E->getOpcode()) {
 | |
|   default: return false;
 | |
|   case BinaryOperator::Mul:
 | |
|     Result.multiply(RHS, APFloat::rmNearestTiesToEven);
 | |
|     return true;
 | |
|   case BinaryOperator::Add:
 | |
|     Result.add(RHS, APFloat::rmNearestTiesToEven);
 | |
|     return true;
 | |
|   case BinaryOperator::Sub:
 | |
|     Result.subtract(RHS, APFloat::rmNearestTiesToEven);
 | |
|     return true;
 | |
|   case BinaryOperator::Div:
 | |
|     Result.divide(RHS, APFloat::rmNearestTiesToEven);
 | |
|     return true;
 | |
|   }
 | |
| }
 | |
| 
 | |
| bool FloatExprEvaluator::VisitFloatingLiteral(const FloatingLiteral *E) {
 | |
|   Result = E->getValue();
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| bool FloatExprEvaluator::VisitCastExpr(CastExpr *E) {
 | |
|   Expr* SubExpr = E->getSubExpr();
 | |
|   
 | |
|   if (SubExpr->getType()->isIntegralType()) {
 | |
|     APSInt IntResult;
 | |
|     if (!EvaluateInteger(SubExpr, IntResult, Info))
 | |
|       return false;
 | |
|     Result = HandleIntToFloatCast(E->getType(), SubExpr->getType(), 
 | |
|                                   IntResult, Info.Ctx);
 | |
|     return true;
 | |
|   }
 | |
|   if (SubExpr->getType()->isRealFloatingType()) {
 | |
|     if (!Visit(SubExpr))
 | |
|       return false;
 | |
|     Result = HandleFloatToFloatCast(E->getType(), SubExpr->getType(),
 | |
|                                     Result, Info.Ctx);
 | |
|     return true;
 | |
|   }
 | |
|   // FIXME: Handle complex types
 | |
| 
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| bool FloatExprEvaluator::VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *E) {
 | |
|   Result = APFloat::getZero(Info.Ctx.getFloatTypeSemantics(E->getType()));
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| //===----------------------------------------------------------------------===//
 | |
| // Complex Evaluation (for float and integer)
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| namespace {
 | |
| class VISIBILITY_HIDDEN ComplexExprEvaluator
 | |
|   : public StmtVisitor<ComplexExprEvaluator, APValue> {
 | |
|   EvalInfo &Info;
 | |
|   
 | |
| public:
 | |
|   ComplexExprEvaluator(EvalInfo &info) : Info(info) {}
 | |
|   
 | |
|   //===--------------------------------------------------------------------===//
 | |
|   //                            Visitor Methods
 | |
|   //===--------------------------------------------------------------------===//
 | |
| 
 | |
|   APValue VisitStmt(Stmt *S) {
 | |
|     return APValue();
 | |
|   }
 | |
|     
 | |
|   APValue VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
 | |
| 
 | |
|   APValue VisitImaginaryLiteral(ImaginaryLiteral *E) {
 | |
|     Expr* SubExpr = E->getSubExpr();
 | |
| 
 | |
|     if (SubExpr->getType()->isRealFloatingType()) {
 | |
|       APFloat Result(0.0);
 | |
| 
 | |
|       if (!EvaluateFloat(SubExpr, Result, Info))
 | |
|         return APValue();
 | |
|     
 | |
|       return APValue(APFloat(Result.getSemantics(), APFloat::fcZero, false), 
 | |
|                      Result);
 | |
|     } else {
 | |
|       assert(SubExpr->getType()->isIntegerType() && 
 | |
|              "Unexpected imaginary literal.");
 | |
| 
 | |
|       llvm::APSInt Result;
 | |
|       if (!EvaluateInteger(SubExpr, Result, Info))
 | |
|         return APValue();
 | |
|       
 | |
|       llvm::APSInt Zero(Result.getBitWidth(), !Result.isSigned());
 | |
|       Zero = 0;
 | |
|       return APValue(Zero, Result);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   APValue VisitCastExpr(CastExpr *E) {
 | |
|     Expr* SubExpr = E->getSubExpr();
 | |
|     QualType EltType = E->getType()->getAsComplexType()->getElementType();
 | |
|     QualType SubType = SubExpr->getType();
 | |
| 
 | |
|     if (SubType->isRealFloatingType()) {
 | |
|       APFloat Result(0.0);
 | |
| 
 | |
|       if (!EvaluateFloat(SubExpr, Result, Info))
 | |
|         return APValue();
 | |
| 
 | |
|       if (EltType->isRealFloatingType()) {
 | |
|         Result = HandleFloatToFloatCast(EltType, SubType, Result, Info.Ctx);
 | |
|         return APValue(Result, 
 | |
|                        APFloat(Result.getSemantics(), APFloat::fcZero, false));
 | |
|       } else {
 | |
|         llvm::APSInt IResult;
 | |
|         IResult = HandleFloatToIntCast(EltType, SubType, Result, Info.Ctx);
 | |
|         llvm::APSInt Zero(IResult.getBitWidth(), !IResult.isSigned());
 | |
|         Zero = 0;
 | |
|         return APValue(IResult, Zero);
 | |
|       }
 | |
|     } else if (SubType->isIntegerType()) {
 | |
|       APSInt Result;
 | |
| 
 | |
|       if (!EvaluateInteger(SubExpr, Result, Info))
 | |
|         return APValue();
 | |
| 
 | |
|       if (EltType->isRealFloatingType()) {
 | |
|         APFloat FResult =
 | |
|             HandleIntToFloatCast(EltType, SubType, Result, Info.Ctx);
 | |
|         return APValue(FResult, 
 | |
|                        APFloat(FResult.getSemantics(), APFloat::fcZero, false));
 | |
|       } else {
 | |
|         Result = HandleIntToIntCast(EltType, SubType, Result, Info.Ctx);
 | |
|         llvm::APSInt Zero(Result.getBitWidth(), !Result.isSigned());
 | |
|         Zero = 0;
 | |
|         return APValue(Result, Zero);
 | |
|       }
 | |
|     } else if (const ComplexType *CT = SubType->getAsComplexType()) {
 | |
|       APValue Src;
 | |
| 
 | |
|       if (!EvaluateComplex(SubExpr, Src, Info))
 | |
|         return APValue();
 | |
| 
 | |
|       QualType SrcType = CT->getElementType();
 | |
| 
 | |
|       if (Src.isComplexFloat()) {
 | |
|         if (EltType->isRealFloatingType()) {
 | |
|           return APValue(HandleFloatToFloatCast(EltType, SrcType, 
 | |
|                                                 Src.getComplexFloatReal(),
 | |
|                                                 Info.Ctx),
 | |
|                          HandleFloatToFloatCast(EltType, SrcType, 
 | |
|                                                 Src.getComplexFloatImag(),
 | |
|                                                 Info.Ctx));
 | |
|         } else {
 | |
|           return APValue(HandleFloatToIntCast(EltType, SrcType,
 | |
|                                               Src.getComplexFloatReal(),
 | |
|                                               Info.Ctx),
 | |
|                          HandleFloatToIntCast(EltType, SrcType, 
 | |
|                                               Src.getComplexFloatImag(),
 | |
|                                               Info.Ctx)); 
 | |
|         }
 | |
|       } else {
 | |
|         assert(Src.isComplexInt() && "Invalid evaluate result.");
 | |
|         if (EltType->isRealFloatingType()) {
 | |
|           return APValue(HandleIntToFloatCast(EltType, SrcType, 
 | |
|                                               Src.getComplexIntReal(),
 | |
|                                               Info.Ctx),
 | |
|                          HandleIntToFloatCast(EltType, SrcType, 
 | |
|                                               Src.getComplexIntImag(),
 | |
|                                               Info.Ctx));
 | |
|         } else {
 | |
|           return APValue(HandleIntToIntCast(EltType, SrcType,
 | |
|                                             Src.getComplexIntReal(),
 | |
|                                             Info.Ctx),
 | |
|                          HandleIntToIntCast(EltType, SrcType, 
 | |
|                                             Src.getComplexIntImag(),
 | |
|                                             Info.Ctx)); 
 | |
|         }
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     // FIXME: Handle more casts.
 | |
|     return APValue();
 | |
|   }
 | |
|   
 | |
|   APValue VisitBinaryOperator(const BinaryOperator *E);
 | |
|   APValue VisitChooseExpr(const ChooseExpr *E)
 | |
|     { return Visit(E->getChosenSubExpr(Info.Ctx)); }
 | |
|   APValue VisitUnaryExtension(const UnaryOperator *E)
 | |
|     { return Visit(E->getSubExpr()); }
 | |
|   // FIXME Missing: unary +/-/~, binary div, ImplicitValueInitExpr,
 | |
|   //                conditional ?:, comma
 | |
| };
 | |
| } // end anonymous namespace
 | |
| 
 | |
| static bool EvaluateComplex(const Expr *E, APValue &Result, EvalInfo &Info)
 | |
| {
 | |
|   Result = ComplexExprEvaluator(Info).Visit(const_cast<Expr*>(E));
 | |
|   assert((!Result.isComplexFloat() ||
 | |
|           (&Result.getComplexFloatReal().getSemantics() == 
 | |
|            &Result.getComplexFloatImag().getSemantics())) && 
 | |
|          "Invalid complex evaluation.");
 | |
|   return Result.isComplexFloat() || Result.isComplexInt();
 | |
| }
 | |
| 
 | |
| APValue ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E)
 | |
| {
 | |
|   APValue Result, RHS;
 | |
|   
 | |
|   if (!EvaluateComplex(E->getLHS(), Result, Info))
 | |
|     return APValue();
 | |
|   
 | |
|   if (!EvaluateComplex(E->getRHS(), RHS, Info))
 | |
|     return APValue();
 | |
| 
 | |
|   assert(Result.isComplexFloat() == RHS.isComplexFloat() &&
 | |
|          "Invalid operands to binary operator.");
 | |
|   switch (E->getOpcode()) {
 | |
|   default: return APValue();
 | |
|   case BinaryOperator::Add:
 | |
|     if (Result.isComplexFloat()) {
 | |
|       Result.getComplexFloatReal().add(RHS.getComplexFloatReal(),
 | |
|                                        APFloat::rmNearestTiesToEven);
 | |
|       Result.getComplexFloatImag().add(RHS.getComplexFloatImag(),
 | |
|                                        APFloat::rmNearestTiesToEven);
 | |
|     } else {
 | |
|       Result.getComplexIntReal() += RHS.getComplexIntReal();
 | |
|       Result.getComplexIntImag() += RHS.getComplexIntImag();
 | |
|     }
 | |
|     break;
 | |
|   case BinaryOperator::Sub:
 | |
|     if (Result.isComplexFloat()) {
 | |
|       Result.getComplexFloatReal().subtract(RHS.getComplexFloatReal(),
 | |
|                                             APFloat::rmNearestTiesToEven);
 | |
|       Result.getComplexFloatImag().subtract(RHS.getComplexFloatImag(),
 | |
|                                             APFloat::rmNearestTiesToEven);
 | |
|     } else {
 | |
|       Result.getComplexIntReal() -= RHS.getComplexIntReal();
 | |
|       Result.getComplexIntImag() -= RHS.getComplexIntImag();
 | |
|     }
 | |
|     break;
 | |
|   case BinaryOperator::Mul:
 | |
|     if (Result.isComplexFloat()) {
 | |
|       APValue LHS = Result;
 | |
|       APFloat &LHS_r = LHS.getComplexFloatReal();
 | |
|       APFloat &LHS_i = LHS.getComplexFloatImag();
 | |
|       APFloat &RHS_r = RHS.getComplexFloatReal();
 | |
|       APFloat &RHS_i = RHS.getComplexFloatImag();
 | |
|       
 | |
|       APFloat Tmp = LHS_r;
 | |
|       Tmp.multiply(RHS_r, APFloat::rmNearestTiesToEven);
 | |
|       Result.getComplexFloatReal() = Tmp;
 | |
|       Tmp = LHS_i;
 | |
|       Tmp.multiply(RHS_i, APFloat::rmNearestTiesToEven);
 | |
|       Result.getComplexFloatReal().subtract(Tmp, APFloat::rmNearestTiesToEven);
 | |
| 
 | |
|       Tmp = LHS_r;
 | |
|       Tmp.multiply(RHS_i, APFloat::rmNearestTiesToEven);
 | |
|       Result.getComplexFloatImag() = Tmp;
 | |
|       Tmp = LHS_i;
 | |
|       Tmp.multiply(RHS_r, APFloat::rmNearestTiesToEven);
 | |
|       Result.getComplexFloatImag().add(Tmp, APFloat::rmNearestTiesToEven);
 | |
|     } else {
 | |
|       APValue LHS = Result;
 | |
|       Result.getComplexIntReal() = 
 | |
|         (LHS.getComplexIntReal() * RHS.getComplexIntReal() -
 | |
|          LHS.getComplexIntImag() * RHS.getComplexIntImag());
 | |
|       Result.getComplexIntImag() = 
 | |
|         (LHS.getComplexIntReal() * RHS.getComplexIntImag() +
 | |
|          LHS.getComplexIntImag() * RHS.getComplexIntReal());
 | |
|     }
 | |
|     break;
 | |
|   }
 | |
| 
 | |
|   return Result;
 | |
| }
 | |
| 
 | |
| //===----------------------------------------------------------------------===//
 | |
| // Top level Expr::Evaluate method.
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| /// Evaluate - Return true if this is a constant which we can fold using
 | |
| /// any crazy technique (that has nothing to do with language standards) that
 | |
| /// we want to.  If this function returns true, it returns the folded constant
 | |
| /// in Result.
 | |
| bool Expr::Evaluate(EvalResult &Result, ASTContext &Ctx) const {
 | |
|   EvalInfo Info(Ctx, Result);
 | |
| 
 | |
|   if (getType()->isVectorType()) {
 | |
|     if (!EvaluateVector(this, Result.Val, Info))
 | |
|       return false;
 | |
|   } else if (getType()->isIntegerType()) {
 | |
|     if (!IntExprEvaluator(Info, Result.Val).Visit(const_cast<Expr*>(this)))
 | |
|       return false;
 | |
|   } else if (getType()->hasPointerRepresentation()) {
 | |
|     if (!EvaluatePointer(this, Result.Val, Info))
 | |
|       return false;
 | |
|   } else if (getType()->isRealFloatingType()) {
 | |
|     llvm::APFloat f(0.0);
 | |
|     if (!EvaluateFloat(this, f, Info))
 | |
|       return false;
 | |
|     
 | |
|     Result.Val = APValue(f);
 | |
|   } else if (getType()->isAnyComplexType()) {
 | |
|     if (!EvaluateComplex(this, Result.Val, Info))
 | |
|       return false;
 | |
|   } else
 | |
|     return false;
 | |
| 
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| bool Expr::EvaluateAsLValue(EvalResult &Result, ASTContext &Ctx) const {
 | |
|   EvalInfo Info(Ctx, Result);
 | |
| 
 | |
|   return EvaluateLValue(this, Result.Val, Info) && !Result.HasSideEffects;
 | |
| }
 | |
| 
 | |
| /// isEvaluatable - Call Evaluate to see if this expression can be constant
 | |
| /// folded, but discard the result.
 | |
| bool Expr::isEvaluatable(ASTContext &Ctx) const {
 | |
|   EvalResult Result;
 | |
|   return Evaluate(Result, Ctx) && !Result.HasSideEffects;
 | |
| }
 | |
| 
 | |
| APSInt Expr::EvaluateAsInt(ASTContext &Ctx) const {
 | |
|   EvalResult EvalResult;
 | |
|   bool Result = Evaluate(EvalResult, Ctx);
 | |
|   Result = Result;
 | |
|   assert(Result && "Could not evaluate expression");
 | |
|   assert(EvalResult.Val.isInt() && "Expression did not evaluate to integer");
 | |
| 
 | |
|   return EvalResult.Val.getInt();
 | |
| }
 |